diff --git a/CMakeLists.txt b/CMakeLists.txt
index f7baae90a68..91a9dae6a66 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -158,6 +158,10 @@ if(NOT QT_BUILD_STANDALONE_TESTS)
         _qt_internal_create_global_android_targets()
     endif()
 
+    if(OHOS)
+        include(src/corelib/Qt6OpenHarmonyMacros.cmake)
+    endif()
+
     if(WASM)
         # Needed when building for WebAssembly.
         include(cmake/QtWasmHelpers.cmake)
diff --git a/cmake/QtAutoDetectHelpers.cmake b/cmake/QtAutoDetectHelpers.cmake
index e226845fa4e..790c2f1c855 100644
--- a/cmake/QtAutoDetectHelpers.cmake
+++ b/cmake/QtAutoDetectHelpers.cmake
@@ -151,6 +151,92 @@ function(qt_auto_detect_android)
     endif()
 endfunction()
 
+# for openharmony
+function(qt_auto_detect_openharmony)
+    if(DEFINED OPENHARMONY_SDK_ROOT
+            OR DEFINED OHOS_ARCH
+            OR OHOS_SDK_VERSION)
+        set(openharmony_detected TRUE)
+    else()
+        set(openharmony_detected FALSE)
+    endif()
+
+    # Auto-detect toolchain file
+    if(NOT DEFINED CMAKE_TOOLCHAIN_FILE AND DEFINED OPENHARMONY_SDK_ROOT)
+        set(toolchain_file "${OPENHARMONY_SDK_ROOT}/native/build/cmake/ohos.toolchain.cmake")
+        if(EXISTS "${toolchain_file}")
+            message(STATUS "OpenHarmony toolchain file within NDK detected: ${toolchain_file}")
+            set(CMAKE_TOOLCHAIN_FILE "${toolchain_file}" CACHE STRING "")
+        else()
+            message(FATAL_ERROR "Cannot find the toolchain file '${toolchain_file}'. "
+                "Please specify the toolchain file with -DCMAKE_TOOLCHAIN_FILE=<file>.")
+        endif()
+    endif()
+
+    if(NOT DEFINED OHOS_SDK_VERSION AND DEFINED OPENHARMONY_SDK_ROOT)
+        set(json_file "${OPENHARMONY_SDK_ROOT}/../sdk-pkg.json")
+        if(EXISTS "${json_file}")
+            file(READ "${json_file}" json_content)
+            string(JSON api_version GET "${json_content}" data apiVersion)
+            if("${api_version}" STREQUAL "")
+                message(FATAL_ERROR "An OpenHarmony build was requested, but no OpenHarmony SDK version was "
+                    "specified nor detected.")
+            else()
+                set(OHOS_SDK_VERSION "${api_version}" CACHE STRING "")
+                message(STATUS "OpenHarmony SDK version detected: ${api_version}")
+            endif()
+        else()
+            file(READ "${OPENHARMONY_SDK_ROOT}/native/oh-uni-package.json" json_content)
+            string(JSON api_version GET "${json_content}" apiVersion)
+            if("${api_version}" STREQUAL "")
+                message(FATAL_ERROR "An OpenHarmony build was requested, but no OpenHarmony SDK version was "
+                    "specified nor detected.")
+            else()
+                set(OHOS_SDK_VERSION "${api_version}" CACHE STRING "")
+                message(STATUS "OpenHarmony SDK version detected: ${api_version}")
+            endif()
+        endif()
+        if(NOT DEFINED OHOS_SDK_VERSION)
+            message(FATAL_ERROR "An OpenHarmony build was requested, but no OpenHarmony SDK version was "
+                "specified nor detected.")
+        endif()
+    endif()
+
+    if(NOT DEFINED CMAKE_TOOLCHAIN_FILE AND openharmony_detected)
+        message(FATAL_ERROR "An OpenHarmony build was requested, but no OpenHarmony toolchain file was "
+            "specified nor detected.")
+    endif()
+
+
+    if(DEFINED CMAKE_TOOLCHAIN_FILE AND NOT DEFINED QT_AUTODETECT_OPENHARMONY)
+        # Peek into the toolchain file and check if it looks like an OpenHarmony one.
+        if(NOT openharmony_detected)
+            file(READ ${CMAKE_TOOLCHAIN_FILE} toolchain_file_content OFFSET 0 LIMIT 80)
+            string(FIND "${toolchain_file_content}" "Huawei Device Co., Ltd"
+                find_result REVERSE)
+            if(NOT ${find_result} EQUAL -1)
+                set(openharmony_detected TRUE)
+            endif()
+        endif()
+
+        if(openharmony_detected)
+            message(STATUS "OpenHarmony build detected, checking configuration defaults...")
+            if(NOT DEFINED OHOS_PLATFORM)
+                set(OHOS_PLATFORM "ohos" CACHE STRING "")
+            endif()
+            if(NOT DEFINED OHOS_STL)
+                set(OHOS_STL "c++_shared" CACHE STRING "")
+            endif()
+            if(DEFINED OHOS_ARCH)
+                set(CMAKE_OPENHARMONY_ARCH_ABI ${OHOS_ARCH} CACHE STRING "")
+            endif()
+        endif()
+        set(QT_AUTODETECT_OPENHARMONY ${openharmony_detected} CACHE STRING "")
+    elseif (QT_AUTODETECT_OPENHARMONY)
+        message(STATUS "OpenHarmony build detected")
+    endif()
+endfunction()
+
 function(qt_auto_detect_vcpkg)
     if(DEFINED ENV{VCPKG_ROOT})
         set(vcpkg_toolchain_file "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
@@ -458,6 +544,7 @@ macro(qt_internal_setup_autodetect)
     qt_auto_detect_macos_universal()
     qt_auto_detect_ios()
     qt_auto_detect_android()
+    qt_auto_detect_openharmony()
     qt_auto_detect_vcpkg()
     qt_auto_detect_pch()
     qt_auto_detect_wasm()
diff --git a/cmake/QtExecutableHelpers.cmake b/cmake/QtExecutableHelpers.cmake
index 1770271862b..798684ad162 100644
--- a/cmake/QtExecutableHelpers.cmake
+++ b/cmake/QtExecutableHelpers.cmake
@@ -81,7 +81,7 @@ function(qt_internal_add_executable name)
 
     qt_internal_add_repo_local_defines(${name})
 
-    if(ANDROID)
+    if(ANDROID OR OHOS)
         # The above call to qt_set_common_target_properties() sets the symbol
         # visibility to hidden, but for Android, we need main() to not be hidden
         # because it has to be loadable at runtime using dlopen().
diff --git a/cmake/QtFlagHandlingHelpers.cmake b/cmake/QtFlagHandlingHelpers.cmake
index cdbaaacad4d..ff61d479582 100644
--- a/cmake/QtFlagHandlingHelpers.cmake
+++ b/cmake/QtFlagHandlingHelpers.cmake
@@ -170,7 +170,7 @@ function(qt_internal_apply_gc_binaries target visibility)
             set(gc_sections_flag "-Wl,-dead_strip")
         elseif(SOLARIS)
             set(gc_sections_flag "-Wl,-z,ignore")
-        elseif(LINUX OR BSD OR WIN32 OR ANDROID)
+        elseif(LINUX OR BSD OR WIN32 OR ANDROID OR OHOS)
             set(gc_sections_flag "-Wl,--gc-sections")
         endif()
 
diff --git a/cmake/QtInternalTargets.cmake b/cmake/QtInternalTargets.cmake
index b5831659603..04e565245b3 100644
--- a/cmake/QtInternalTargets.cmake
+++ b/cmake/QtInternalTargets.cmake
@@ -66,6 +66,11 @@ function(qt_internal_set_warnings_are_errors_flags target target_scope)
         if (ANDROID)
             list(APPEND flags -Wno-error=literal-suffix)
         endif()
+
+        if(OHOS)
+            list(APPEND flags -Wno-error=literal-suffix)
+            list(APPEND flags -Wno-error=c++20-extensions)
+        endif()
     elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
         # Only enable for versions of MSVC that are known to work
         # 1939 is Visual Studio 2022 version 17.0
diff --git a/cmake/QtMkspecHelpers.cmake b/cmake/QtMkspecHelpers.cmake
index cd08daa2c44..4798f4035d2 100644
--- a/cmake/QtMkspecHelpers.cmake
+++ b/cmake/QtMkspecHelpers.cmake
@@ -48,6 +48,8 @@ macro(qt_internal_setup_platform_definitions_and_mkspec)
         elseif(CLANG)
             set(QT_DEFAULT_MKSPEC linux-clang)
         endif()
+    elseif(OHOS)
+        set(QT_DEFAULT_MKSPEC ohos-clang)
     elseif(ANDROID)
         if(GCC)
             set(QT_DEFAULT_MKSPEC android-g++)
diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake
index 0b42991e243..73a414a60e4 100644
--- a/cmake/QtModuleHelpers.cmake
+++ b/cmake/QtModuleHelpers.cmake
@@ -327,13 +327,21 @@ function(qt_internal_add_module target)
     endif()
 
     if(NOT arg_HEADER_MODULE)
-        set_target_properties(${target} PROPERTIES
-            LIBRARY_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}"
-            RUNTIME_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_BINDIR}"
-            ARCHIVE_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}"
-            VERSION ${PROJECT_VERSION}
-            SOVERSION ${PROJECT_VERSION_MAJOR}
-            )
+        if(OHOS)
+            set_target_properties(${target} PROPERTIES
+                LIBRARY_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}"
+                RUNTIME_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_BINDIR}"
+                ARCHIVE_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}"
+                )
+        else()
+            set_target_properties(${target} PROPERTIES
+                LIBRARY_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}"
+                RUNTIME_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_BINDIR}"
+                ARCHIVE_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}"
+                VERSION ${PROJECT_VERSION}
+                SOVERSION ${PROJECT_VERSION_MAJOR}
+                )
+        endif()
         qt_set_target_info_properties(${target} ${ARGN})
         qt_handle_multi_config_output_dirs("${target}")
 
diff --git a/cmake/QtPlatformSupport.cmake b/cmake/QtPlatformSupport.cmake
index e20a5e153d4..a0ba9479709 100644
--- a/cmake/QtPlatformSupport.cmake
+++ b/cmake/QtPlatformSupport.cmake
@@ -11,6 +11,7 @@ endfunction()
 
 qt_set01(LINUX CMAKE_SYSTEM_NAME STREQUAL "Linux")
 qt_set01(HPUX CMAKE_SYSTEM_NAME STREQUAL "HPUX")
+qt_set01(OHOS CMAKE_SYSTEM_NAME STREQUAL "OHOS")
 qt_set01(ANDROID CMAKE_SYSTEM_NAME STREQUAL "Android")  # FIXME: How to identify this?
 qt_set01(INTEGRITY CMAKE_SYSTEM_NAME STREQUAL "Integrity") # FIXME: How to identify this?
 qt_set01(VXWORKS CMAKE_SYSTEM_NAME STREQUAL "VxWorks") # FIXME: How to identify this?
diff --git a/cmake/QtPluginHelpers.cmake b/cmake/QtPluginHelpers.cmake
index bc0f651b99c..f3f21bfc40a 100644
--- a/cmake/QtPluginHelpers.cmake
+++ b/cmake/QtPluginHelpers.cmake
@@ -135,7 +135,11 @@ function(qt_internal_add_plugin target)
     # Make sure the Qt6 plugin library names are like they were in Qt5 qmake land.
     # Whereas the Qt6 CMake target names are like the Qt5 CMake target names.
     get_target_property(output_name ${target} OUTPUT_NAME)
-    set_property(TARGET "${target}" PROPERTY OUTPUT_NAME "${output_name}${QT_LIBINFIX}")
+    if(OHOS)
+        set_property(TARGET "${target}" PROPERTY OUTPUT_NAME "plugins_${plugin_type}_${output_name}${QT_LIBINFIX}")
+    else()
+        set_property(TARGET "${target}" PROPERTY OUTPUT_NAME "${output_name}${QT_LIBINFIX}")
+    endif()
 
     # Add a custom target with the Qt5 qmake name for a more user friendly ninja experience.
     if(arg_OUTPUT_NAME AND NOT TARGET "${output_name}")
diff --git a/cmake/QtPriHelpers.cmake b/cmake/QtPriHelpers.cmake
index f1d45cdcf6c..499b7d3d56d 100644
--- a/cmake/QtPriHelpers.cmake
+++ b/cmake/QtPriHelpers.cmake
@@ -792,6 +792,10 @@ QT_PATCH_VERSION = ${PROJECT_VERSION_PATCH}
         list(APPEND extra_statements "QT_ARCHS = ${architectures}")
     endif()
 
+    if(OHOS)
+        list(APPEND extra_statements "OHOS_SDK_VERSION = ${OHOS_SDK_VERSION}")
+    endif()
+
     list(APPEND extra_statements "QT_EDITION = Open Source")
 
     if(WASM)
diff --git a/cmake/QtProcessConfigureArgs.cmake b/cmake/QtProcessConfigureArgs.cmake
index d1dee1c0db8..642357afc46 100644
--- a/cmake/QtProcessConfigureArgs.cmake
+++ b/cmake/QtProcessConfigureArgs.cmake
@@ -901,6 +901,16 @@ endif()
 translate_string_input(android-javac-source QT_ANDROID_JAVAC_SOURCE)
 translate_string_input(android-javac-target QT_ANDROID_JAVAC_TARGET)
 
+#for openharmony
+translate_path_input(openharmony-sdk OPENHARMONY_SDK_ROOT)
+translate_path_input(openharmony-platform OHOS_SDK_VERSION)
+if(DEFINED INPUT_openharmony-abis)
+    if(INPUT_openharmony-abis MATCHES ",")
+        qtConfAddError("The -openharmony-abis option cannot handle more than one ABI "
+            "when building with CMake.")
+    endif()
+    translate_string_input(openharmony-abis OHOS_ARCH)
+endif()
 # FIXME: config_help.txt says -sdk should apply to macOS as well.
 translate_string_input(sdk QT_UIKIT_SDK)
 if(DEFINED INPUT_sdk OR (DEFINED INPUT_xplatform AND INPUT_xplatform STREQUAL "macx-ios-clang")
diff --git a/cmake/QtRpathHelpers.cmake b/cmake/QtRpathHelpers.cmake
index a8e3bb5fe4e..a9c9d0a21b6 100644
--- a/cmake/QtRpathHelpers.cmake
+++ b/cmake/QtRpathHelpers.cmake
@@ -77,7 +77,7 @@ endfunction()
 #
 # QT_DISABLE_RPATH can be set to disable embedding any Qt specific rpaths.
 function(qt_apply_rpaths)
-    # No rpath support for win32 and android.
+    # No rpath support for win32 and android and openharmony.
     if(WIN32 OR ANDROID)
         return()
     endif()
diff --git a/cmake/QtSeparateDebugInfo.cmake b/cmake/QtSeparateDebugInfo.cmake
index 61f62207fab..29040dee526 100644
--- a/cmake/QtSeparateDebugInfo.cmake
+++ b/cmake/QtSeparateDebugInfo.cmake
@@ -101,6 +101,7 @@ function(qt_internal_generate_binary_strip_wrapper)
     if((UNIX OR MINGW)
             AND NOT APPLE
             AND NOT ANDROID
+            AND NOT OHOS
             AND CMAKE_STRIP)
 
         # To make reconfiguration more robust when QT_INTERNAL_STRIP_SUPPORTS_KEEP_SECTION is
diff --git a/cmake/configure-cmake-mapping.md b/cmake/configure-cmake-mapping.md
index 6fad45d08fa..30c035b0c81 100644
--- a/cmake/configure-cmake-mapping.md
+++ b/cmake/configure-cmake-mapping.md
@@ -93,6 +93,10 @@ The following table describes the mapping of configure options to CMake argument
 | -sdk <sdk>                            | -DQT_UIKIT_SDK=<value>                            | Should be provided a value like 'iphoneos' or 'iphonesimulator' |
 |                                       |                                                   | If no value is provided, a simulator_and_device build is        |
 |                                       |                                                   | assumed.                                                        |
+| -openharmony-sdk <path>               | -DOPENHARMONY_SDK_ROOT=<path>                     |   
+| -openharmony-abis <abi_1>,...,<abi_n> | -DOHOS_ARCH=<abi_1>                               |  
+| -openharmony-platform 17              | -DOHOS_SDK_VERSION=17                             |  
+|                                       |                                                   |
 | -android-sdk <path>                   | -DANDROID_SDK_ROOT=<path>                         |                                                                 |
 | -android-ndk <path>                   | -DCMAKE_TOOLCHAIN_FILE=<toolchain file in NDK>    |                                                                 |
 | -android-ndk-platform android-23      | -DANDROID_PLATFORM=android-23                     |                                                                 |
diff --git a/config_help.txt b/config_help.txt
index 5169b2a91ba..9df3a69c1eb 100644
--- a/config_help.txt
+++ b/config_help.txt
@@ -174,6 +174,10 @@ Build environment:
                          should be one of the available SDKs as listed by
                          'xcodebuild -showsdks'.
 
+  -openharmony-sdk path .... Set OpenHarmony SDK root path [$OPENHARMONY_SDK_ROOT]
+  -openharmony-abis .......  Only one ABI can be specified, default is: arm64-v8a
+  -openharmony-platform  .... Set OpenHarmony SDK version [$OHOS_SDK_VERSION]
+
   -android-sdk path .... Set Android SDK root path [$ANDROID_SDK_ROOT]
   -android-ndk path .... Set Android NDK root path [$ANDROID_NDK_ROOT]
   -android-ndk-platform  Set Android platform
diff --git a/configure.cmake b/configure.cmake
index 9a242b3cbdb..b66c397d9d6 100644
--- a/configure.cmake
+++ b/configure.cmake
@@ -1354,6 +1354,11 @@ qt_extra_definition("QT_VERSION_MAJOR" ${PROJECT_VERSION_MAJOR} PUBLIC)
 qt_extra_definition("QT_VERSION_MINOR" ${PROJECT_VERSION_MINOR} PUBLIC)
 qt_extra_definition("QT_VERSION_PATCH" ${PROJECT_VERSION_PATCH} PUBLIC)
 
+if(OHOS)
+    qt_extra_definition("OHOS_SDK_VERSION" ${OHOS_SDK_VERSION} PUBLIC)
+    qt_extra_definition("NAPI_DISABLE_CPP_EXCEPTIONS" "1" PUBLIC)
+endif()
+
 qt_extra_definition("QT_COPYRIGHT" \"${QT_COPYRIGHT}\" PRIVATE)
 qt_extra_definition("QT_COPYRIGHT_YEAR" \"${QT_COPYRIGHT_YEAR}\" PRIVATE)
 
diff --git a/mkspecs/ohos-clang/qmake.conf b/mkspecs/ohos-clang/qmake.conf
new file mode 100644
index 00000000000..8d0b83601fa
--- /dev/null
+++ b/mkspecs/ohos-clang/qmake.conf
@@ -0,0 +1,87 @@
+# qmake configuration for building with ohos-clang
+MAKEFILE_GENERATOR      = UNIX
+QMAKE_PLATFORM          = openharmony
+QMAKE_COMPILER          = clang
+
+CONFIG                 += unversioned_soname unversioned_libname plugin_with_soname android_deployment_settings
+
+include(../common/linux.conf)
+include(../common/gcc-base-unix.conf)
+include(../common/clang.conf)
+
+load(device_config)
+
+NDK_ROOT = $$(OPENHARMONY_NDK_ROOT)
+!exists($$NDK_ROOT): error("You need to set the OPENHARMONY_NDK_ROOT environment variable to point to your OpenHarmony NDK.")
+MESSAGE($${NDK_ROOT})
+ALL_OPENHARMONY_ABIS = $$(ALL_OPENHARMONY_ABIS)
+isEmpty(ALL_OPENHARMONY_ABIS): ALL_OPENHARMONY_ABIS = $$DEFAULT_OPENHARMONY_ABIS
+isEmpty(ALL_OPENHARMONY_ABIS): ALL_OPENHARMONY_ABIS = arm64-v8a armeabi-v7a x86_64 x86
+
+NDK_LLVM_PATH    = $$NDK_ROOT/native/llvm
+QMAKE_CC         = $$NDK_LLVM_PATH/bin/clang
+QMAKE_CXX        = $$NDK_LLVM_PATH/bin/clang++
+QMAKE_LINK       = $$QMAKE_CXX
+QMAKE_OBJCOPY    = $$NDK_LLVM_PATH/bin/llvm-objcopy
+QMAKE_AR         = $$NDK_LLVM_PATH/bin/llvm-ar cqs
+QMAKE_OBJCOPY    = $$NDK_LLVM_PATH/bin/llvm-objcopy
+QMAKE_NM         = $$NDK_LLVM_PATH/bin/llvm-nm -P
+
+QMAKE_CFLAGS_OPTIMIZE      = -Oz
+QMAKE_CFLAGS_OPTIMIZE_FULL = -Oz
+
+QMAKE_CFLAGS_WARN_ON    = -Wall -W
+QMAKE_CFLAGS_WARN_OFF   =
+QMAKE_CFLAGS_SHLIB      = -fPIC
+QMAKE_CFLAGS_YACC       = -Wno-unused -Wno-parentheses
+QMAKE_CFLAGS_THREAD     = -D_REENTRANT
+QMAKE_CFLAGS_HIDESYMS   = -fvisibility=hidden
+QMAKE_CFLAGS_NEON       = -mfpu=neon
+
+QMAKE_LFLAGS_APP        = -Wl,--build-id=sha1 -Wl,--no-undefined -Wl,-z,noexecstack -shared
+QMAKE_LFLAGS_SHLIB      = -Wl,--build-id=sha1 -Wl,--no-undefined -Wl,-z,noexecstack -shared
+QMAKE_LFLAGS_PLUGIN     = $$QMAKE_LFLAGS_SHLIB
+QMAKE_LFLAGS_NOUNDEF    = -Wl,--no-undefined
+QMAKE_LFLAGS_RPATH      = -Wl,-rpath=
+QMAKE_LFLAGS_RPATHLINK  = -Wl,-rpath-link=
+
+equals(QMAKE_HOST.os, Windows) {
+    QMAKE_LINK_OBJECT_MAX = 10
+}
+
+QMAKE_LIBS_X11          =
+QMAKE_LIBS_THREAD       =
+QMAKE_LIBS_OPENGL       =
+QMAKE_INCDIR_POST       =
+QMAKE_INCDIR_X11        =
+QMAKE_LIBDIR_X11        =
+QMAKE_INCDIR_OPENGL     =
+QMAKE_LIBDIR_OPENGL     =
+
+OPENHARMONY_USE_LLVM = true
+
+armeabi-v7a.sdk = armeabi-v7a
+armeabi-v7a.target = armeabi-v7a
+armeabi-v7a.dir_affix = armeabi-v7a
+armeabi-v7a.CONFIG = armeabi-v7a
+armeabi-v7a.deployment_identifier = armeabi-v7a
+
+arm64-v8a.sdk = arm64-v8a
+arm64-v8a.target = arm64-v8a
+arm64-v8a.dir_affix = arm64-v8a
+arm64-v8a.CONFIG = arm64-v8a
+arm64-v8a.deployment_identifier = arm64-v8a
+
+x86.sdk = x86
+x86.target = x86
+x86.dir_affix = x86
+x86.CONFIG = x86
+x86.deployment_identifier = x86
+
+x86_64.sdk = x86_64
+x86_64.target = x86_64
+x86_64.dir_affix = x86_64
+x86_64.CONFIG = x86_64
+x86_64.deployment_identifier = x86_64
+
+load(qt_config)
diff --git a/mkspecs/ohos-clang/qplatformdefs.h b/mkspecs/ohos-clang/qplatformdefs.h
new file mode 100644
index 00000000000..6f82bd0acc6
--- /dev/null
+++ b/mkspecs/ohos-clang/qplatformdefs.h
@@ -0,0 +1,141 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QPLATFORMDEFS_H
+#define QPLATFORMDEFS_H
+
+// Get Qt defines/settings
+
+#include "qglobal.h"
+
+// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs
+
+// 1) need to reset default environment if _BSD_SOURCE is defined
+// 2) need to specify POSIX thread interfaces explicitly in glibc 2.0
+// 3) it seems older glibc need this to include the X/Open stuff
+
+#include <unistd.h>
+
+// We are hot - unistd.h should have turned on the specific APIs we requested
+
+#include <features.h>
+#include <pthread.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <dlfcn.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/ipc.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#ifndef _GNU_SOURCE
+#  define _GNU_SOURCE
+#endif
+
+#ifdef QT_LARGEFILE_SUPPORT
+#define QT_STATBUF              struct stat64
+#define QT_STATBUF4TSTAT        struct stat64
+#define QT_STAT                 ::stat64
+#define QT_FSTAT                ::fstat64
+#define QT_LSTAT                ::lstat64
+#define QT_OPEN                 ::open64
+#define QT_TRUNCATE             ::truncate64
+#define QT_FTRUNCATE            ::ftruncate64
+#define QT_LSEEK                ::lseek64
+#else
+#define QT_STATBUF              struct stat
+#define QT_STATBUF4TSTAT        struct stat
+#define QT_STAT                 ::stat
+#define QT_FSTAT                ::fstat
+#define QT_LSTAT                ::lstat
+#define QT_OPEN                 ::open
+#define QT_TRUNCATE             ::truncate
+#define QT_FTRUNCATE            ::ftruncate
+#define QT_LSEEK                ::lseek
+#endif
+
+#ifdef QT_LARGEFILE_SUPPORT
+#define QT_FOPEN                ::fopen64
+#define QT_FSEEK                ::fseeko64
+#define QT_FTELL                ::ftello64
+#define QT_FGETPOS              ::fgetpos64
+#define QT_FSETPOS              ::fsetpos64
+#define QT_MMAP                 ::mmap64
+#define QT_FPOS_T               fpos64_t
+#define QT_OFF_T                off64_t
+#else
+#define QT_FOPEN                ::fopen
+#define QT_FSEEK                ::fseek
+#define QT_FTELL                ::ftell
+#define QT_FGETPOS              ::fgetpos
+#define QT_FSETPOS              ::fsetpos
+#define QT_MMAP                 ::mmap
+#define QT_FPOS_T               fpos_t
+#define QT_OFF_T                long
+#endif
+
+#define QT_STAT_REG             S_IFREG
+#define QT_STAT_DIR             S_IFDIR
+#define QT_STAT_MASK            S_IFMT
+#define QT_STAT_LNK             S_IFLNK
+#define QT_SOCKET_CONNECT       ::connect
+#define QT_SOCKET_BIND          ::bind
+#define QT_FILENO               fileno
+#define QT_CLOSE                ::close
+#define QT_READ                 ::read
+#define QT_WRITE                ::write
+#define QT_ACCESS               ::access
+#define QT_GETCWD               ::getcwd
+#define QT_CHDIR                ::chdir
+#define QT_MKDIR                ::mkdir
+#define QT_RMDIR                ::rmdir
+#define QT_OPEN_LARGEFILE       O_LARGEFILE
+#define QT_OPEN_RDONLY          O_RDONLY
+#define QT_OPEN_WRONLY          O_WRONLY
+#define QT_OPEN_RDWR            O_RDWR
+#define QT_OPEN_CREAT           O_CREAT
+#define QT_OPEN_TRUNC           O_TRUNC
+#define QT_OPEN_APPEND          O_APPEND
+#define QT_OPEN_EXCL            O_EXCL
+
+// Directory iteration
+#define QT_DIR                  DIR
+
+#define QT_OPENDIR              ::opendir
+#define QT_CLOSEDIR             ::closedir
+
+#if defined(QT_LARGEFILE_SUPPORT) \
+        && defined(QT_USE_XOPEN_LFS_EXTENSIONS) \
+        && !defined(QT_NO_READDIR64)
+#define QT_DIRENT               struct dirent64
+#define QT_READDIR              ::readdir64
+#define QT_READDIR_R            ::readdir64_r
+#else
+#define QT_DIRENT               struct dirent
+#define QT_READDIR              ::readdir
+#define QT_READDIR_R            ::readdir_r
+#endif
+
+#define QT_SOCKET_CONNECT       ::connect
+#define QT_SOCKET_BIND          ::bind
+
+
+#define QT_SIGNAL_RETTYPE       void
+#define QT_SIGNAL_ARGS          int
+#define QT_SIGNAL_IGNORE        SIG_IGN
+
+#define QT_SOCKLEN_T            socklen_t
+
+#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
+#define QT_SNPRINTF             ::snprintf
+#define QT_VSNPRINTF            ::vsnprintf
+#endif
+
+#endif // QPLATFORMDEFS_H
diff --git a/qt_cmdline.cmake b/qt_cmdline.cmake
index e0d8676f364..3df13ff79cf 100644
--- a/qt_cmdline.cmake
+++ b/qt_cmdline.cmake
@@ -30,6 +30,9 @@ qt_commandline_option(settingsdir TYPE string NAME sysconfdir)
 qt_commandline_option(sysconfdir TYPE string)
 qt_commandline_option(testsdir TYPE string)
 qt_commandline_option(translationdir TYPE string)
+qt_commandline_option(openharmony-sdk TYPE string)
+qt_commandline_option(openharmony-platform TYPE string)
+qt_commandline_option(openharmony-abis TYPE string)
 qt_commandline_option(android-arch TYPE string)
 qt_commandline_option(android-abis TYPE string)
 qt_commandline_option(android-ndk TYPE string)
diff --git a/src/3rdparty/node-addon-api/CMakeLists.txt b/src/3rdparty/node-addon-api/CMakeLists.txt
new file mode 100644
index 00000000000..ad1ead6fc58
--- /dev/null
+++ b/src/3rdparty/node-addon-api/CMakeLists.txt
@@ -0,0 +1,17 @@
+qt_internal_add_3rdparty_library(Napi
+    INTERFACE
+    SOURCES
+        napi.h
+        napi-inl.h
+        napi-inl-deprecated.h
+
+)
+
+qt_internal_add_sync_header_dependencies(Napi Core)
+
+qt_internal_add_3rdparty_header_module(NapiPrivate
+    EXTERNAL_HEADERS
+        napi.h
+        napi-inl.h
+        napi-inl-deprecated.h
+)
diff --git a/src/3rdparty/node-addon-api/napi-inl-deprecated.h b/src/3rdparty/node-addon-api/napi-inl-deprecated.h
new file mode 100644
index 00000000000..f19aca76bdc
--- /dev/null
+++ b/src/3rdparty/node-addon-api/napi-inl-deprecated.h
@@ -0,0 +1,192 @@
+#ifndef SRC_NAPI_INL_DEPRECATED_H_
+#define SRC_NAPI_INL_DEPRECATED_H_
+
+////////////////////////////////////////////////////////////////////////////////
+// PropertyDescriptor class
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename Getter>
+inline PropertyDescriptor
+PropertyDescriptor::Accessor(const char* utf8name,
+                             Getter getter,
+                             napi_property_attributes attributes,
+                             void* /*data*/) {
+  typedef details::CallbackData<Getter, Napi::Value> CbData;
+  // TODO: Delete when the function is destroyed
+  auto callbackData = new CbData({ getter, nullptr });
+
+  return PropertyDescriptor({
+    utf8name,
+    nullptr,
+    nullptr,
+    CbData::Wrapper,
+    nullptr,
+    nullptr,
+    attributes,
+    callbackData
+  });
+}
+
+template <typename Getter>
+inline PropertyDescriptor PropertyDescriptor::Accessor(const std::string& utf8name,
+                                                       Getter getter,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  return Accessor(utf8name.c_str(), getter, attributes, data);
+}
+
+template <typename Getter>
+inline PropertyDescriptor PropertyDescriptor::Accessor(napi_value name,
+                                                       Getter getter,
+                                                       napi_property_attributes attributes,
+                                                       void* /*data*/) {
+  typedef details::CallbackData<Getter, Napi::Value> CbData;
+  // TODO: Delete when the function is destroyed
+  auto callbackData = new CbData({ getter, nullptr });
+
+  return PropertyDescriptor({
+    nullptr,
+    name,
+    nullptr,
+    CbData::Wrapper,
+    nullptr,
+    nullptr,
+    attributes,
+    callbackData
+  });
+}
+
+template <typename Getter>
+inline PropertyDescriptor PropertyDescriptor::Accessor(Name name,
+                                                       Getter getter,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  napi_value nameValue = name;
+  return PropertyDescriptor::Accessor(nameValue, getter, attributes, data);
+}
+
+template <typename Getter, typename Setter>
+inline PropertyDescriptor PropertyDescriptor::Accessor(const char* utf8name,
+                                                       Getter getter,
+                                                       Setter setter,
+                                                       napi_property_attributes attributes,
+                                                       void* /*data*/) {
+  typedef details::AccessorCallbackData<Getter, Setter> CbData;
+  // TODO: Delete when the function is destroyed
+  auto callbackData = new CbData({ getter, setter, nullptr });
+
+  return PropertyDescriptor({
+    utf8name,
+    nullptr,
+    nullptr,
+    CbData::GetterWrapper,
+    CbData::SetterWrapper,
+    nullptr,
+    attributes,
+    callbackData
+  });
+}
+
+template <typename Getter, typename Setter>
+inline PropertyDescriptor PropertyDescriptor::Accessor(const std::string& utf8name,
+                                                       Getter getter,
+                                                       Setter setter,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  return Accessor(utf8name.c_str(), getter, setter, attributes, data);
+}
+
+template <typename Getter, typename Setter>
+inline PropertyDescriptor PropertyDescriptor::Accessor(napi_value name,
+                                                       Getter getter,
+                                                       Setter setter,
+                                                       napi_property_attributes attributes,
+                                                       void* /*data*/) {
+  typedef details::AccessorCallbackData<Getter, Setter> CbData;
+  // TODO: Delete when the function is destroyed
+  auto callbackData = new CbData({ getter, setter, nullptr });
+
+  return PropertyDescriptor({
+    nullptr,
+    name,
+    nullptr,
+    CbData::GetterWrapper,
+    CbData::SetterWrapper,
+    nullptr,
+    attributes,
+    callbackData
+  });
+}
+
+template <typename Getter, typename Setter>
+inline PropertyDescriptor PropertyDescriptor::Accessor(Name name,
+                                                       Getter getter,
+                                                       Setter setter,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  napi_value nameValue = name;
+  return PropertyDescriptor::Accessor(nameValue, getter, setter, attributes, data);
+}
+
+template <typename Callable>
+inline PropertyDescriptor PropertyDescriptor::Function(const char* utf8name,
+                                                       Callable cb,
+                                                       napi_property_attributes attributes,
+                                                       void* /*data*/) {
+  typedef decltype(cb(CallbackInfo(nullptr, nullptr))) ReturnType;
+  typedef details::CallbackData<Callable, ReturnType> CbData;
+  // TODO: Delete when the function is destroyed
+  auto callbackData = new CbData({ cb, nullptr });
+
+  return PropertyDescriptor({
+    utf8name,
+    nullptr,
+    CbData::Wrapper,
+    nullptr,
+    nullptr,
+    nullptr,
+    attributes,
+    callbackData
+  });
+}
+
+template <typename Callable>
+inline PropertyDescriptor PropertyDescriptor::Function(const std::string& utf8name,
+                                                       Callable cb,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  return Function(utf8name.c_str(), cb, attributes, data);
+}
+
+template <typename Callable>
+inline PropertyDescriptor PropertyDescriptor::Function(napi_value name,
+                                                       Callable cb,
+                                                       napi_property_attributes attributes,
+                                                       void* /*data*/) {
+  typedef decltype(cb(CallbackInfo(nullptr, nullptr))) ReturnType;
+  typedef details::CallbackData<Callable, ReturnType> CbData;
+  // TODO: Delete when the function is destroyed
+  auto callbackData = new CbData({ cb, nullptr });
+
+  return PropertyDescriptor({
+    nullptr,
+    name,
+    CbData::Wrapper,
+    nullptr,
+    nullptr,
+    nullptr,
+    attributes,
+    callbackData
+  });
+}
+
+template <typename Callable>
+inline PropertyDescriptor PropertyDescriptor::Function(Name name,
+                                                       Callable cb,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  napi_value nameValue = name;
+  return PropertyDescriptor::Function(nameValue, cb, attributes, data);
+}
+
+#endif // !SRC_NAPI_INL_DEPRECATED_H_
diff --git a/src/3rdparty/node-addon-api/napi-inl.h b/src/3rdparty/node-addon-api/napi-inl.h
new file mode 100644
index 00000000000..9f5ed4ff49d
--- /dev/null
+++ b/src/3rdparty/node-addon-api/napi-inl.h
@@ -0,0 +1,4097 @@
+#ifndef SRC_NAPI_INL_H_
+#define SRC_NAPI_INL_H_
+
+////////////////////////////////////////////////////////////////////////////////
+// N-API C++ Wrapper Classes
+//
+// Inline header-only implementations for "N-API" ABI-stable C APIs for Node.js.
+////////////////////////////////////////////////////////////////////////////////
+
+// Note: Do not include this file directly! Include "napi.h" instead.
+
+#include <cstring>
+#include <type_traits>
+
+namespace Napi {
+
+// Helpers to handle functions exposed from C++.
+namespace details {
+
+// Attach a data item to an object and delete it when the object gets
+// garbage-collected.
+// TODO: Replace this code with `napi_add_finalizer()` whenever it becomes
+// available on all supported versions of Node.js.
+template <typename FreeType>
+static inline napi_status AttachData(napi_env env,
+                                     napi_value obj,
+                                     FreeType* data) {
+  napi_value symbol, external;
+  napi_status status = napi_create_symbol(env, nullptr, &symbol);
+  if (status == napi_ok) {
+    status = napi_create_external(env,
+                              data,
+                              [](napi_env /*env*/, void* data, void* /*hint*/) {
+                                delete static_cast<FreeType*>(data);
+                              },
+                              nullptr,
+                              &external);
+    if (status == napi_ok) {
+      napi_property_descriptor desc = {
+        nullptr,
+        symbol,
+        nullptr,
+        nullptr,
+        nullptr,
+        external,
+        napi_default,
+        nullptr
+      };
+      status = napi_define_properties(env, obj, 1, &desc);
+    }
+  }
+  return status;
+}
+
+// For use in JS to C++ callback wrappers to catch any Napi::Error exceptions
+// and rethrow them as JavaScript exceptions before returning from the callback.
+template <typename Callable>
+inline napi_value WrapCallback(Callable callback) {
+#ifdef NAPI_CPP_EXCEPTIONS
+  try {
+    return callback();
+  } catch (const Error& e) {
+    e.ThrowAsJavaScriptException();
+    return nullptr;
+  }
+#else // NAPI_CPP_EXCEPTIONS
+  // When C++ exceptions are disabled, errors are immediately thrown as JS
+  // exceptions, so there is no need to catch and rethrow them here.
+  return callback();
+#endif // NAPI_CPP_EXCEPTIONS
+}
+
+template <typename Callable, typename Return>
+struct CallbackData {
+  static inline
+  napi_value Wrapper(napi_env env, napi_callback_info info) {
+    return details::WrapCallback([&] {
+      CallbackInfo callbackInfo(env, info);
+      CallbackData* callbackData =
+        static_cast<CallbackData*>(callbackInfo.Data());
+      callbackInfo.SetData(callbackData->data);
+      return callbackData->callback(callbackInfo);
+    });
+  }
+
+  Callable callback;
+  void* data;
+};
+
+template <typename Callable>
+struct CallbackData<Callable, void> {
+  static inline
+  napi_value Wrapper(napi_env env, napi_callback_info info) {
+    return details::WrapCallback([&] {
+      CallbackInfo callbackInfo(env, info);
+      CallbackData* callbackData =
+        static_cast<CallbackData*>(callbackInfo.Data());
+      callbackInfo.SetData(callbackData->data);
+      callbackData->callback(callbackInfo);
+      return nullptr;
+    });
+  }
+
+  Callable callback;
+  void* data;
+};
+
+template <typename T, typename Finalizer, typename Hint = void>
+struct FinalizeData {
+  static inline
+  void Wrapper(napi_env env, void* data, void* finalizeHint) {
+    FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
+    finalizeData->callback(Env(env), static_cast<T*>(data));
+    delete finalizeData;
+  }
+
+  static inline
+  void WrapperWithHint(napi_env env, void* data, void* finalizeHint) {
+    FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
+    finalizeData->callback(Env(env), static_cast<T*>(data), finalizeData->hint);
+    delete finalizeData;
+  }
+
+  Finalizer callback;
+  Hint* hint;
+};
+
+#if (NAPI_VERSION > 3)
+template <typename ContextType=void,
+          typename Finalizer=std::function<void(Env, void*, ContextType*)>,
+          typename FinalizerDataType=void>
+struct ThreadSafeFinalize {
+  static inline
+  void Wrapper(napi_env env, void* rawFinalizeData, void* /* rawContext */) {
+    if (rawFinalizeData == nullptr)
+      return;
+
+    ThreadSafeFinalize* finalizeData =
+        static_cast<ThreadSafeFinalize*>(rawFinalizeData);
+    finalizeData->callback(Env(env));
+    if (finalizeData->tsfn) {
+      *finalizeData->tsfn = nullptr;
+    }
+    delete finalizeData;
+  }
+
+  static inline
+  void FinalizeWrapperWithData(napi_env env,
+                               void* rawFinalizeData,
+                               void* /* rawContext */) {
+    if (rawFinalizeData == nullptr)
+      return;
+
+    ThreadSafeFinalize* finalizeData =
+        static_cast<ThreadSafeFinalize*>(rawFinalizeData);
+    finalizeData->callback(Env(env), finalizeData->data);
+    if (finalizeData->tsfn) {
+      *finalizeData->tsfn = nullptr;
+    }
+    delete finalizeData;
+  }
+
+  static inline
+  void FinalizeWrapperWithContext(napi_env env,
+                                  void* rawFinalizeData,
+                                  void* rawContext) {
+    if (rawFinalizeData == nullptr)
+      return;
+
+    ThreadSafeFinalize* finalizeData =
+        static_cast<ThreadSafeFinalize*>(rawFinalizeData);
+    finalizeData->callback(Env(env), static_cast<ContextType*>(rawContext));
+    if (finalizeData->tsfn) {
+      *finalizeData->tsfn = nullptr;
+    }
+    delete finalizeData;
+  }
+
+  static inline
+  void FinalizeFinalizeWrapperWithDataAndContext(napi_env env,
+                                         void* rawFinalizeData,
+                                         void* rawContext) {
+    if (rawFinalizeData == nullptr)
+      return;
+
+    ThreadSafeFinalize* finalizeData =
+        static_cast<ThreadSafeFinalize*>(rawFinalizeData);
+    finalizeData->callback(Env(env), finalizeData->data,
+        static_cast<ContextType*>(rawContext));
+    if (finalizeData->tsfn) {
+      *finalizeData->tsfn = nullptr;
+    }
+    delete finalizeData;
+  }
+
+  FinalizerDataType* data;
+  Finalizer callback;
+  napi_threadsafe_function* tsfn;
+};
+#endif
+
+template <typename Getter, typename Setter>
+struct AccessorCallbackData {
+  static inline
+  napi_value GetterWrapper(napi_env env, napi_callback_info info) {
+    return details::WrapCallback([&] {
+      CallbackInfo callbackInfo(env, info);
+      AccessorCallbackData* callbackData =
+        static_cast<AccessorCallbackData*>(callbackInfo.Data());
+      callbackInfo.SetData(callbackData->data);
+      return callbackData->getterCallback(callbackInfo);
+    });
+  }
+
+  static inline
+  napi_value SetterWrapper(napi_env env, napi_callback_info info) {
+    return details::WrapCallback([&] {
+      CallbackInfo callbackInfo(env, info);
+      AccessorCallbackData* callbackData =
+        static_cast<AccessorCallbackData*>(callbackInfo.Data());
+      callbackInfo.SetData(callbackData->data);
+      callbackData->setterCallback(callbackInfo);
+      return nullptr;
+    });
+  }
+
+  Getter getterCallback;
+  Setter setterCallback;
+  void* data;
+};
+
+}  // namespace details
+
+#ifndef NODE_ADDON_API_DISABLE_DEPRECATED
+# include "napi-inl-deprecated.h"
+#endif // !NODE_ADDON_API_DISABLE_DEPRECATED
+
+////////////////////////////////////////////////////////////////////////////////
+// Module registration
+////////////////////////////////////////////////////////////////////////////////
+
+#define NODE_API_MODULE(modname, regfunc)                 \
+  napi_value __napi_ ## regfunc(napi_env env,             \
+                                napi_value exports) {     \
+    return Napi::RegisterModule(env, exports, regfunc);   \
+  }                                                       \
+  NAPI_MODULE(modname, __napi_ ## regfunc)
+
+// Adapt the NAPI_MODULE registration function:
+//  - Wrap the arguments in NAPI wrappers.
+//  - Catch any NAPI errors and rethrow as JS exceptions.
+inline napi_value RegisterModule(napi_env env,
+                                 napi_value exports,
+                                 ModuleRegisterCallback registerCallback) {
+  return details::WrapCallback([&] {
+    return napi_value(registerCallback(Napi::Env(env),
+                                       Napi::Object(env, exports)));
+  });
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Env class
+////////////////////////////////////////////////////////////////////////////////
+
+inline Env::Env(napi_env env) : _env(env) {
+}
+
+inline Env::operator napi_env() const {
+  return _env;
+}
+
+inline Object Env::Global() const {
+  napi_value value;
+  napi_status status = napi_get_global(*this, &value);
+  NAPI_THROW_IF_FAILED(*this, status, Object());
+  return Object(*this, value);
+}
+
+inline Value Env::Undefined() const {
+  napi_value value;
+  napi_status status = napi_get_undefined(*this, &value);
+  NAPI_THROW_IF_FAILED(*this, status, Value());
+  return Value(*this, value);
+}
+
+inline Value Env::Null() const {
+  napi_value value;
+  napi_status status = napi_get_null(*this, &value);
+  NAPI_THROW_IF_FAILED(*this, status, Value());
+  return Value(*this, value);
+}
+
+inline bool Env::IsExceptionPending() const {
+  bool result;
+  napi_status status = napi_is_exception_pending(_env, &result);
+  if (status != napi_ok) result = false; // Checking for a pending exception shouldn't throw.
+  return result;
+}
+
+inline Error Env::GetAndClearPendingException() {
+  napi_value value;
+  napi_status status = napi_get_and_clear_last_exception(_env, &value);
+  if (status != napi_ok) {
+    // Don't throw another exception when failing to get the exception!
+    return Error();
+  }
+  return Error(_env, value);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Value class
+////////////////////////////////////////////////////////////////////////////////
+
+inline Value::Value() : _env(nullptr), _value(nullptr) {
+}
+
+inline Value::Value(napi_env env, napi_value value) : _env(env), _value(value) {
+}
+
+inline Value::operator napi_value() const {
+  return _value;
+}
+
+inline bool Value::operator ==(const Value& other) const {
+  return StrictEquals(other);
+}
+
+inline bool Value::operator !=(const Value& other) const {
+  return !this->operator ==(other);
+}
+
+inline bool Value::StrictEquals(const Value& other) const {
+  bool result;
+  napi_status status = napi_strict_equals(_env, *this, other, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline Napi::Env Value::Env() const {
+  return Napi::Env(_env);
+}
+
+inline bool Value::IsEmpty() const {
+  return _value == nullptr;
+}
+
+inline napi_valuetype Value::Type() const {
+  if (IsEmpty()) {
+    return napi_undefined;
+  }
+
+  napi_valuetype type;
+  napi_status status = napi_typeof(_env, _value, &type);
+  NAPI_THROW_IF_FAILED(_env, status, napi_undefined);
+  return type;
+}
+
+inline bool Value::IsUndefined() const {
+  return Type() == napi_undefined;
+}
+
+inline bool Value::IsNull() const {
+  return Type() == napi_null;
+}
+
+inline bool Value::IsBoolean() const {
+  return Type() == napi_boolean;
+}
+
+inline bool Value::IsNumber() const {
+  return Type() == napi_number;
+}
+
+// currently experimental guard with version of NAPI_VERSION that it is
+// released in once it is no longer experimental
+#if (NAPI_VERSION > 2147483646)
+inline bool Value::IsBigInt() const {
+  return Type() == napi_bigint;
+}
+#endif  // NAPI_EXPERIMENTAL
+
+inline bool Value::IsString() const {
+  return Type() == napi_string;
+}
+
+inline bool Value::IsSymbol() const {
+  return Type() == napi_symbol;
+}
+
+inline bool Value::IsArray() const {
+  if (IsEmpty()) {
+    return false;
+  }
+
+  bool result;
+  napi_status status = napi_is_array(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Value::IsArrayBuffer() const {
+  if (IsEmpty()) {
+    return false;
+  }
+
+  bool result;
+  napi_status status = napi_is_arraybuffer(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Value::IsTypedArray() const {
+  if (IsEmpty()) {
+    return false;
+  }
+
+  bool result;
+  napi_status status = napi_is_typedarray(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Value::IsObject() const {
+  return Type() == napi_object || IsFunction();
+}
+
+inline bool Value::IsFunction() const {
+  return Type() == napi_function;
+}
+
+inline bool Value::IsPromise() const {
+  if (IsEmpty()) {
+    return false;
+  }
+
+  bool result;
+  napi_status status = napi_is_promise(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Value::IsDataView() const {
+  if (IsEmpty()) {
+    return false;
+  }
+
+  bool result;
+  napi_status status = napi_is_dataview(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Value::IsBuffer() const {
+  if (IsEmpty()) {
+    return false;
+  }
+
+  bool result;
+  napi_status status = napi_is_buffer(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Value::IsExternal() const {
+  return Type() == napi_external;
+}
+
+template <typename T>
+inline T Value::As() const {
+  return T(_env, _value);
+}
+
+inline Boolean Value::ToBoolean() const {
+  napi_value result;
+  napi_status status = napi_coerce_to_bool(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, Boolean());
+  return Boolean(_env, result);
+}
+
+inline Number Value::ToNumber() const {
+  napi_value result;
+  napi_status status = napi_coerce_to_number(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, Number());
+  return Number(_env, result);
+}
+
+inline String Value::ToString() const {
+  napi_value result;
+  napi_status status = napi_coerce_to_string(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, String());
+  return String(_env, result);
+}
+
+inline Object Value::ToObject() const {
+  napi_value result;
+  napi_status status = napi_coerce_to_object(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, Object());
+  return Object(_env, result);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Boolean class
+////////////////////////////////////////////////////////////////////////////////
+
+inline Boolean Boolean::New(napi_env env, bool val) {
+  napi_value value;
+  napi_status status = napi_get_boolean(env, val, &value);
+  NAPI_THROW_IF_FAILED(env, status, Boolean());
+  return Boolean(env, value);
+}
+
+inline Boolean::Boolean() : Napi::Value() {
+}
+
+inline Boolean::Boolean(napi_env env, napi_value value) : Napi::Value(env, value) {
+}
+
+inline Boolean::operator bool() const {
+  return Value();
+}
+
+inline bool Boolean::Value() const {
+  bool result;
+  napi_status status = napi_get_value_bool(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Number class
+////////////////////////////////////////////////////////////////////////////////
+
+inline Number Number::New(napi_env env, double val) {
+  napi_value value;
+  napi_status status = napi_create_double(env, val, &value);
+  NAPI_THROW_IF_FAILED(env, status, Number());
+  return Number(env, value);
+}
+
+inline Number::Number() : Value() {
+}
+
+inline Number::Number(napi_env env, napi_value value) : Value(env, value) {
+}
+
+inline Number::operator int32_t() const {
+  return Int32Value();
+}
+
+inline Number::operator uint32_t() const {
+  return Uint32Value();
+}
+
+inline Number::operator int64_t() const {
+  return Int64Value();
+}
+
+inline Number::operator float() const {
+  return FloatValue();
+}
+
+inline Number::operator double() const {
+  return DoubleValue();
+}
+
+inline int32_t Number::Int32Value() const {
+  int32_t result;
+  napi_status status = napi_get_value_int32(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, 0);
+  return result;
+}
+
+inline uint32_t Number::Uint32Value() const {
+  uint32_t result;
+  napi_status status = napi_get_value_uint32(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, 0);
+  return result;
+}
+
+inline int64_t Number::Int64Value() const {
+  int64_t result;
+  napi_status status = napi_get_value_int64(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, 0);
+  return result;
+}
+
+inline float Number::FloatValue() const {
+  return static_cast<float>(DoubleValue());
+}
+
+inline double Number::DoubleValue() const {
+  double result;
+  napi_status status = napi_get_value_double(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, 0);
+  return result;
+}
+
+// currently experimental guard with version of NAPI_VERSION that it is
+// released in once it is no longer experimental
+#if (NAPI_VERSION > 2147483646)
+////////////////////////////////////////////////////////////////////////////////
+// BigInt Class
+////////////////////////////////////////////////////////////////////////////////
+
+inline BigInt BigInt::New(napi_env env, int64_t val) {
+  napi_value value;
+  napi_status status = napi_create_bigint_int64(env, val, &value);
+  NAPI_THROW_IF_FAILED(env, status, BigInt());
+  return BigInt(env, value);
+}
+
+inline BigInt BigInt::New(napi_env env, uint64_t val) {
+  napi_value value;
+  napi_status status = napi_create_bigint_uint64(env, val, &value);
+  NAPI_THROW_IF_FAILED(env, status, BigInt());
+  return BigInt(env, value);
+}
+
+inline BigInt BigInt::New(napi_env env, int sign_bit, size_t word_count, const uint64_t* words) {
+  napi_value value;
+  napi_status status = napi_create_bigint_words(env, sign_bit, word_count, words, &value);
+  NAPI_THROW_IF_FAILED(env, status, BigInt());
+  return BigInt(env, value);
+}
+
+inline BigInt::BigInt() : Value() {
+}
+
+inline BigInt::BigInt(napi_env env, napi_value value) : Value(env, value) {
+}
+
+inline int64_t BigInt::Int64Value(bool* lossless) const {
+  int64_t result;
+  napi_status status = napi_get_value_bigint_int64(
+      _env, _value, &result, lossless);
+  NAPI_THROW_IF_FAILED(_env, status, 0);
+  return result;
+}
+
+inline uint64_t BigInt::Uint64Value(bool* lossless) const {
+  uint64_t result;
+  napi_status status = napi_get_value_bigint_uint64(
+      _env, _value, &result, lossless);
+  NAPI_THROW_IF_FAILED(_env, status, 0);
+  return result;
+}
+
+inline size_t BigInt::WordCount() const {
+  size_t word_count;
+  napi_status status = napi_get_value_bigint_words(
+      _env, _value, nullptr, &word_count, nullptr);
+  NAPI_THROW_IF_FAILED(_env, status, 0);
+  return word_count;
+}
+
+inline void BigInt::ToWords(int* sign_bit, size_t* word_count, uint64_t* words) {
+  napi_status status = napi_get_value_bigint_words(
+      _env, _value, sign_bit, word_count, words);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+#endif  // NAPI_EXPERIMENTAL
+
+////////////////////////////////////////////////////////////////////////////////
+// Name class
+////////////////////////////////////////////////////////////////////////////////
+
+inline Name::Name() : Value() {
+}
+
+inline Name::Name(napi_env env, napi_value value) : Value(env, value) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// String class
+////////////////////////////////////////////////////////////////////////////////
+
+inline String String::New(napi_env env, const std::string& val) {
+  return String::New(env, val.c_str(), val.size());
+}
+
+inline String String::New(napi_env env, const std::u16string& val) {
+  return String::New(env, val.c_str(), val.size());
+}
+
+inline String String::New(napi_env env, const char* val) {
+  napi_value value;
+  napi_status status = napi_create_string_utf8(env, val, std::strlen(val), &value);
+  NAPI_THROW_IF_FAILED(env, status, String());
+  return String(env, value);
+}
+
+inline String String::New(napi_env env, const char16_t* val) {
+  napi_value value;
+  napi_status status = napi_create_string_utf16(env, val, std::u16string(val).size(), &value);
+  NAPI_THROW_IF_FAILED(env, status, String());
+  return String(env, value);
+}
+
+inline String String::New(napi_env env, const char* val, size_t length) {
+  napi_value value;
+  napi_status status = napi_create_string_utf8(env, val, length, &value);
+  NAPI_THROW_IF_FAILED(env, status, String());
+  return String(env, value);
+}
+
+inline String String::New(napi_env env, const char16_t* val, size_t length) {
+  napi_value value;
+  napi_status status = napi_create_string_utf16(env, val, length, &value);
+  NAPI_THROW_IF_FAILED(env, status, String());
+  return String(env, value);
+}
+
+inline String::String() : Name() {
+}
+
+inline String::String(napi_env env, napi_value value) : Name(env, value) {
+}
+
+inline String::operator std::string() const {
+  return Utf8Value();
+}
+
+inline String::operator std::u16string() const {
+  return Utf16Value();
+}
+
+inline std::string String::Utf8Value() const {
+  size_t length;
+  napi_status status = napi_get_value_string_utf8(_env, _value, nullptr, 0, &length);
+  NAPI_THROW_IF_FAILED(_env, status, "");
+
+  std::string value;
+  value.reserve(length + 1);
+  value.resize(length);
+  status = napi_get_value_string_utf8(_env, _value, &value[0], value.capacity(), nullptr);
+  NAPI_THROW_IF_FAILED(_env, status, "");
+  return value;
+}
+
+inline std::u16string String::Utf16Value() const {
+  size_t length;
+  napi_status status = napi_get_value_string_utf16(_env, _value, nullptr, 0, &length);
+  NAPI_THROW_IF_FAILED(_env, status, NAPI_WIDE_TEXT(""));
+
+  std::u16string value;
+  value.reserve(length + 1);
+  value.resize(length);
+  status = napi_get_value_string_utf16(_env, _value, &value[0], value.capacity(), nullptr);
+  NAPI_THROW_IF_FAILED(_env, status, NAPI_WIDE_TEXT(""));
+  return value;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Symbol class
+////////////////////////////////////////////////////////////////////////////////
+
+inline Symbol Symbol::New(napi_env env, const char* description) {
+  napi_value descriptionValue = description != nullptr ?
+    String::New(env, description) : static_cast<napi_value>(nullptr);
+  return Symbol::New(env, descriptionValue);
+}
+
+inline Symbol Symbol::New(napi_env env, const std::string& description) {
+  napi_value descriptionValue = String::New(env, description);
+  return Symbol::New(env, descriptionValue);
+}
+
+inline Symbol Symbol::New(napi_env env, String description) {
+  napi_value descriptionValue = description;
+  return Symbol::New(env, descriptionValue);
+}
+
+inline Symbol Symbol::New(napi_env env, napi_value description) {
+  napi_value value;
+  napi_status status = napi_create_symbol(env, description, &value);
+  NAPI_THROW_IF_FAILED(env, status, Symbol());
+  return Symbol(env, value);
+}
+
+inline Symbol Symbol::WellKnown(napi_env env, const std::string& name) {
+  return Napi::Env(env).Global().Get("Symbol").As<Object>().Get(name).As<Symbol>();
+}
+
+inline Symbol::Symbol() : Name() {
+}
+
+inline Symbol::Symbol(napi_env env, napi_value value) : Name(env, value) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Automagic value creation
+////////////////////////////////////////////////////////////////////////////////
+
+namespace details {
+template <typename T>
+struct vf_number {
+  static Number From(napi_env env, T value) {
+    return Number::New(env, static_cast<double>(value));
+  }
+};
+
+template<>
+struct vf_number<bool> {
+  static Boolean From(napi_env env, bool value) {
+    return Boolean::New(env, value);
+  }
+};
+
+struct vf_utf8_charp {
+  static String From(napi_env env, const char* value) {
+    return String::New(env, value);
+  }
+};
+
+struct vf_utf16_charp {
+  static String From(napi_env env, const char16_t* value) {
+    return String::New(env, value);
+  }
+};
+struct vf_utf8_string {
+  static String From(napi_env env, const std::string& value) {
+    return String::New(env, value);
+  }
+};
+
+struct vf_utf16_string {
+  static String From(napi_env env, const std::u16string& value) {
+    return String::New(env, value);
+  }
+};
+
+template <typename T>
+struct vf_fallback {
+  static Value From(napi_env env, const T& value) {
+    return Value(env, value);
+  }
+};
+
+template <typename...> struct disjunction : std::false_type {};
+template <typename B> struct disjunction<B> : B {};
+template <typename B, typename... Bs>
+struct disjunction<B, Bs...>
+    : std::conditional<bool(B::value), B, disjunction<Bs...>>::type {};
+
+template <typename T>
+struct can_make_string
+    : disjunction<typename std::is_convertible<T, const char *>::type,
+                  typename std::is_convertible<T, const char16_t *>::type,
+                  typename std::is_convertible<T, std::string>::type,
+                  typename std::is_convertible<T, std::u16string>::type> {};
+}
+
+template <typename T>
+Value Value::From(napi_env env, const T& value) {
+  using Helper = typename std::conditional<
+    std::is_integral<T>::value || std::is_floating_point<T>::value,
+    details::vf_number<T>,
+    typename std::conditional<
+      details::can_make_string<T>::value,
+      String,
+      details::vf_fallback<T>
+    >::type
+  >::type;
+  return Helper::From(env, value);
+}
+
+template <typename T>
+String String::From(napi_env env, const T& value) {
+  struct Dummy {};
+  using Helper = typename std::conditional<
+    std::is_convertible<T, const char*>::value,
+    details::vf_utf8_charp,
+    typename std::conditional<
+      std::is_convertible<T, const char16_t*>::value,
+      details::vf_utf16_charp,
+      typename std::conditional<
+        std::is_convertible<T, std::string>::value,
+        details::vf_utf8_string,
+        typename std::conditional<
+          std::is_convertible<T, std::u16string>::value,
+          details::vf_utf16_string,
+          Dummy
+        >::type
+      >::type
+    >::type
+  >::type;
+  return Helper::From(env, value);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Object class
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename Key>
+inline Object::PropertyLValue<Key>::operator Value() const {
+  return Object(_env, _object).Get(_key);
+}
+
+template <typename Key> template <typename ValueType>
+inline Object::PropertyLValue<Key>& Object::PropertyLValue<Key>::operator =(ValueType value) {
+  Object(_env, _object).Set(_key, value);
+  return *this;
+}
+
+template <typename Key>
+inline Object::PropertyLValue<Key>::PropertyLValue(Object object, Key key)
+  : _env(object.Env()), _object(object), _key(key) {}
+
+inline Object Object::New(napi_env env) {
+  napi_value value;
+  napi_status status = napi_create_object(env, &value);
+  NAPI_THROW_IF_FAILED(env, status, Object());
+  return Object(env, value);
+}
+
+inline Object::Object() : Value() {
+}
+
+inline Object::Object(napi_env env, napi_value value) : Value(env, value) {
+}
+
+inline Object::PropertyLValue<std::string> Object::operator [](const char* utf8name) {
+  return PropertyLValue<std::string>(*this, utf8name);
+}
+
+inline Object::PropertyLValue<std::string> Object::operator [](const std::string& utf8name) {
+  return PropertyLValue<std::string>(*this, utf8name);
+}
+
+inline Object::PropertyLValue<uint32_t> Object::operator [](uint32_t index) {
+  return PropertyLValue<uint32_t>(*this, index);
+}
+
+inline Value Object::operator [](const char* utf8name) const {
+  return Get(utf8name);
+}
+
+inline Value Object::operator [](const std::string& utf8name) const {
+  return Get(utf8name);
+}
+
+inline Value Object::operator [](uint32_t index) const {
+  return Get(index);
+}
+
+inline bool Object::Has(napi_value key) const {
+  bool result;
+  napi_status status = napi_has_property(_env, _value, key, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Object::Has(Value key) const {
+  bool result;
+  napi_status status = napi_has_property(_env, _value, key, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Object::Has(const char* utf8name) const {
+  bool result;
+  napi_status status = napi_has_named_property(_env, _value, utf8name, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Object::Has(const std::string& utf8name) const {
+  return Has(utf8name.c_str());
+}
+
+inline bool Object::HasOwnProperty(napi_value key) const {
+  bool result;
+  napi_status status = napi_has_own_property(_env, _value, key, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Object::HasOwnProperty(Value key) const {
+  bool result;
+  napi_status status = napi_has_own_property(_env, _value, key, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Object::HasOwnProperty(const char* utf8name) const {
+  napi_value key;
+  napi_status status = napi_create_string_utf8(_env, utf8name, std::strlen(utf8name), &key);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return HasOwnProperty(key);
+}
+
+inline bool Object::HasOwnProperty(const std::string& utf8name) const {
+  return HasOwnProperty(utf8name.c_str());
+}
+
+inline Value Object::Get(napi_value key) const {
+  napi_value result;
+  napi_status status = napi_get_property(_env, _value, key, &result);
+  NAPI_THROW_IF_FAILED(_env, status, Value());
+  return Value(_env, result);
+}
+
+inline Value Object::Get(Value key) const {
+  napi_value result;
+  napi_status status = napi_get_property(_env, _value, key, &result);
+  NAPI_THROW_IF_FAILED(_env, status, Value());
+  return Value(_env, result);
+}
+
+inline Value Object::Get(const char* utf8name) const {
+  napi_value result;
+  napi_status status = napi_get_named_property(_env, _value, utf8name, &result);
+  NAPI_THROW_IF_FAILED(_env, status, Value());
+  return Value(_env, result);
+}
+
+inline Value Object::Get(const std::string& utf8name) const {
+  return Get(utf8name.c_str());
+}
+
+template <typename ValueType>
+inline void Object::Set(napi_value key, const ValueType& value) {
+  napi_status status =
+      napi_set_property(_env, _value, key, Value::From(_env, value));
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+template <typename ValueType>
+inline void Object::Set(Value key, const ValueType& value) {
+  napi_status status =
+      napi_set_property(_env, _value, key, Value::From(_env, value));
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+template <typename ValueType>
+inline void Object::Set(const char* utf8name, const ValueType& value) {
+  napi_status status =
+      napi_set_named_property(_env, _value, utf8name, Value::From(_env, value));
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+template <typename ValueType>
+inline void Object::Set(const std::string& utf8name, const ValueType& value) {
+  Set(utf8name.c_str(), value);
+}
+
+inline bool Object::Delete(napi_value key) {
+  bool result;
+  napi_status status = napi_delete_property(_env, _value, key, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Object::Delete(Value key) {
+  bool result;
+  napi_status status = napi_delete_property(_env, _value, key, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline bool Object::Delete(const char* utf8name) {
+  return Delete(String::New(_env, utf8name));
+}
+
+inline bool Object::Delete(const std::string& utf8name) {
+  return Delete(String::New(_env, utf8name));
+}
+
+inline bool Object::Has(uint32_t index) const {
+  bool result;
+  napi_status status = napi_has_element(_env, _value, index, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline Value Object::Get(uint32_t index) const {
+  napi_value value;
+  napi_status status = napi_get_element(_env, _value, index, &value);
+  NAPI_THROW_IF_FAILED(_env, status, Value());
+  return Value(_env, value);
+}
+
+template <typename ValueType>
+inline void Object::Set(uint32_t index, const ValueType& value) {
+  napi_status status =
+      napi_set_element(_env, _value, index, Value::From(_env, value));
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline bool Object::Delete(uint32_t index) {
+  bool result;
+  napi_status status = napi_delete_element(_env, _value, index, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+inline Array Object::GetPropertyNames() const {
+  napi_value result;
+  napi_status status = napi_get_property_names(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, Array());
+  return Array(_env, result);
+}
+
+inline void Object::DefineProperty(const PropertyDescriptor& property) {
+  napi_status status = napi_define_properties(_env, _value, 1,
+    reinterpret_cast<const napi_property_descriptor*>(&property));
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline void Object::DefineProperties(const std::initializer_list<PropertyDescriptor>& properties) {
+  napi_status status = napi_define_properties(_env, _value, properties.size(),
+    reinterpret_cast<const napi_property_descriptor*>(properties.begin()));
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline void Object::DefineProperties(const std::vector<PropertyDescriptor>& properties) {
+  napi_status status = napi_define_properties(_env, _value, properties.size(),
+    reinterpret_cast<const napi_property_descriptor*>(properties.data()));
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline bool Object::InstanceOf(const Function& constructor) const {
+  bool result;
+  napi_status status = napi_instanceof(_env, _value, constructor, &result);
+  NAPI_THROW_IF_FAILED(_env, status, false);
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// External class
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+inline External<T> External<T>::New(napi_env env, T* data) {
+  napi_value value;
+  napi_status status = napi_create_external(env, data, nullptr, nullptr, &value);
+  NAPI_THROW_IF_FAILED(env, status, External());
+  return External(env, value);
+}
+
+template <typename T>
+template <typename Finalizer>
+inline External<T> External<T>::New(napi_env env,
+                                    T* data,
+                                    Finalizer finalizeCallback) {
+  napi_value value;
+  details::FinalizeData<T, Finalizer>* finalizeData =
+    new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
+  napi_status status = napi_create_external(
+    env,
+    data,
+    details::FinalizeData<T, Finalizer>::Wrapper,
+    finalizeData,
+    &value);
+  if (status != napi_ok) {
+    delete finalizeData;
+    NAPI_THROW_IF_FAILED(env, status, External());
+  }
+  return External(env, value);
+}
+
+template <typename T>
+template <typename Finalizer, typename Hint>
+inline External<T> External<T>::New(napi_env env,
+                                    T* data,
+                                    Finalizer finalizeCallback,
+                                    Hint* finalizeHint) {
+  napi_value value;
+  details::FinalizeData<T, Finalizer, Hint>* finalizeData =
+    new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
+  napi_status status = napi_create_external(
+    env,
+    data,
+    details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
+    finalizeData,
+    &value);
+  if (status != napi_ok) {
+    delete finalizeData;
+    NAPI_THROW_IF_FAILED(env, status, External());
+  }
+  return External(env, value);
+}
+
+template <typename T>
+inline External<T>::External() : Value() {
+}
+
+template <typename T>
+inline External<T>::External(napi_env env, napi_value value) : Value(env, value) {
+}
+
+template <typename T>
+inline T* External<T>::Data() const {
+  void* data;
+  napi_status status = napi_get_value_external(_env, _value, &data);
+  NAPI_THROW_IF_FAILED(_env, status, nullptr);
+  return reinterpret_cast<T*>(data);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Array class
+////////////////////////////////////////////////////////////////////////////////
+
+inline Array Array::New(napi_env env) {
+  napi_value value;
+  napi_status status = napi_create_array(env, &value);
+  NAPI_THROW_IF_FAILED(env, status, Array());
+  return Array(env, value);
+}
+
+inline Array Array::New(napi_env env, size_t length) {
+  napi_value value;
+  napi_status status = napi_create_array_with_length(env, length, &value);
+  NAPI_THROW_IF_FAILED(env, status, Array());
+  return Array(env, value);
+}
+
+inline Array::Array() : Object() {
+}
+
+inline Array::Array(napi_env env, napi_value value) : Object(env, value) {
+}
+
+inline uint32_t Array::Length() const {
+  uint32_t result;
+  napi_status status = napi_get_array_length(_env, _value, &result);
+  NAPI_THROW_IF_FAILED(_env, status, 0);
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ArrayBuffer class
+////////////////////////////////////////////////////////////////////////////////
+
+inline ArrayBuffer ArrayBuffer::New(napi_env env, size_t byteLength) {
+  napi_value value;
+  void* data;
+  napi_status status = napi_create_arraybuffer(env, byteLength, &data, &value);
+  NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
+
+  return ArrayBuffer(env, value, data, byteLength);
+}
+
+inline ArrayBuffer ArrayBuffer::New(napi_env env,
+                                    void* externalData,
+                                    size_t byteLength) {
+  napi_value value;
+  napi_status status = napi_create_external_arraybuffer(
+    env, externalData, byteLength, nullptr, nullptr, &value);
+  NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
+
+  return ArrayBuffer(env, value, externalData, byteLength);
+}
+
+template <typename Finalizer>
+inline ArrayBuffer ArrayBuffer::New(napi_env env,
+                                    void* externalData,
+                                    size_t byteLength,
+                                    Finalizer finalizeCallback) {
+  napi_value value;
+  details::FinalizeData<void, Finalizer>* finalizeData =
+    new details::FinalizeData<void, Finalizer>({ finalizeCallback, nullptr });
+  napi_status status = napi_create_external_arraybuffer(
+    env,
+    externalData,
+    byteLength,
+    details::FinalizeData<void, Finalizer>::Wrapper,
+    finalizeData,
+    &value);
+  if (status != napi_ok) {
+    delete finalizeData;
+    NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
+  }
+
+  return ArrayBuffer(env, value, externalData, byteLength);
+}
+
+template <typename Finalizer, typename Hint>
+inline ArrayBuffer ArrayBuffer::New(napi_env env,
+                                    void* externalData,
+                                    size_t byteLength,
+                                    Finalizer finalizeCallback,
+                                    Hint* finalizeHint) {
+  napi_value value;
+  details::FinalizeData<void, Finalizer, Hint>* finalizeData =
+    new details::FinalizeData<void, Finalizer, Hint>({ finalizeCallback, finalizeHint });
+  napi_status status = napi_create_external_arraybuffer(
+    env,
+    externalData,
+    byteLength,
+    details::FinalizeData<void, Finalizer, Hint>::WrapperWithHint,
+    finalizeData,
+    &value);
+  if (status != napi_ok) {
+    delete finalizeData;
+    NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
+  }
+
+  return ArrayBuffer(env, value, externalData, byteLength);
+}
+
+inline ArrayBuffer::ArrayBuffer() : Object(), _data(nullptr), _length(0) {
+}
+
+inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value)
+  : Object(env, value), _data(nullptr), _length(0) {
+}
+
+inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value, void* data, size_t length)
+  : Object(env, value), _data(data), _length(length) {
+}
+
+inline void* ArrayBuffer::Data() {
+  EnsureInfo();
+  return _data;
+}
+
+inline size_t ArrayBuffer::ByteLength() {
+  EnsureInfo();
+  return _length;
+}
+
+inline void ArrayBuffer::EnsureInfo() const {
+  // The ArrayBuffer instance may have been constructed from a napi_value whose
+  // length/data are not yet known. Fetch and cache these values just once,
+  // since they can never change during the lifetime of the ArrayBuffer.
+  if (_data == nullptr) {
+    napi_status status = napi_get_arraybuffer_info(_env, _value, &_data, &_length);
+    NAPI_THROW_IF_FAILED_VOID(_env, status);
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DataView class
+////////////////////////////////////////////////////////////////////////////////
+inline DataView DataView::New(napi_env env,
+                              Napi::ArrayBuffer arrayBuffer) {
+  return New(env, arrayBuffer, 0, arrayBuffer.ByteLength());
+}
+
+inline DataView DataView::New(napi_env env,
+                              Napi::ArrayBuffer arrayBuffer,
+                              size_t byteOffset) {
+  if (byteOffset > arrayBuffer.ByteLength()) {
+    NAPI_THROW(RangeError::New(env,
+        "Start offset is outside the bounds of the buffer"),
+        DataView());
+  }
+  return New(env, arrayBuffer, byteOffset,
+      arrayBuffer.ByteLength() - byteOffset);
+}
+
+inline DataView DataView::New(napi_env env,
+                              Napi::ArrayBuffer arrayBuffer,
+                              size_t byteOffset,
+                              size_t byteLength) {
+  if (byteOffset + byteLength > arrayBuffer.ByteLength()) {
+    NAPI_THROW(RangeError::New(env, "Invalid DataView length"),
+               DataView());
+  }
+  napi_value value;
+  napi_status status = napi_create_dataview(
+    env, byteLength, arrayBuffer, byteOffset, &value);
+  NAPI_THROW_IF_FAILED(env, status, DataView());
+  return DataView(env, value);
+}
+
+inline DataView::DataView() : Object() {
+}
+
+inline DataView::DataView(napi_env env, napi_value value) : Object(env, value) {
+  napi_status status = napi_get_dataview_info(
+    _env,
+    _value   /* dataView */,
+    &_length /* byteLength */,
+    &_data   /* data */,
+    nullptr  /* arrayBuffer */,
+    nullptr  /* byteOffset */);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline Napi::ArrayBuffer DataView::ArrayBuffer() const {
+  napi_value arrayBuffer;
+  napi_status status = napi_get_dataview_info(
+    _env,
+    _value       /* dataView */,
+    nullptr      /* byteLength */,
+    nullptr      /* data */,
+    &arrayBuffer /* arrayBuffer */,
+    nullptr      /* byteOffset */);
+  NAPI_THROW_IF_FAILED(_env, status, Napi::ArrayBuffer());
+  return Napi::ArrayBuffer(_env, arrayBuffer);
+}
+
+inline size_t DataView::ByteOffset() const {
+  size_t byteOffset;
+  napi_status status = napi_get_dataview_info(
+    _env,
+    _value      /* dataView */,
+    nullptr     /* byteLength */,
+    nullptr     /* data */,
+    nullptr     /* arrayBuffer */,
+    &byteOffset /* byteOffset */);
+  NAPI_THROW_IF_FAILED(_env, status, 0);
+  return byteOffset;
+}
+
+inline size_t DataView::ByteLength() const {
+  return _length;
+}
+
+inline void* DataView::Data() const {
+  return _data;
+}
+
+inline float DataView::GetFloat32(size_t byteOffset) const {
+  return ReadData<float>(byteOffset);
+}
+
+inline double DataView::GetFloat64(size_t byteOffset) const {
+  return ReadData<double>(byteOffset);
+}
+
+inline int8_t DataView::GetInt8(size_t byteOffset) const {
+  return ReadData<int8_t>(byteOffset);
+}
+
+inline int16_t DataView::GetInt16(size_t byteOffset) const {
+  return ReadData<int16_t>(byteOffset);
+}
+
+inline int32_t DataView::GetInt32(size_t byteOffset) const {
+  return ReadData<int32_t>(byteOffset);
+}
+
+inline uint8_t DataView::GetUint8(size_t byteOffset) const {
+  return ReadData<uint8_t>(byteOffset);
+}
+
+inline uint16_t DataView::GetUint16(size_t byteOffset) const {
+  return ReadData<uint16_t>(byteOffset);
+}
+
+inline uint32_t DataView::GetUint32(size_t byteOffset) const {
+  return ReadData<uint32_t>(byteOffset);
+}
+
+inline void DataView::SetFloat32(size_t byteOffset, float value) const {
+  WriteData<float>(byteOffset, value);
+}
+
+inline void DataView::SetFloat64(size_t byteOffset, double value) const {
+  WriteData<double>(byteOffset, value);
+}
+
+inline void DataView::SetInt8(size_t byteOffset, int8_t value) const {
+  WriteData<int8_t>(byteOffset, value);
+}
+
+inline void DataView::SetInt16(size_t byteOffset, int16_t value) const {
+  WriteData<int16_t>(byteOffset, value);
+}
+
+inline void DataView::SetInt32(size_t byteOffset, int32_t value) const {
+  WriteData<int32_t>(byteOffset, value);
+}
+
+inline void DataView::SetUint8(size_t byteOffset, uint8_t value) const {
+  WriteData<uint8_t>(byteOffset, value);
+}
+
+inline void DataView::SetUint16(size_t byteOffset, uint16_t value) const {
+  WriteData<uint16_t>(byteOffset, value);
+}
+
+inline void DataView::SetUint32(size_t byteOffset, uint32_t value) const {
+  WriteData<uint32_t>(byteOffset, value);
+}
+
+template <typename T>
+inline T DataView::ReadData(size_t byteOffset) const {
+  if (byteOffset + sizeof(T) > _length ||
+      byteOffset + sizeof(T) < byteOffset) {  // overflow
+    NAPI_THROW(RangeError::New(_env,
+        "Offset is outside the bounds of the DataView"), 0);
+  }
+
+  return *reinterpret_cast<T*>(static_cast<uint8_t*>(_data) + byteOffset);
+}
+
+template <typename T>
+inline void DataView::WriteData(size_t byteOffset, T value) const {
+  if (byteOffset + sizeof(T) > _length ||
+      byteOffset + sizeof(T) < byteOffset) {  // overflow
+    NAPI_THROW_VOID(RangeError::New(_env,
+        "Offset is outside the bounds of the DataView"));
+  }
+
+  *reinterpret_cast<T*>(static_cast<uint8_t*>(_data) + byteOffset) = value;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TypedArray class
+////////////////////////////////////////////////////////////////////////////////
+
+inline TypedArray::TypedArray()
+  : Object(), _type(TypedArray::unknown_array_type), _length(0) {
+}
+
+inline TypedArray::TypedArray(napi_env env, napi_value value)
+  : Object(env, value), _type(TypedArray::unknown_array_type), _length(0) {
+}
+
+inline TypedArray::TypedArray(napi_env env,
+                              napi_value value,
+                              napi_typedarray_type type,
+                              size_t length)
+  : Object(env, value), _type(type), _length(length) {
+}
+
+inline napi_typedarray_type TypedArray::TypedArrayType() const {
+  if (_type == TypedArray::unknown_array_type) {
+    napi_status status = napi_get_typedarray_info(_env, _value,
+      &const_cast<TypedArray*>(this)->_type, &const_cast<TypedArray*>(this)->_length,
+      nullptr, nullptr, nullptr);
+    NAPI_THROW_IF_FAILED(_env, status, napi_int8_array);
+  }
+
+  return _type;
+}
+
+inline uint8_t TypedArray::ElementSize() const {
+  switch (TypedArrayType()) {
+    case napi_int8_array:
+    case napi_uint8_array:
+    case napi_uint8_clamped_array:
+      return 1;
+    case napi_int16_array:
+    case napi_uint16_array:
+      return 2;
+    case napi_int32_array:
+    case napi_uint32_array:
+    case napi_float32_array:
+      return 4;
+    case napi_float64_array:
+      return 8;
+    default:
+      return 0;
+  }
+}
+
+inline size_t TypedArray::ElementLength() const {
+  if (_type == TypedArray::unknown_array_type) {
+    napi_status status = napi_get_typedarray_info(_env, _value,
+      &const_cast<TypedArray*>(this)->_type, &const_cast<TypedArray*>(this)->_length,
+      nullptr, nullptr, nullptr);
+    NAPI_THROW_IF_FAILED(_env, status, 0);
+  }
+
+  return _length;
+}
+
+inline size_t TypedArray::ByteOffset() const {
+  size_t byteOffset;
+  napi_status status = napi_get_typedarray_info(
+    _env, _value, nullptr, nullptr, nullptr, nullptr, &byteOffset);
+  NAPI_THROW_IF_FAILED(_env, status, 0);
+  return byteOffset;
+}
+
+inline size_t TypedArray::ByteLength() const {
+  return ElementSize() * ElementLength();
+}
+
+inline Napi::ArrayBuffer TypedArray::ArrayBuffer() const {
+  napi_value arrayBuffer;
+  napi_status status = napi_get_typedarray_info(
+    _env, _value, nullptr, nullptr, nullptr, &arrayBuffer, nullptr);
+  NAPI_THROW_IF_FAILED(_env, status, Napi::ArrayBuffer());
+  return Napi::ArrayBuffer(_env, arrayBuffer);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TypedArrayOf<T> class
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+inline TypedArrayOf<T> TypedArrayOf<T>::New(napi_env env,
+                                            size_t elementLength,
+                                            napi_typedarray_type type) {
+  Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(env, elementLength * sizeof (T));
+  return New(env, elementLength, arrayBuffer, 0, type);
+}
+
+template <typename T>
+inline TypedArrayOf<T> TypedArrayOf<T>::New(napi_env env,
+                                            size_t elementLength,
+                                            Napi::ArrayBuffer arrayBuffer,
+                                            size_t bufferOffset,
+                                            napi_typedarray_type type) {
+  napi_value value;
+  napi_status status = napi_create_typedarray(
+    env, type, elementLength, arrayBuffer, bufferOffset, &value);
+  NAPI_THROW_IF_FAILED(env, status, TypedArrayOf<T>());
+
+  return TypedArrayOf<T>(
+    env, value, type, elementLength,
+    reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(arrayBuffer.Data()) + bufferOffset));
+}
+
+template <typename T>
+inline TypedArrayOf<T>::TypedArrayOf() : TypedArray(), _data(nullptr) {
+}
+
+template <typename T>
+inline TypedArrayOf<T>::TypedArrayOf(napi_env env, napi_value value)
+  : TypedArray(env, value), _data(nullptr) {
+  napi_status status = napi_get_typedarray_info(
+    _env, _value, &_type, &_length, reinterpret_cast<void**>(&_data), nullptr, nullptr);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+template <typename T>
+inline TypedArrayOf<T>::TypedArrayOf(napi_env env,
+                                     napi_value value,
+                                     napi_typedarray_type type,
+                                     size_t length,
+                                     T* data)
+  : TypedArray(env, value, type, length), _data(data) {
+  if (!(type == TypedArrayTypeForPrimitiveType<T>() ||
+      (type == napi_uint8_clamped_array && std::is_same<T, uint8_t>::value))) {
+    NAPI_THROW_VOID(TypeError::New(env, "Array type must match the template parameter. "
+      "(Uint8 arrays may optionally have the \"clamped\" array type.)"));
+  }
+}
+
+template <typename T>
+inline T& TypedArrayOf<T>::operator [](size_t index) {
+  return _data[index];
+}
+
+template <typename T>
+inline const T& TypedArrayOf<T>::operator [](size_t index) const {
+  return _data[index];
+}
+
+template <typename T>
+inline T* TypedArrayOf<T>::Data() {
+  return _data;
+}
+
+template <typename T>
+inline const T* TypedArrayOf<T>::Data() const {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Function class
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename CbData>
+static inline napi_status
+CreateFunction(napi_env env,
+               const char* utf8name,
+               napi_callback cb,
+               CbData* data,
+               napi_value* result) {
+  napi_status status =
+      napi_create_function(env, utf8name, NAPI_AUTO_LENGTH, cb, data, result);
+  if (status == napi_ok) {
+    status = Napi::details::AttachData(env, *result, data);
+  }
+
+  return status;
+}
+
+template <typename Callable>
+inline Function Function::New(napi_env env,
+                              Callable cb,
+                              const char* utf8name,
+                              void* data) {
+  typedef decltype(cb(CallbackInfo(nullptr, nullptr))) ReturnType;
+  typedef details::CallbackData<Callable, ReturnType> CbData;
+  auto callbackData = new CbData({ cb, data });
+
+  napi_value value;
+  napi_status status = CreateFunction(env,
+                                      utf8name,
+                                      CbData::Wrapper,
+                                      callbackData,
+                                      &value);
+  if (status != napi_ok) {
+    delete callbackData;
+    NAPI_THROW_IF_FAILED(env, status, Function());
+  }
+
+  return Function(env, value);
+}
+
+template <typename Callable>
+inline Function Function::New(napi_env env,
+                              Callable cb,
+                              const std::string& utf8name,
+                              void* data) {
+  return New(env, cb, utf8name.c_str(), data);
+}
+
+inline Function::Function() : Object() {
+}
+
+inline Function::Function(napi_env env, napi_value value) : Object(env, value) {
+}
+
+inline Value Function::operator ()(const std::initializer_list<napi_value>& args) const {
+  return Call(Env().Undefined(), args);
+}
+
+inline Value Function::Call(const std::initializer_list<napi_value>& args) const {
+  return Call(Env().Undefined(), args);
+}
+
+inline Value Function::Call(const std::vector<napi_value>& args) const {
+  return Call(Env().Undefined(), args);
+}
+
+inline Value Function::Call(size_t argc, const napi_value* args) const {
+  return Call(Env().Undefined(), argc, args);
+}
+
+inline Value Function::Call(napi_value recv, const std::initializer_list<napi_value>& args) const {
+  return Call(recv, args.size(), args.begin());
+}
+
+inline Value Function::Call(napi_value recv, const std::vector<napi_value>& args) const {
+  return Call(recv, args.size(), args.data());
+}
+
+inline Value Function::Call(napi_value recv, size_t argc, const napi_value* args) const {
+  napi_value result;
+  napi_status status = napi_call_function(
+    _env, recv, _value, argc, args, &result);
+  NAPI_THROW_IF_FAILED(_env, status, Value());
+  return Value(_env, result);
+}
+
+inline Value Function::MakeCallback(
+    napi_value recv,
+    const std::initializer_list<napi_value>& args,
+    napi_async_context context) const {
+  return MakeCallback(recv, args.size(), args.begin(), context);
+}
+
+inline Value Function::MakeCallback(
+    napi_value recv,
+    const std::vector<napi_value>& args,
+    napi_async_context context) const {
+  return MakeCallback(recv, args.size(), args.data(), context);
+}
+
+inline Value Function::MakeCallback(
+    napi_value recv,
+    size_t argc,
+    const napi_value* args,
+    napi_async_context context) const {
+  napi_value result;
+  napi_status status = napi_make_callback(
+    _env, context, recv, _value, argc, args, &result);
+  NAPI_THROW_IF_FAILED(_env, status, Value());
+  return Value(_env, result);
+}
+
+inline Object Function::New(const std::initializer_list<napi_value>& args) const {
+  return New(args.size(), args.begin());
+}
+
+inline Object Function::New(const std::vector<napi_value>& args) const {
+  return New(args.size(), args.data());
+}
+
+inline Object Function::New(size_t argc, const napi_value* args) const {
+  napi_value result;
+  napi_status status = napi_new_instance(
+    _env, _value, argc, args, &result);
+  NAPI_THROW_IF_FAILED(_env, status, Object());
+  return Object(_env, result);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Promise class
+////////////////////////////////////////////////////////////////////////////////
+
+inline Promise::Deferred Promise::Deferred::New(napi_env env) {
+  return Promise::Deferred(env);
+}
+
+inline Promise::Deferred::Deferred(napi_env env) : _env(env) {
+  napi_status status = napi_create_promise(_env, &_deferred, &_promise);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline Promise Promise::Deferred::Promise() const {
+  return Napi::Promise(_env, _promise);
+}
+
+inline Napi::Env Promise::Deferred::Env() const {
+  return Napi::Env(_env);
+}
+
+inline void Promise::Deferred::Resolve(napi_value value) const {
+  napi_status status = napi_resolve_deferred(_env, _deferred, value);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline void Promise::Deferred::Reject(napi_value value) const {
+  napi_status status = napi_reject_deferred(_env, _deferred, value);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline Promise::Promise(napi_env env, napi_value value) : Object(env, value) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Buffer<T> class
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+inline Buffer<T> Buffer<T>::New(napi_env env, size_t length) {
+  napi_value value;
+  void* data;
+  napi_status status = napi_create_buffer(env, length * sizeof (T), &data, &value);
+  NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
+  return Buffer(env, value, length, static_cast<T*>(data));
+}
+
+template <typename T>
+inline Buffer<T> Buffer<T>::New(napi_env env, T* data, size_t length) {
+  napi_value value;
+  napi_status status = napi_create_external_buffer(
+    env, length * sizeof (T), data, nullptr, nullptr, &value);
+  NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
+  return Buffer(env, value, length, data);
+}
+
+template <typename T>
+template <typename Finalizer>
+inline Buffer<T> Buffer<T>::New(napi_env env,
+                                T* data,
+                                size_t length,
+                                Finalizer finalizeCallback) {
+  napi_value value;
+  details::FinalizeData<T, Finalizer>* finalizeData =
+    new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
+  napi_status status = napi_create_external_buffer(
+    env,
+    length * sizeof (T),
+    data,
+    details::FinalizeData<T, Finalizer>::Wrapper,
+    finalizeData,
+    &value);
+  if (status != napi_ok) {
+    delete finalizeData;
+    NAPI_THROW_IF_FAILED(env, status, Buffer());
+  }
+  return Buffer(env, value, length, data);
+}
+
+template <typename T>
+template <typename Finalizer, typename Hint>
+inline Buffer<T> Buffer<T>::New(napi_env env,
+                                T* data,
+                                size_t length,
+                                Finalizer finalizeCallback,
+                                Hint* finalizeHint) {
+  napi_value value;
+  details::FinalizeData<T, Finalizer, Hint>* finalizeData =
+    new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
+  napi_status status = napi_create_external_buffer(
+    env,
+    length * sizeof (T),
+    data,
+    details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
+    finalizeData,
+    &value);
+  if (status != napi_ok) {
+    delete finalizeData;
+    NAPI_THROW_IF_FAILED(env, status, Buffer());
+  }
+  return Buffer(env, value, length, data);
+}
+
+template <typename T>
+inline Buffer<T> Buffer<T>::Copy(napi_env env, const T* data, size_t length) {
+  napi_value value;
+  napi_status status = napi_create_buffer_copy(
+    env, length * sizeof (T), data, nullptr, &value);
+  NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
+  return Buffer<T>(env, value);
+}
+
+template <typename T>
+inline Buffer<T>::Buffer() : Uint8Array(), _length(0), _data(nullptr) {
+}
+
+template <typename T>
+inline Buffer<T>::Buffer(napi_env env, napi_value value)
+  : Uint8Array(env, value), _length(0), _data(nullptr) {
+}
+
+template <typename T>
+inline Buffer<T>::Buffer(napi_env env, napi_value value, size_t length, T* data)
+  : Uint8Array(env, value), _length(length), _data(data) {
+}
+
+template <typename T>
+inline size_t Buffer<T>::Length() const {
+  EnsureInfo();
+  return _length;
+}
+
+template <typename T>
+inline T* Buffer<T>::Data() const {
+  EnsureInfo();
+  return _data;
+}
+
+template <typename T>
+inline void Buffer<T>::EnsureInfo() const {
+  // The Buffer instance may have been constructed from a napi_value whose
+  // length/data are not yet known. Fetch and cache these values just once,
+  // since they can never change during the lifetime of the Buffer.
+  if (_data == nullptr) {
+    size_t byteLength;
+    void* voidData;
+    napi_status status = napi_get_buffer_info(_env, _value, &voidData, &byteLength);
+    NAPI_THROW_IF_FAILED_VOID(_env, status);
+    _length = byteLength / sizeof (T);
+    _data = static_cast<T*>(voidData);
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Error class
+////////////////////////////////////////////////////////////////////////////////
+
+inline Error Error::New(napi_env env) {
+  napi_status status;
+  napi_value error = nullptr;
+
+  const napi_extended_error_info* info;
+  status = napi_get_last_error_info(env, &info);
+  NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_last_error_info");
+
+  if (status == napi_ok) {
+    if (info->error_code == napi_pending_exception) {
+      status = napi_get_and_clear_last_exception(env, &error);
+      NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
+    }
+    else {
+      const char* error_message = info->error_message != nullptr ?
+        info->error_message : "Error in native callback";
+
+      bool isExceptionPending;
+      status = napi_is_exception_pending(env, &isExceptionPending);
+      NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending");
+
+      if (isExceptionPending) {
+        status = napi_get_and_clear_last_exception(env, &error);
+        NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
+      }
+
+      napi_value message;
+      status = napi_create_string_utf8(
+        env,
+        error_message,
+        std::strlen(error_message),
+        &message);
+      NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_string_utf8");
+
+      if (status == napi_ok) {
+        switch (info->error_code) {
+        case napi_object_expected:
+        case napi_string_expected:
+        case napi_boolean_expected:
+        case napi_number_expected:
+          status = napi_create_type_error(env, nullptr, message, &error);
+          break;
+        default:
+          status = napi_create_error(env, nullptr,  message, &error);
+          break;
+        }
+        NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error");
+      }
+    }
+  }
+
+  return Error(env, error);
+}
+
+inline Error Error::New(napi_env env, const char* message) {
+  return Error::New<Error>(env, message, std::strlen(message), napi_create_error);
+}
+
+inline Error Error::New(napi_env env, const std::string& message) {
+  return Error::New<Error>(env, message.c_str(), message.size(), napi_create_error);
+}
+
+inline NAPI_NO_RETURN void Error::Fatal(const char* location, const char* message) {
+  napi_fatal_error(location, NAPI_AUTO_LENGTH, message, NAPI_AUTO_LENGTH);
+}
+
+inline Error::Error() : ObjectReference() {
+}
+
+inline Error::Error(napi_env env, napi_value value) : ObjectReference(env, nullptr) {
+  if (value != nullptr) {
+    napi_status status = napi_create_reference(env, value, 1, &_ref);
+
+    // Avoid infinite recursion in the failure case.
+    // Don't try to construct & throw another Error instance.
+    NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_create_reference");
+  }
+}
+
+inline Error::Error(Error&& other) : ObjectReference(std::move(other)) {
+}
+
+inline Error& Error::operator =(Error&& other) {
+  static_cast<Reference<Object>*>(this)->operator=(std::move(other));
+  return *this;
+}
+
+inline Error::Error(const Error& other) : ObjectReference(other) {
+}
+
+inline Error& Error::operator =(Error& other) {
+  Reset();
+
+  _env = other.Env();
+  HandleScope scope(_env);
+
+  napi_value value = other.Value();
+  if (value != nullptr) {
+    napi_status status = napi_create_reference(_env, value, 1, &_ref);
+    NAPI_THROW_IF_FAILED(_env, status, *this);
+  }
+
+  return *this;
+}
+
+inline const std::string& Error::Message() const NAPI_NOEXCEPT {
+  if (_message.size() == 0 && _env != nullptr) {
+#ifdef NAPI_CPP_EXCEPTIONS
+    try {
+      _message = Get("message").As<String>();
+    }
+    catch (...) {
+      // Catch all errors here, to include e.g. a std::bad_alloc from
+      // the std::string::operator=, because this method may not throw.
+    }
+#else // NAPI_CPP_EXCEPTIONS
+    _message = Get("message").As<String>();
+#endif // NAPI_CPP_EXCEPTIONS
+  }
+  return _message;
+}
+
+inline void Error::ThrowAsJavaScriptException() const {
+  HandleScope scope(_env);
+  if (!IsEmpty()) {
+
+    // We intentionally don't use `NAPI_THROW_*` macros here to ensure
+    // that there is no possible recursion as `ThrowAsJavaScriptException`
+    // is part of `NAPI_THROW_*` macro definition for noexcept.
+
+    napi_status status = napi_throw(_env, Value());
+
+#ifdef NAPI_CPP_EXCEPTIONS
+    if (status != napi_ok) {
+      throw Error::New(_env);
+    }
+#else // NAPI_CPP_EXCEPTIONS
+    NAPI_FATAL_IF_FAILED(status, "Error::ThrowAsJavaScriptException", "napi_throw");
+#endif // NAPI_CPP_EXCEPTIONS
+  }
+}
+
+#ifdef NAPI_CPP_EXCEPTIONS
+
+inline const char* Error::what() const NAPI_NOEXCEPT {
+  return Message().c_str();
+}
+
+#endif // NAPI_CPP_EXCEPTIONS
+
+template <typename TError>
+inline TError Error::New(napi_env env,
+                         const char* message,
+                         size_t length,
+                         create_error_fn create_error) {
+  napi_value str;
+  napi_status status = napi_create_string_utf8(env, message, length, &str);
+  NAPI_THROW_IF_FAILED(env, status, TError());
+
+  napi_value error;
+  status = create_error(env, nullptr, str, &error);
+  NAPI_THROW_IF_FAILED(env, status, TError());
+
+  return TError(env, error);
+}
+
+inline TypeError TypeError::New(napi_env env, const char* message) {
+  return Error::New<TypeError>(env, message, std::strlen(message), napi_create_type_error);
+}
+
+inline TypeError TypeError::New(napi_env env, const std::string& message) {
+  return Error::New<TypeError>(env, message.c_str(), message.size(), napi_create_type_error);
+}
+
+inline TypeError::TypeError() : Error() {
+}
+
+inline TypeError::TypeError(napi_env env, napi_value value) : Error(env, value) {
+}
+
+inline RangeError RangeError::New(napi_env env, const char* message) {
+  return Error::New<RangeError>(env, message, std::strlen(message), napi_create_range_error);
+}
+
+inline RangeError RangeError::New(napi_env env, const std::string& message) {
+  return Error::New<RangeError>(env, message.c_str(), message.size(), napi_create_range_error);
+}
+
+inline RangeError::RangeError() : Error() {
+}
+
+inline RangeError::RangeError(napi_env env, napi_value value) : Error(env, value) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Reference<T> class
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+inline Reference<T> Reference<T>::New(const T& value, uint32_t initialRefcount) {
+  napi_env env = value.Env();
+  napi_value val = value;
+
+  if (val == nullptr) {
+    return Reference<T>(env, nullptr);
+  }
+
+  napi_ref ref;
+  napi_status status = napi_create_reference(env, value, initialRefcount, &ref);
+  NAPI_THROW_IF_FAILED(env, status, Reference<T>());
+
+  return Reference<T>(env, ref);
+}
+
+
+template <typename T>
+inline Reference<T>::Reference() : _env(nullptr), _ref(nullptr), _suppressDestruct(false) {
+}
+
+template <typename T>
+inline Reference<T>::Reference(napi_env env, napi_ref ref)
+  : _env(env), _ref(ref), _suppressDestruct(false) {
+}
+
+template <typename T>
+inline Reference<T>::~Reference() {
+  if (_ref != nullptr) {
+    if (!_suppressDestruct) {
+      napi_delete_reference(_env, _ref);
+    }
+
+    _ref = nullptr;
+  }
+}
+
+template <typename T>
+inline Reference<T>::Reference(Reference<T>&& other)
+  : _env(other._env), _ref(other._ref), _suppressDestruct(other._suppressDestruct) {
+  other._env = nullptr;
+  other._ref = nullptr;
+  other._suppressDestruct = false;
+}
+
+template <typename T>
+inline Reference<T>& Reference<T>::operator =(Reference<T>&& other) {
+  Reset();
+  _env = other._env;
+  _ref = other._ref;
+  _suppressDestruct = other._suppressDestruct;
+  other._env = nullptr;
+  other._ref = nullptr;
+  other._suppressDestruct = false;
+  return *this;
+}
+
+template <typename T>
+inline Reference<T>::Reference(const Reference<T>& other)
+  : _env(other._env), _ref(nullptr), _suppressDestruct(false) {
+  HandleScope scope(_env);
+
+  napi_value value = other.Value();
+  if (value != nullptr) {
+    // Copying is a limited scenario (currently only used for Error object) and always creates a
+    // strong reference to the given value even if the incoming reference is weak.
+    napi_status status = napi_create_reference(_env, value, 1, &_ref);
+    NAPI_FATAL_IF_FAILED(status, "Reference<T>::Reference", "napi_create_reference");
+  }
+}
+
+template <typename T>
+inline Reference<T>::operator napi_ref() const {
+  return _ref;
+}
+
+template <typename T>
+inline bool Reference<T>::operator ==(const Reference<T> &other) const {
+  HandleScope scope(_env);
+  return this->Value().StrictEquals(other.Value());
+}
+
+template <typename T>
+inline bool Reference<T>::operator !=(const Reference<T> &other) const {
+  return !this->operator ==(other);
+}
+
+template <typename T>
+inline Napi::Env Reference<T>::Env() const {
+  return Napi::Env(_env);
+}
+
+template <typename T>
+inline bool Reference<T>::IsEmpty() const {
+  return _ref == nullptr;
+}
+
+template <typename T>
+inline T Reference<T>::Value() const {
+  if (_ref == nullptr) {
+    return T(_env, nullptr);
+  }
+
+  napi_value value;
+  napi_status status = napi_get_reference_value(_env, _ref, &value);
+  NAPI_THROW_IF_FAILED(_env, status, T());
+  return T(_env, value);
+}
+
+template <typename T>
+inline uint32_t Reference<T>::Ref() {
+  uint32_t result;
+  napi_status status = napi_reference_ref(_env, _ref, &result);
+  NAPI_THROW_IF_FAILED(_env, status, 1);
+  return result;
+}
+
+template <typename T>
+inline uint32_t Reference<T>::Unref() {
+  uint32_t result;
+  napi_status status = napi_reference_unref(_env, _ref, &result);
+  NAPI_THROW_IF_FAILED(_env, status, 1);
+  return result;
+}
+
+template <typename T>
+inline void Reference<T>::Reset() {
+  if (_ref != nullptr) {
+    napi_status status = napi_delete_reference(_env, _ref);
+    NAPI_THROW_IF_FAILED_VOID(_env, status);
+    _ref = nullptr;
+  }
+}
+
+template <typename T>
+inline void Reference<T>::Reset(const T& value, uint32_t refcount) {
+  Reset();
+  _env = value.Env();
+
+  napi_value val = value;
+  if (val != nullptr) {
+    napi_status status = napi_create_reference(_env, value, refcount, &_ref);
+    NAPI_THROW_IF_FAILED_VOID(_env, status);
+  }
+}
+
+template <typename T>
+inline void Reference<T>::SuppressDestruct() {
+  _suppressDestruct = true;
+}
+
+template <typename T>
+inline Reference<T> Weak(T value) {
+  return Reference<T>::New(value, 0);
+}
+
+inline ObjectReference Weak(Object value) {
+  return Reference<Object>::New(value, 0);
+}
+
+inline FunctionReference Weak(Function value) {
+  return Reference<Function>::New(value, 0);
+}
+
+template <typename T>
+inline Reference<T> Persistent(T value) {
+  return Reference<T>::New(value, 1);
+}
+
+inline ObjectReference Persistent(Object value) {
+  return Reference<Object>::New(value, 1);
+}
+
+inline FunctionReference Persistent(Function value) {
+  return Reference<Function>::New(value, 1);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ObjectReference class
+////////////////////////////////////////////////////////////////////////////////
+
+inline ObjectReference::ObjectReference(): Reference<Object>() {
+}
+
+inline ObjectReference::ObjectReference(napi_env env, napi_ref ref): Reference<Object>(env, ref) {
+}
+
+inline ObjectReference::ObjectReference(Reference<Object>&& other)
+  : Reference<Object>(std::move(other)) {
+}
+
+inline ObjectReference& ObjectReference::operator =(Reference<Object>&& other) {
+  static_cast<Reference<Object>*>(this)->operator=(std::move(other));
+  return *this;
+}
+
+inline ObjectReference::ObjectReference(ObjectReference&& other)
+  : Reference<Object>(std::move(other)) {
+}
+
+inline ObjectReference& ObjectReference::operator =(ObjectReference&& other) {
+  static_cast<Reference<Object>*>(this)->operator=(std::move(other));
+  return *this;
+}
+
+inline ObjectReference::ObjectReference(const ObjectReference& other)
+  : Reference<Object>(other) {
+}
+
+inline Napi::Value ObjectReference::Get(const char* utf8name) const {
+  EscapableHandleScope scope(_env);
+  return scope.Escape(Value().Get(utf8name));
+}
+
+inline Napi::Value ObjectReference::Get(const std::string& utf8name) const {
+  EscapableHandleScope scope(_env);
+  return scope.Escape(Value().Get(utf8name));
+}
+
+inline void ObjectReference::Set(const char* utf8name, napi_value value) {
+  HandleScope scope(_env);
+  Value().Set(utf8name, value);
+}
+
+inline void ObjectReference::Set(const char* utf8name, Napi::Value value) {
+  HandleScope scope(_env);
+  Value().Set(utf8name, value);
+}
+
+inline void ObjectReference::Set(const char* utf8name, const char* utf8value) {
+  HandleScope scope(_env);
+  Value().Set(utf8name, utf8value);
+}
+
+inline void ObjectReference::Set(const char* utf8name, bool boolValue) {
+  HandleScope scope(_env);
+  Value().Set(utf8name, boolValue);
+}
+
+inline void ObjectReference::Set(const char* utf8name, double numberValue) {
+  HandleScope scope(_env);
+  Value().Set(utf8name, numberValue);
+}
+
+inline void ObjectReference::Set(const std::string& utf8name, napi_value value) {
+  HandleScope scope(_env);
+  Value().Set(utf8name, value);
+}
+
+inline void ObjectReference::Set(const std::string& utf8name, Napi::Value value) {
+  HandleScope scope(_env);
+  Value().Set(utf8name, value);
+}
+
+inline void ObjectReference::Set(const std::string& utf8name, std::string& utf8value) {
+  HandleScope scope(_env);
+  Value().Set(utf8name, utf8value);
+}
+
+inline void ObjectReference::Set(const std::string& utf8name, bool boolValue) {
+  HandleScope scope(_env);
+  Value().Set(utf8name, boolValue);
+}
+
+inline void ObjectReference::Set(const std::string& utf8name, double numberValue) {
+  HandleScope scope(_env);
+  Value().Set(utf8name, numberValue);
+}
+
+inline Napi::Value ObjectReference::Get(uint32_t index) const {
+  EscapableHandleScope scope(_env);
+  return scope.Escape(Value().Get(index));
+}
+
+inline void ObjectReference::Set(uint32_t index, napi_value value) {
+  HandleScope scope(_env);
+  Value().Set(index, value);
+}
+
+inline void ObjectReference::Set(uint32_t index, Napi::Value value) {
+  HandleScope scope(_env);
+  Value().Set(index, value);
+}
+
+inline void ObjectReference::Set(uint32_t index, const char* utf8value) {
+  HandleScope scope(_env);
+  Value().Set(index, utf8value);
+}
+
+inline void ObjectReference::Set(uint32_t index, const std::string& utf8value) {
+  HandleScope scope(_env);
+  Value().Set(index, utf8value);
+}
+
+inline void ObjectReference::Set(uint32_t index, bool boolValue) {
+  HandleScope scope(_env);
+  Value().Set(index, boolValue);
+}
+
+inline void ObjectReference::Set(uint32_t index, double numberValue) {
+  HandleScope scope(_env);
+  Value().Set(index, numberValue);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FunctionReference class
+////////////////////////////////////////////////////////////////////////////////
+
+inline FunctionReference::FunctionReference(): Reference<Function>() {
+}
+
+inline FunctionReference::FunctionReference(napi_env env, napi_ref ref)
+  : Reference<Function>(env, ref) {
+}
+
+inline FunctionReference::FunctionReference(Reference<Function>&& other)
+  : Reference<Function>(std::move(other)) {
+}
+
+inline FunctionReference& FunctionReference::operator =(Reference<Function>&& other) {
+  static_cast<Reference<Function>*>(this)->operator=(std::move(other));
+  return *this;
+}
+
+inline FunctionReference::FunctionReference(FunctionReference&& other)
+  : Reference<Function>(std::move(other)) {
+}
+
+inline FunctionReference& FunctionReference::operator =(FunctionReference&& other) {
+  static_cast<Reference<Function>*>(this)->operator=(std::move(other));
+  return *this;
+}
+
+inline Napi::Value FunctionReference::operator ()(
+    const std::initializer_list<napi_value>& args) const {
+  EscapableHandleScope scope(_env);
+  return scope.Escape(Value()(args));
+}
+
+inline Napi::Value FunctionReference::Call(const std::initializer_list<napi_value>& args) const {
+  EscapableHandleScope scope(_env);
+  Napi::Value result = Value().Call(args);
+  if (scope.Env().IsExceptionPending()) {
+    return Value();
+  }
+  return scope.Escape(result);
+}
+
+inline Napi::Value FunctionReference::Call(const std::vector<napi_value>& args) const {
+  EscapableHandleScope scope(_env);
+  Napi::Value result = Value().Call(args);
+  if (scope.Env().IsExceptionPending()) {
+    return Value();
+  }
+  return scope.Escape(result);
+}
+
+inline Napi::Value FunctionReference::Call(
+    napi_value recv, const std::initializer_list<napi_value>& args) const {
+  EscapableHandleScope scope(_env);
+  Napi::Value result = Value().Call(recv, args);
+  if (scope.Env().IsExceptionPending()) {
+    return Value();
+  }
+  return scope.Escape(result);
+}
+
+inline Napi::Value FunctionReference::Call(
+    napi_value recv, const std::vector<napi_value>& args) const {
+  EscapableHandleScope scope(_env);
+  Napi::Value result = Value().Call(recv, args);
+  if (scope.Env().IsExceptionPending()) {
+    return Value();
+  }
+  return scope.Escape(result);
+}
+
+inline Napi::Value FunctionReference::Call(
+    napi_value recv, size_t argc, const napi_value* args) const {
+  EscapableHandleScope scope(_env);
+  Napi::Value result = Value().Call(recv, argc, args);
+  if (scope.Env().IsExceptionPending()) {
+    return Value();
+  }
+  return scope.Escape(result);
+}
+
+inline Napi::Value FunctionReference::MakeCallback(
+    napi_value recv,
+    const std::initializer_list<napi_value>& args,
+    napi_async_context context) const {
+  EscapableHandleScope scope(_env);
+  Napi::Value result = Value().MakeCallback(recv, args, context);
+  if (scope.Env().IsExceptionPending()) {
+    return Value();
+  }
+  return scope.Escape(result);
+}
+
+inline Napi::Value FunctionReference::MakeCallback(
+    napi_value recv,
+    const std::vector<napi_value>& args,
+    napi_async_context context) const {
+  EscapableHandleScope scope(_env);
+  Napi::Value result = Value().MakeCallback(recv, args, context);
+  if (scope.Env().IsExceptionPending()) {
+    return Value();
+  }
+  return scope.Escape(result);
+}
+
+inline Napi::Value FunctionReference::MakeCallback(
+    napi_value recv,
+    size_t argc,
+    const napi_value* args,
+    napi_async_context context) const {
+  EscapableHandleScope scope(_env);
+  Napi::Value result = Value().MakeCallback(recv, argc, args, context);
+  if (scope.Env().IsExceptionPending()) {
+    return Value();
+  }
+  return scope.Escape(result);
+}
+
+inline Object FunctionReference::New(const std::initializer_list<napi_value>& args) const {
+  EscapableHandleScope scope(_env);
+  return scope.Escape(Value().New(args)).As<Object>();
+}
+
+inline Object FunctionReference::New(const std::vector<napi_value>& args) const {
+  EscapableHandleScope scope(_env);
+  return scope.Escape(Value().New(args)).As<Object>();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// CallbackInfo class
+////////////////////////////////////////////////////////////////////////////////
+
+inline CallbackInfo::CallbackInfo(napi_env env, napi_callback_info info)
+    : _env(env), _info(info), _this(nullptr), _dynamicArgs(nullptr), _data(nullptr) {
+  _argc = _staticArgCount;
+  _argv = _staticArgs;
+  napi_status status = napi_get_cb_info(env, info, &_argc, _argv, &_this, &_data);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+
+  if (_argc > _staticArgCount) {
+    // Use either a fixed-size array (on the stack) or a dynamically-allocated
+    // array (on the heap) depending on the number of args.
+    _dynamicArgs = new napi_value[_argc];
+    _argv = _dynamicArgs;
+
+    status = napi_get_cb_info(env, info, &_argc, _argv, nullptr, nullptr);
+    NAPI_THROW_IF_FAILED_VOID(_env, status);
+  }
+}
+
+inline CallbackInfo::~CallbackInfo() {
+  if (_dynamicArgs != nullptr) {
+    delete[] _dynamicArgs;
+  }
+}
+
+inline Value CallbackInfo::NewTarget() const {
+  napi_value newTarget;
+  napi_status status = napi_get_new_target(_env, _info, &newTarget);
+  NAPI_THROW_IF_FAILED(_env, status, Value());
+  return Value(_env, newTarget);
+}
+
+inline bool CallbackInfo::IsConstructCall() const {
+  return !NewTarget().IsEmpty();
+}
+
+inline Napi::Env CallbackInfo::Env() const {
+  return Napi::Env(_env);
+}
+
+inline size_t CallbackInfo::Length() const {
+  return _argc;
+}
+
+inline const Value CallbackInfo::operator [](size_t index) const {
+  return index < _argc ? Value(_env, _argv[index]) : Env().Undefined();
+}
+
+inline Value CallbackInfo::This() const {
+  if (_this == nullptr) {
+    return Env().Undefined();
+  }
+  return Object(_env, _this);
+}
+
+inline void* CallbackInfo::Data() const {
+  return _data;
+}
+
+inline void CallbackInfo::SetData(void* data) {
+  _data = data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PropertyDescriptor class
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename Getter>
+inline PropertyDescriptor
+PropertyDescriptor::Accessor(Napi::Env env,
+                             Napi::Object object,
+                             const char* utf8name,
+                             Getter getter,
+                             napi_property_attributes attributes,
+                             void* data) {
+  typedef details::CallbackData<Getter, Napi::Value> CbData;
+  auto callbackData = new CbData({ getter, data });
+
+  napi_status status = AttachData(env, object, callbackData);
+  if (status != napi_ok) {
+    delete callbackData;
+    NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
+  }
+
+  return PropertyDescriptor({
+    utf8name,
+    nullptr,
+    nullptr,
+    CbData::Wrapper,
+    nullptr,
+    nullptr,
+    attributes,
+    callbackData
+  });
+}
+
+template <typename Getter>
+inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
+                                                       Napi::Object object,
+                                                       const std::string& utf8name,
+                                                       Getter getter,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  return Accessor(env, object, utf8name.c_str(), getter, attributes, data);
+}
+
+template <typename Getter>
+inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
+                                                       Napi::Object object,
+                                                       Name name,
+                                                       Getter getter,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  typedef details::CallbackData<Getter, Napi::Value> CbData;
+  auto callbackData = new CbData({ getter, data });
+
+  napi_status status = AttachData(env, object, callbackData);
+  if (status != napi_ok) {
+    delete callbackData;
+    NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
+  }
+
+  return PropertyDescriptor({
+    nullptr,
+    name,
+    nullptr,
+    CbData::Wrapper,
+    nullptr,
+    nullptr,
+    attributes,
+    callbackData
+  });
+}
+
+template <typename Getter, typename Setter>
+inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
+                                                       Napi::Object object,
+                                                       const char* utf8name,
+                                                       Getter getter,
+                                                       Setter setter,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  typedef details::AccessorCallbackData<Getter, Setter> CbData;
+  auto callbackData = new CbData({ getter, setter, data });
+
+  napi_status status = AttachData(env, object, callbackData);
+  if (status != napi_ok) {
+    delete callbackData;
+    NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
+  }
+
+  return PropertyDescriptor({
+    utf8name,
+    nullptr,
+    nullptr,
+    CbData::GetterWrapper,
+    CbData::SetterWrapper,
+    nullptr,
+    attributes,
+    callbackData
+  });
+}
+
+template <typename Getter, typename Setter>
+inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
+                                                       Napi::Object object,
+                                                       const std::string& utf8name,
+                                                       Getter getter,
+                                                       Setter setter,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  return Accessor(env, object, utf8name.c_str(), getter, setter, attributes, data);
+}
+
+template <typename Getter, typename Setter>
+inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
+                                                       Napi::Object object,
+                                                       Name name,
+                                                       Getter getter,
+                                                       Setter setter,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  typedef details::AccessorCallbackData<Getter, Setter> CbData;
+  auto callbackData = new CbData({ getter, setter, data });
+
+  napi_status status = AttachData(env, object, callbackData);
+  if (status != napi_ok) {
+    delete callbackData;
+    NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
+  }
+
+  return PropertyDescriptor({
+    nullptr,
+    name,
+    nullptr,
+    CbData::GetterWrapper,
+    CbData::SetterWrapper,
+    nullptr,
+    attributes,
+    callbackData
+  });
+}
+
+template <typename Callable>
+inline PropertyDescriptor PropertyDescriptor::Function(Napi::Env env,
+                                                       Napi::Object /*object*/,
+                                                       const char* utf8name,
+                                                       Callable cb,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  return PropertyDescriptor({
+    utf8name,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    Napi::Function::New(env, cb, utf8name, data),
+    attributes,
+    nullptr
+  });
+}
+
+template <typename Callable>
+inline PropertyDescriptor PropertyDescriptor::Function(Napi::Env env,
+                                                       Napi::Object object,
+                                                       const std::string& utf8name,
+                                                       Callable cb,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  return Function(env, object, utf8name.c_str(), cb, attributes, data);
+}
+
+template <typename Callable>
+inline PropertyDescriptor PropertyDescriptor::Function(Napi::Env env,
+                                                       Napi::Object /*object*/,
+                                                       Name name,
+                                                       Callable cb,
+                                                       napi_property_attributes attributes,
+                                                       void* data) {
+  return PropertyDescriptor({
+    nullptr,
+    name,
+    nullptr,
+    nullptr,
+    nullptr,
+    Napi::Function::New(env, cb, nullptr, data),
+    attributes,
+    nullptr
+  });
+}
+
+inline PropertyDescriptor PropertyDescriptor::Value(const char* utf8name,
+                                                    napi_value value,
+                                                    napi_property_attributes attributes) {
+  return PropertyDescriptor({
+    utf8name, nullptr, nullptr, nullptr, nullptr, value, attributes, nullptr
+  });
+}
+
+inline PropertyDescriptor PropertyDescriptor::Value(const std::string& utf8name,
+                                                    napi_value value,
+                                                    napi_property_attributes attributes) {
+  return Value(utf8name.c_str(), value, attributes);
+}
+
+inline PropertyDescriptor PropertyDescriptor::Value(napi_value name,
+                                                    napi_value value,
+                                                    napi_property_attributes attributes) {
+  return PropertyDescriptor({
+    nullptr, name, nullptr, nullptr, nullptr, value, attributes, nullptr
+  });
+}
+
+inline PropertyDescriptor PropertyDescriptor::Value(Name name,
+                                                    Napi::Value value,
+                                                    napi_property_attributes attributes) {
+  napi_value nameValue = name;
+  napi_value valueValue = value;
+  return PropertyDescriptor::Value(nameValue, valueValue, attributes);
+}
+
+inline PropertyDescriptor::PropertyDescriptor(napi_property_descriptor desc)
+  : _desc(desc) {
+}
+
+inline PropertyDescriptor::operator napi_property_descriptor&() {
+  return _desc;
+}
+
+inline PropertyDescriptor::operator const napi_property_descriptor&() const {
+  return _desc;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ObjectWrap<T> class
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
+  napi_env env = callbackInfo.Env();
+  napi_value wrapper = callbackInfo.This();
+  napi_status status;
+  napi_ref ref;
+  T* instance = static_cast<T*>(this);
+  status = napi_wrap(env, wrapper, instance, FinalizeCallback, nullptr, &ref);
+  NAPI_THROW_IF_FAILED_VOID(env, status);
+
+  Reference<Object>* instanceRef = instance;
+  *instanceRef = Reference<Object>(env, ref);
+}
+
+template<typename T>
+inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
+  T* unwrapped;
+  napi_status status = napi_unwrap(wrapper.Env(), wrapper, reinterpret_cast<void**>(&unwrapped));
+  NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr);
+  return unwrapped;
+}
+
+template <typename T>
+inline Function
+ObjectWrap<T>::DefineClass(Napi::Env env,
+                           const char* utf8name,
+                           const size_t props_count,
+                           const napi_property_descriptor* descriptors,
+                           void* data) {
+  napi_status status;
+  std::vector<napi_property_descriptor> props(props_count);
+
+  // We copy the descriptors to a local array because before defining the class
+  // we must replace static method property descriptors with value property
+  // descriptors such that the value is a function-valued `napi_value` created
+  // with `CreateFunction()`.
+  //
+  // This replacement could be made for instance methods as well, but V8 aborts
+  // if we do that, because it expects methods defined on the prototype template
+  // to have `FunctionTemplate`s.
+  for (size_t index = 0; index < props_count; index++) {
+    props[index] = descriptors[index];
+    napi_property_descriptor* prop = &props[index];
+    if (prop->method == T::StaticMethodCallbackWrapper) {
+      status = CreateFunction(env,
+               utf8name,
+               prop->method,
+               static_cast<StaticMethodCallbackData*>(prop->data),
+               &(prop->value));
+      NAPI_THROW_IF_FAILED(env, status, Function());
+      prop->method = nullptr;
+      prop->data = nullptr;
+    } else if (prop->method == T::StaticVoidMethodCallbackWrapper) {
+      status = CreateFunction(env,
+               utf8name,
+               prop->method,
+               static_cast<StaticVoidMethodCallbackData*>(prop->data),
+               &(prop->value));
+      NAPI_THROW_IF_FAILED(env, status, Function());
+      prop->method = nullptr;
+      prop->data = nullptr;
+    }
+  }
+
+  napi_value value;
+  status = napi_define_class(env,
+                             utf8name,
+                             NAPI_AUTO_LENGTH,
+                             T::ConstructorCallbackWrapper,
+                             data,
+                             props_count,
+                             props.data(),
+                             &value);
+  NAPI_THROW_IF_FAILED(env, status, Function());
+
+  // After defining the class we iterate once more over the property descriptors
+  // and attach the data associated with accessors and instance methods to the
+  // newly created JavaScript class.
+  for (size_t idx = 0; idx < props_count; idx++) {
+    const napi_property_descriptor* prop = &props[idx];
+
+    if (prop->getter == T::StaticGetterCallbackWrapper ||
+        prop->setter == T::StaticSetterCallbackWrapper) {
+      status = Napi::details::AttachData(env,
+                          value,
+                          static_cast<StaticAccessorCallbackData*>(prop->data));
+      NAPI_THROW_IF_FAILED(env, status, Function());
+    } else if (prop->getter == T::InstanceGetterCallbackWrapper ||
+        prop->setter == T::InstanceSetterCallbackWrapper) {
+      status = Napi::details::AttachData(env,
+                          value,
+                          static_cast<InstanceAccessorCallbackData*>(prop->data));
+      NAPI_THROW_IF_FAILED(env, status, Function());
+    } else if (prop->method != nullptr && !(prop->attributes & napi_static)) {
+      if (prop->method == T::InstanceVoidMethodCallbackWrapper) {
+        status = Napi::details::AttachData(env,
+                      value,
+                      static_cast<InstanceVoidMethodCallbackData*>(prop->data));
+        NAPI_THROW_IF_FAILED(env, status, Function());
+      } else if (prop->method == T::InstanceMethodCallbackWrapper) {
+        status = Napi::details::AttachData(env,
+                          value,
+                          static_cast<InstanceMethodCallbackData*>(prop->data));
+        NAPI_THROW_IF_FAILED(env, status, Function());
+      }
+    }
+  }
+
+  return Function(env, value);
+}
+
+template <typename T>
+inline Function ObjectWrap<T>::DefineClass(
+    Napi::Env env,
+    const char* utf8name,
+    const std::initializer_list<ClassPropertyDescriptor<T>>& properties,
+    void* data) {
+  return DefineClass(env,
+          utf8name,
+          properties.size(),
+          reinterpret_cast<const napi_property_descriptor*>(properties.begin()),
+          data);
+}
+
+template <typename T>
+inline Function ObjectWrap<T>::DefineClass(
+    Napi::Env env,
+    const char* utf8name,
+    const std::vector<ClassPropertyDescriptor<T>>& properties,
+    void* data) {
+  return DefineClass(env,
+           utf8name,
+           properties.size(),
+           reinterpret_cast<const napi_property_descriptor*>(properties.data()),
+           data);
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
+    const char* utf8name,
+    StaticVoidMethodCallback method,
+    napi_property_attributes attributes,
+    void* data) {
+  StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
+
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.utf8name = utf8name;
+  desc.method = T::StaticVoidMethodCallbackWrapper;
+  desc.data = callbackData;
+  desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
+    const char* utf8name,
+    StaticMethodCallback method,
+    napi_property_attributes attributes,
+    void* data) {
+  StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
+
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.utf8name = utf8name;
+  desc.method = T::StaticMethodCallbackWrapper;
+  desc.data = callbackData;
+  desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
+    Symbol name,
+    StaticVoidMethodCallback method,
+    napi_property_attributes attributes,
+    void* data) {
+  StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
+
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.name = name;
+  desc.method = T::StaticVoidMethodCallbackWrapper;
+  desc.data = callbackData;
+  desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
+    Symbol name,
+    StaticMethodCallback method,
+    napi_property_attributes attributes,
+    void* data) {
+  StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
+
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.name = name;
+  desc.method = T::StaticMethodCallbackWrapper;
+  desc.data = callbackData;
+  desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
+    const char* utf8name,
+    StaticGetterCallback getter,
+    StaticSetterCallback setter,
+    napi_property_attributes attributes,
+    void* data) {
+  StaticAccessorCallbackData* callbackData =
+    new StaticAccessorCallbackData({ getter, setter, data });
+
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.utf8name = utf8name;
+  desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
+  desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
+  desc.data = callbackData;
+  desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
+    Symbol name,
+    StaticGetterCallback getter,
+    StaticSetterCallback setter,
+    napi_property_attributes attributes,
+    void* data) {
+  StaticAccessorCallbackData* callbackData =
+    new StaticAccessorCallbackData({ getter, setter, data });
+
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.name = name;
+  desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
+  desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
+  desc.data = callbackData;
+  desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
+    const char* utf8name,
+    InstanceVoidMethodCallback method,
+    napi_property_attributes attributes,
+    void* data) {
+  InstanceVoidMethodCallbackData* callbackData =
+    new InstanceVoidMethodCallbackData({ method, data});
+
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.utf8name = utf8name;
+  desc.method = T::InstanceVoidMethodCallbackWrapper;
+  desc.data = callbackData;
+  desc.attributes = attributes;
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
+    const char* utf8name,
+    InstanceMethodCallback method,
+    napi_property_attributes attributes,
+    void* data) {
+  InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
+
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.utf8name = utf8name;
+  desc.method = T::InstanceMethodCallbackWrapper;
+  desc.data = callbackData;
+  desc.attributes = attributes;
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
+    Symbol name,
+    InstanceVoidMethodCallback method,
+    napi_property_attributes attributes,
+    void* data) {
+  InstanceVoidMethodCallbackData* callbackData =
+    new InstanceVoidMethodCallbackData({ method, data});
+
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.name = name;
+  desc.method = T::InstanceVoidMethodCallbackWrapper;
+  desc.data = callbackData;
+  desc.attributes = attributes;
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
+    Symbol name,
+    InstanceMethodCallback method,
+    napi_property_attributes attributes,
+    void* data) {
+  InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
+
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.name = name;
+  desc.method = T::InstanceMethodCallbackWrapper;
+  desc.data = callbackData;
+  desc.attributes = attributes;
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
+    const char* utf8name,
+    InstanceGetterCallback getter,
+    InstanceSetterCallback setter,
+    napi_property_attributes attributes,
+    void* data) {
+  InstanceAccessorCallbackData* callbackData =
+    new InstanceAccessorCallbackData({ getter, setter, data });
+
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.utf8name = utf8name;
+  desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
+  desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
+  desc.data = callbackData;
+  desc.attributes = attributes;
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
+    Symbol name,
+    InstanceGetterCallback getter,
+    InstanceSetterCallback setter,
+    napi_property_attributes attributes,
+    void* data) {
+  InstanceAccessorCallbackData* callbackData =
+    new InstanceAccessorCallbackData({ getter, setter, data });
+
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.name = name;
+  desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
+  desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
+  desc.data = callbackData;
+  desc.attributes = attributes;
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(const char* utf8name,
+    Napi::Value value, napi_property_attributes attributes) {
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.utf8name = utf8name;
+  desc.value = value;
+  desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(Symbol name,
+    Napi::Value value, napi_property_attributes attributes) {
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.name = name;
+  desc.value = value;
+  desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
+    const char* utf8name,
+    Napi::Value value,
+    napi_property_attributes attributes) {
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.utf8name = utf8name;
+  desc.value = value;
+  desc.attributes = attributes;
+  return desc;
+}
+
+template <typename T>
+inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
+    Symbol name,
+    Napi::Value value,
+    napi_property_attributes attributes) {
+  napi_property_descriptor desc = napi_property_descriptor();
+  desc.name = name;
+  desc.value = value;
+  desc.attributes = attributes;
+  return desc;
+}
+
+template <typename T>
+inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
+    napi_env env,
+    napi_callback_info info) {
+  napi_value new_target;
+  napi_status status = napi_get_new_target(env, info, &new_target);
+  if (status != napi_ok) return nullptr;
+
+  bool isConstructCall = (new_target != nullptr);
+  if (!isConstructCall) {
+    napi_throw_type_error(env, nullptr, "Class constructors cannot be invoked without 'new'");
+    return nullptr;
+  }
+
+  T* instance;
+  napi_value wrapper = details::WrapCallback([&] {
+    CallbackInfo callbackInfo(env, info);
+    instance = new T(callbackInfo);
+    return callbackInfo.This();
+  });
+
+  return wrapper;
+}
+
+template <typename T>
+inline napi_value ObjectWrap<T>::StaticVoidMethodCallbackWrapper(
+    napi_env env,
+    napi_callback_info info) {
+  return details::WrapCallback([&] {
+    CallbackInfo callbackInfo(env, info);
+    StaticVoidMethodCallbackData* callbackData =
+      reinterpret_cast<StaticVoidMethodCallbackData*>(callbackInfo.Data());
+    callbackInfo.SetData(callbackData->data);
+    callbackData->callback(callbackInfo);
+    return nullptr;
+  });
+}
+
+template <typename T>
+inline napi_value ObjectWrap<T>::StaticMethodCallbackWrapper(
+    napi_env env,
+    napi_callback_info info) {
+  return details::WrapCallback([&] {
+    CallbackInfo callbackInfo(env, info);
+    StaticMethodCallbackData* callbackData =
+      reinterpret_cast<StaticMethodCallbackData*>(callbackInfo.Data());
+    callbackInfo.SetData(callbackData->data);
+    return callbackData->callback(callbackInfo);
+  });
+}
+
+template <typename T>
+inline napi_value ObjectWrap<T>::StaticGetterCallbackWrapper(
+    napi_env env,
+    napi_callback_info info) {
+  return details::WrapCallback([&] {
+    CallbackInfo callbackInfo(env, info);
+    StaticAccessorCallbackData* callbackData =
+      reinterpret_cast<StaticAccessorCallbackData*>(callbackInfo.Data());
+    callbackInfo.SetData(callbackData->data);
+    return callbackData->getterCallback(callbackInfo);
+  });
+}
+
+template <typename T>
+inline napi_value ObjectWrap<T>::StaticSetterCallbackWrapper(
+    napi_env env,
+    napi_callback_info info) {
+  return details::WrapCallback([&] {
+    CallbackInfo callbackInfo(env, info);
+    StaticAccessorCallbackData* callbackData =
+      reinterpret_cast<StaticAccessorCallbackData*>(callbackInfo.Data());
+    callbackInfo.SetData(callbackData->data);
+    callbackData->setterCallback(callbackInfo, callbackInfo[0]);
+    return nullptr;
+  });
+}
+
+template <typename T>
+inline napi_value ObjectWrap<T>::InstanceVoidMethodCallbackWrapper(
+    napi_env env,
+    napi_callback_info info) {
+  return details::WrapCallback([&] {
+    CallbackInfo callbackInfo(env, info);
+    InstanceVoidMethodCallbackData* callbackData =
+      reinterpret_cast<InstanceVoidMethodCallbackData*>(callbackInfo.Data());
+    callbackInfo.SetData(callbackData->data);
+    T* instance = Unwrap(callbackInfo.This().As<Object>());
+    auto cb = callbackData->callback;
+    (instance->*cb)(callbackInfo);
+    return nullptr;
+  });
+}
+
+template <typename T>
+inline napi_value ObjectWrap<T>::InstanceMethodCallbackWrapper(
+    napi_env env,
+    napi_callback_info info) {
+  return details::WrapCallback([&] {
+    CallbackInfo callbackInfo(env, info);
+    InstanceMethodCallbackData* callbackData =
+      reinterpret_cast<InstanceMethodCallbackData*>(callbackInfo.Data());
+    callbackInfo.SetData(callbackData->data);
+    T* instance = Unwrap(callbackInfo.This().As<Object>());
+    auto cb = callbackData->callback;
+    return (instance->*cb)(callbackInfo);
+  });
+}
+
+template <typename T>
+inline napi_value ObjectWrap<T>::InstanceGetterCallbackWrapper(
+    napi_env env,
+    napi_callback_info info) {
+  return details::WrapCallback([&] {
+    CallbackInfo callbackInfo(env, info);
+    InstanceAccessorCallbackData* callbackData =
+      reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
+    callbackInfo.SetData(callbackData->data);
+    T* instance = Unwrap(callbackInfo.This().As<Object>());
+    auto cb = callbackData->getterCallback;
+    return (instance->*cb)(callbackInfo);
+  });
+}
+
+template <typename T>
+inline napi_value ObjectWrap<T>::InstanceSetterCallbackWrapper(
+    napi_env env,
+    napi_callback_info info) {
+  return details::WrapCallback([&] {
+    CallbackInfo callbackInfo(env, info);
+    InstanceAccessorCallbackData* callbackData =
+      reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
+    callbackInfo.SetData(callbackData->data);
+    T* instance = Unwrap(callbackInfo.This().As<Object>());
+    auto cb = callbackData->setterCallback;
+    (instance->*cb)(callbackInfo, callbackInfo[0]);
+    return nullptr;
+  });
+}
+
+template <typename T>
+inline void ObjectWrap<T>::FinalizeCallback(napi_env /*env*/, void* data, void* /*hint*/) {
+  T* instance = reinterpret_cast<T*>(data);
+  delete instance;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// HandleScope class
+////////////////////////////////////////////////////////////////////////////////
+
+inline HandleScope::HandleScope(napi_env env, napi_handle_scope scope)
+    : _env(env), _scope(scope) {
+}
+
+inline HandleScope::HandleScope(Napi::Env env) : _env(env) {
+  napi_status status = napi_open_handle_scope(_env, &_scope);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline HandleScope::~HandleScope() {
+  napi_close_handle_scope(_env, _scope);
+}
+
+inline HandleScope::operator napi_handle_scope() const {
+  return _scope;
+}
+
+inline Napi::Env HandleScope::Env() const {
+  return Napi::Env(_env);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// EscapableHandleScope class
+////////////////////////////////////////////////////////////////////////////////
+
+inline EscapableHandleScope::EscapableHandleScope(
+  napi_env env, napi_escapable_handle_scope scope) : _env(env), _scope(scope) {
+}
+
+inline EscapableHandleScope::EscapableHandleScope(Napi::Env env) : _env(env) {
+  napi_status status = napi_open_escapable_handle_scope(_env, &_scope);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline EscapableHandleScope::~EscapableHandleScope() {
+  napi_close_escapable_handle_scope(_env, _scope);
+}
+
+inline EscapableHandleScope::operator napi_escapable_handle_scope() const {
+  return _scope;
+}
+
+inline Napi::Env EscapableHandleScope::Env() const {
+  return Napi::Env(_env);
+}
+
+inline Value EscapableHandleScope::Escape(napi_value escapee) {
+  napi_value result;
+  napi_status status = napi_escape_handle(_env, _scope, escapee, &result);
+  NAPI_THROW_IF_FAILED(_env, status, Value());
+  return Value(_env, result);
+}
+
+
+#if (NAPI_VERSION > 2)
+////////////////////////////////////////////////////////////////////////////////
+// CallbackScope class
+////////////////////////////////////////////////////////////////////////////////
+
+inline CallbackScope::CallbackScope(
+  napi_env env, napi_callback_scope scope) : _env(env), _scope(scope) {
+}
+
+inline CallbackScope::CallbackScope(napi_env env, napi_async_context context)
+    : _env(env) {
+  napi_status status = napi_open_callback_scope(
+      _env, Object::New(env), context, &_scope);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline CallbackScope::~CallbackScope() {
+  napi_close_callback_scope(_env, _scope);
+}
+
+inline CallbackScope::operator napi_callback_scope() const {
+  return _scope;
+}
+
+inline Napi::Env CallbackScope::Env() const {
+  return Napi::Env(_env);
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// AsyncContext class
+////////////////////////////////////////////////////////////////////////////////
+
+inline AsyncContext::AsyncContext(napi_env env, const char* resource_name)
+  : AsyncContext(env, resource_name, Object::New(env)) {
+}
+
+inline AsyncContext::AsyncContext(napi_env env,
+		                  const char* resource_name,
+                                  const Object& resource)
+  : _env(env),
+    _context(nullptr) {
+  napi_value resource_id;
+  napi_status status = napi_create_string_utf8(
+      _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+
+  status = napi_async_init(_env, resource, resource_id, &_context);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline AsyncContext::~AsyncContext() {
+  if (_context != nullptr) {
+    napi_async_destroy(_env, _context);
+    _context = nullptr;
+  }
+}
+
+inline AsyncContext::AsyncContext(AsyncContext&& other) {
+  _env = other._env;
+  other._env = nullptr;
+  _context = other._context;
+  other._context = nullptr;
+}
+
+inline AsyncContext& AsyncContext::operator =(AsyncContext&& other) {
+  _env = other._env;
+  other._env = nullptr;
+  _context = other._context;
+  other._context = nullptr;
+  return *this;
+}
+
+inline AsyncContext::operator napi_async_context() const {
+  return _context;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// AsyncWorker class
+////////////////////////////////////////////////////////////////////////////////
+
+inline AsyncWorker::AsyncWorker(const Function& callback)
+  : AsyncWorker(callback, "generic") {
+}
+
+inline AsyncWorker::AsyncWorker(const Function& callback,
+                                const char* resource_name)
+  : AsyncWorker(callback, resource_name, Object::New(callback.Env())) {
+}
+
+inline AsyncWorker::AsyncWorker(const Function& callback,
+                                const char* resource_name,
+                                const Object& resource)
+  : AsyncWorker(Object::New(callback.Env()),
+                callback,
+                resource_name,
+                resource) {
+}
+
+inline AsyncWorker::AsyncWorker(const Object& receiver,
+                                const Function& callback)
+  : AsyncWorker(receiver, callback, "generic") {
+}
+
+inline AsyncWorker::AsyncWorker(const Object& receiver,
+                                const Function& callback,
+                                const char* resource_name)
+  : AsyncWorker(receiver,
+                callback,
+                resource_name,
+                Object::New(callback.Env())) {
+}
+
+inline AsyncWorker::AsyncWorker(const Object& receiver,
+                                const Function& callback,
+                                const char* resource_name,
+                                const Object& resource)
+  : _env(callback.Env()),
+    _receiver(Napi::Persistent(receiver)),
+    _callback(Napi::Persistent(callback)),
+    _suppress_destruct(false) {
+  napi_value resource_id;
+  napi_status status = napi_create_string_latin1(
+      _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+
+  status = napi_create_async_work(_env, resource, resource_id, OnExecute,
+                                  OnWorkComplete, this, &_work);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline AsyncWorker::AsyncWorker(Napi::Env env)
+  : AsyncWorker(env, "generic") {
+}
+
+inline AsyncWorker::AsyncWorker(Napi::Env env,
+                                const char* resource_name)
+  : AsyncWorker(env, resource_name, Object::New(env)) {
+}
+
+inline AsyncWorker::AsyncWorker(Napi::Env env,
+                                const char* resource_name,
+                                const Object& resource)
+  : _env(env),
+    _receiver(),
+    _callback(),
+    _suppress_destruct(false) {
+  napi_value resource_id;
+  napi_status status = napi_create_string_latin1(
+      _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+
+  status = napi_create_async_work(_env, resource, resource_id, OnExecute,
+                                  OnWorkComplete, this, &_work);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline AsyncWorker::~AsyncWorker() {
+  if (_work != nullptr) {
+    napi_delete_async_work(_env, _work);
+    _work = nullptr;
+  }
+}
+
+inline void AsyncWorker::Destroy() {
+  delete this;
+}
+
+inline AsyncWorker::AsyncWorker(AsyncWorker&& other) {
+  _env = other._env;
+  other._env = nullptr;
+  _work = other._work;
+  other._work = nullptr;
+  _receiver = std::move(other._receiver);
+  _callback = std::move(other._callback);
+  _error = std::move(other._error);
+  _suppress_destruct = other._suppress_destruct;
+}
+
+inline AsyncWorker& AsyncWorker::operator =(AsyncWorker&& other) {
+  _env = other._env;
+  other._env = nullptr;
+  _work = other._work;
+  other._work = nullptr;
+  _receiver = std::move(other._receiver);
+  _callback = std::move(other._callback);
+  _error = std::move(other._error);
+  _suppress_destruct = other._suppress_destruct;
+  return *this;
+}
+
+inline AsyncWorker::operator napi_async_work() const {
+  return _work;
+}
+
+inline Napi::Env AsyncWorker::Env() const {
+  return Napi::Env(_env);
+}
+
+inline void AsyncWorker::Queue() {
+  napi_status status = napi_queue_async_work(_env, _work);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline void AsyncWorker::Cancel() {
+  napi_status status = napi_cancel_async_work(_env, _work);
+  NAPI_THROW_IF_FAILED_VOID(_env, status);
+}
+
+inline ObjectReference& AsyncWorker::Receiver() {
+  return _receiver;
+}
+
+inline FunctionReference& AsyncWorker::Callback() {
+  return _callback;
+}
+
+inline void AsyncWorker::SuppressDestruct() {
+  _suppress_destruct = true;
+}
+
+inline void AsyncWorker::OnOK() {
+  if (!_callback.IsEmpty()) {
+    _callback.Call(_receiver.Value(), GetResult(_callback.Env()));
+  }
+}
+
+inline void AsyncWorker::OnError(const Error& e) {
+  if (!_callback.IsEmpty()) {
+    _callback.Call(_receiver.Value(), std::initializer_list<napi_value>{ e.Value() });
+  }
+}
+
+inline void AsyncWorker::SetError(const std::string& error) {
+  _error = error;
+}
+
+inline std::vector<napi_value> AsyncWorker::GetResult(Napi::Env /*env*/) {
+  return {};
+}
+// The OnExecute method receives an napi_env argument. However, do NOT
+// use it within this method, as it does not run on the main thread and must
+// not run any method that would cause JavaScript to run. In practice, this
+// means that almost any use of napi_env will be incorrect.
+inline void AsyncWorker::OnExecute(napi_env /*DO_NOT_USE*/, void* this_pointer) {
+  AsyncWorker* self = static_cast<AsyncWorker*>(this_pointer);
+#ifdef NAPI_CPP_EXCEPTIONS
+  try {
+    self->Execute();
+  } catch (const std::exception& e) {
+    self->SetError(e.what());
+  }
+#else // NAPI_CPP_EXCEPTIONS
+  self->Execute();
+#endif // NAPI_CPP_EXCEPTIONS
+}
+
+inline void AsyncWorker::OnWorkComplete(
+    napi_env /*env*/, napi_status status, void* this_pointer) {
+  AsyncWorker* self = static_cast<AsyncWorker*>(this_pointer);
+  if (status != napi_cancelled) {
+    HandleScope scope(self->_env);
+    details::WrapCallback([&] {
+      if (self->_error.size() == 0) {
+        self->OnOK();
+      }
+      else {
+        self->OnError(Error::New(self->_env, self->_error));
+      }
+      return nullptr;
+    });
+  }
+  if (!self->_suppress_destruct) {
+    self->Destroy();
+  }
+}
+
+#if (NAPI_VERSION > 3)
+////////////////////////////////////////////////////////////////////////////////
+// ThreadSafeFunction class
+////////////////////////////////////////////////////////////////////////////////
+
+// static
+template <typename ResourceString>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                  const Function& callback,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount) {
+  return New(env, callback, Object(), resourceName, maxQueueSize,
+             initialThreadCount);
+}
+
+// static
+template <typename ResourceString, typename ContextType>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                  const Function& callback,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  ContextType* context) {
+  return New(env, callback, Object(), resourceName, maxQueueSize,
+             initialThreadCount, context);
+}
+
+// static
+template <typename ResourceString, typename Finalizer>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                  const Function& callback,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  Finalizer finalizeCallback) {
+  return New(env, callback, Object(), resourceName, maxQueueSize,
+             initialThreadCount, finalizeCallback);
+}
+
+// static
+template <typename ResourceString, typename Finalizer,
+          typename FinalizerDataType>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                  const Function& callback,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  Finalizer finalizeCallback,
+                                  FinalizerDataType* data) {
+  return New(env, callback, Object(), resourceName, maxQueueSize,
+             initialThreadCount, finalizeCallback, data);
+}
+
+// static
+template <typename ResourceString, typename ContextType, typename Finalizer>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                  const Function& callback,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  ContextType* context,
+                                  Finalizer finalizeCallback) {
+  return New(env, callback, Object(), resourceName, maxQueueSize,
+             initialThreadCount, context, finalizeCallback);
+}
+
+// static
+template <typename ResourceString, typename ContextType,
+          typename Finalizer, typename FinalizerDataType>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                                  const Function& callback,
+                                                  ResourceString resourceName,
+                                                  size_t maxQueueSize,
+                                                  size_t initialThreadCount,
+                                                  ContextType* context,
+                                                  Finalizer finalizeCallback,
+                                                  FinalizerDataType* data) {
+  return New(env, callback, Object(), resourceName, maxQueueSize,
+             initialThreadCount, context, finalizeCallback, data);
+}
+
+// static
+template <typename ResourceString>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                  const Function& callback,
+                                  const Object& resource,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount) {
+  return New(env, callback, resource, resourceName, maxQueueSize,
+             initialThreadCount, static_cast<void*>(nullptr) /* context */);
+}
+
+// static
+template <typename ResourceString, typename ContextType>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                  const Function& callback,
+                                  const Object& resource,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  ContextType* context) {
+  return New(env, callback, resource, resourceName, maxQueueSize,
+             initialThreadCount, context,
+             [](Env, ContextType*) {} /* empty finalizer */);
+}
+
+// static
+template <typename ResourceString, typename Finalizer>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                  const Function& callback,
+                                  const Object& resource,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  Finalizer finalizeCallback) {
+  return New(env, callback, resource, resourceName, maxQueueSize,
+             initialThreadCount, static_cast<void*>(nullptr) /* context */,
+             finalizeCallback, static_cast<void*>(nullptr) /* data */,
+             details::ThreadSafeFinalize<void, Finalizer>::Wrapper);
+}
+
+// static
+template <typename ResourceString, typename Finalizer,
+          typename FinalizerDataType>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                  const Function& callback,
+                                  const Object& resource,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  Finalizer finalizeCallback,
+                                  FinalizerDataType* data) {
+  return New(env, callback, resource, resourceName, maxQueueSize,
+             initialThreadCount, static_cast<void*>(nullptr) /* context */,
+             finalizeCallback, data,
+             details::ThreadSafeFinalize<
+                 void, Finalizer, FinalizerDataType>::FinalizeWrapperWithData);
+}
+
+// static
+template <typename ResourceString, typename ContextType, typename Finalizer>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                  const Function& callback,
+                                  const Object& resource,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  ContextType* context,
+                                  Finalizer finalizeCallback) {
+  return New(env, callback, resource, resourceName, maxQueueSize,
+             initialThreadCount, context, finalizeCallback,
+             static_cast<void*>(nullptr) /* data */,
+             details::ThreadSafeFinalize<
+                 ContextType, Finalizer>::FinalizeWrapperWithContext);
+}
+
+// static
+template <typename ResourceString, typename ContextType,
+          typename Finalizer, typename FinalizerDataType>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                                  const Function& callback,
+                                                  const Object& resource,
+                                                  ResourceString resourceName,
+                                                  size_t maxQueueSize,
+                                                  size_t initialThreadCount,
+                                                  ContextType* context,
+                                                  Finalizer finalizeCallback,
+                                                  FinalizerDataType* data) {
+  return New(env, callback, resource, resourceName, maxQueueSize,
+             initialThreadCount, context, finalizeCallback, data,
+             details::ThreadSafeFinalize<ContextType, Finalizer,
+                 FinalizerDataType>::FinalizeFinalizeWrapperWithDataAndContext);
+}
+
+inline ThreadSafeFunction::ThreadSafeFunction()
+  : _tsfn(new napi_threadsafe_function(nullptr)) {
+}
+
+inline ThreadSafeFunction::ThreadSafeFunction(
+    napi_threadsafe_function tsfn)
+  : _tsfn(new napi_threadsafe_function(tsfn)) {
+}
+
+inline ThreadSafeFunction::ThreadSafeFunction(ThreadSafeFunction&& other)
+  : _tsfn(std::move(other._tsfn)) {
+  other._tsfn.reset();
+}
+
+inline ThreadSafeFunction& ThreadSafeFunction::operator =(
+    ThreadSafeFunction&& other) {
+  if (*_tsfn != nullptr) {
+    Error::Fatal("ThreadSafeFunction::operator =",
+        "You cannot assign a new TSFN because existing one is still alive.");
+    return *this;
+  }
+  _tsfn = std::move(other._tsfn);
+  other._tsfn.reset();
+  return *this;
+}
+
+inline napi_status ThreadSafeFunction::BlockingCall() const {
+  return CallInternal(nullptr, napi_tsfn_blocking);
+}
+
+template <typename Callback>
+inline napi_status ThreadSafeFunction::BlockingCall(
+    Callback callback) const {
+  return CallInternal(new CallbackWrapper(callback), napi_tsfn_blocking);
+}
+
+template <typename DataType, typename Callback>
+inline napi_status ThreadSafeFunction::BlockingCall(
+    DataType* data, Callback callback) const {
+  auto wrapper = [data, callback](Env env, Function jsCallback) {
+    callback(env, jsCallback, data);
+  };
+  return CallInternal(new CallbackWrapper(wrapper), napi_tsfn_blocking);
+}
+
+inline napi_status ThreadSafeFunction::NonBlockingCall() const {
+  return CallInternal(nullptr, napi_tsfn_nonblocking);
+}
+
+template <typename Callback>
+inline napi_status ThreadSafeFunction::NonBlockingCall(
+    Callback callback) const {
+  return CallInternal(new CallbackWrapper(callback), napi_tsfn_nonblocking);
+}
+
+template <typename DataType, typename Callback>
+inline napi_status ThreadSafeFunction::NonBlockingCall(
+    DataType* data, Callback callback) const {
+  auto wrapper = [data, callback](Env env, Function jsCallback) {
+    callback(env, jsCallback, data);
+  };
+  return CallInternal(new CallbackWrapper(wrapper), napi_tsfn_nonblocking);
+}
+
+inline napi_status ThreadSafeFunction::Acquire() const {
+  return napi_acquire_threadsafe_function(*_tsfn);
+}
+
+inline napi_status ThreadSafeFunction::Release() {
+  return napi_release_threadsafe_function(*_tsfn, napi_tsfn_release);
+}
+
+inline napi_status ThreadSafeFunction::Abort() {
+  return napi_release_threadsafe_function(*_tsfn, napi_tsfn_abort);
+}
+
+inline ThreadSafeFunction::ConvertibleContext
+ThreadSafeFunction::GetContext() const {
+  void* context;
+  napi_get_threadsafe_function_context(*_tsfn, &context);
+  return ConvertibleContext({ context });
+}
+
+// static
+template <typename ResourceString, typename ContextType,
+          typename Finalizer, typename FinalizerDataType>
+inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
+                                                  const Function& callback,
+                                                  const Object& resource,
+                                                  ResourceString resourceName,
+                                                  size_t maxQueueSize,
+                                                  size_t initialThreadCount,
+                                                  ContextType* context,
+                                                  Finalizer finalizeCallback,
+                                                  FinalizerDataType* data,
+                                                  napi_finalize wrapper) {
+  static_assert(details::can_make_string<ResourceString>::value
+      || std::is_convertible<ResourceString, napi_value>::value,
+      "Resource name should be convertible to the string type");
+
+  ThreadSafeFunction tsfn;
+  auto* finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
+      FinalizerDataType>({ data, finalizeCallback, tsfn._tsfn.get() });
+  napi_status status = napi_create_threadsafe_function(env, callback, resource,
+      Value::From(env, resourceName), maxQueueSize, initialThreadCount,
+      finalizeData, wrapper, context, CallJS, tsfn._tsfn.get());
+  if (status != napi_ok) {
+    delete finalizeData;
+    NAPI_THROW_IF_FAILED(env, status, ThreadSafeFunction());
+  }
+
+  return tsfn;
+}
+
+inline napi_status ThreadSafeFunction::CallInternal(
+    CallbackWrapper* callbackWrapper,
+    napi_threadsafe_function_call_mode mode) const {
+  napi_status status = napi_call_threadsafe_function(
+      *_tsfn, callbackWrapper, mode);
+  if (status != napi_ok && callbackWrapper != nullptr) {
+    delete callbackWrapper;
+  }
+
+  return status;
+}
+
+// static
+inline void ThreadSafeFunction::CallJS(napi_env env,
+                                       napi_value jsCallback,
+                                       void* /* context */,
+                                       void* data) {
+  if (env == nullptr && jsCallback == nullptr) {
+    return;
+  }
+
+  if (data != nullptr) {
+    auto* callbackWrapper = static_cast<CallbackWrapper*>(data);
+    (*callbackWrapper)(env, Function(env, jsCallback));
+    delete callbackWrapper;
+  } else if (jsCallback != nullptr) {
+    Function(env, jsCallback).Call({});
+  }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Memory Management class
+////////////////////////////////////////////////////////////////////////////////
+
+inline int64_t MemoryManagement::AdjustExternalMemory(Env env, int64_t change_in_bytes) {
+  int64_t result;
+  napi_status status = napi_adjust_external_memory(env, change_in_bytes, &result);
+  NAPI_THROW_IF_FAILED(env, status, 0);
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Version Management class
+////////////////////////////////////////////////////////////////////////////////
+
+inline uint32_t VersionManagement::GetNapiVersion(Env env) {
+  uint32_t result;
+  napi_status status = napi_get_version(env, &result);
+  NAPI_THROW_IF_FAILED(env, status, 0);
+  return result;
+}
+
+inline const napi_node_version* VersionManagement::GetNodeVersion(Env env) {
+  const napi_node_version* result;
+  napi_status status = napi_get_node_version(env, &result);
+  NAPI_THROW_IF_FAILED(env, status, 0);
+  return result;
+}
+
+} // namespace Napi
+
+#endif // SRC_NAPI_INL_H_
diff --git a/src/3rdparty/node-addon-api/napi.h b/src/3rdparty/node-addon-api/napi.h
new file mode 100644
index 00000000000..7bbea198dd3
--- /dev/null
+++ b/src/3rdparty/node-addon-api/napi.h
@@ -0,0 +1,2053 @@
+#ifndef SRC_NAPI_H_
+#define SRC_NAPI_H_
+
+#include <node_api.h>
+#include <functional>
+#include <initializer_list>
+#include <memory>
+#include <string>
+#include <vector>
+
+// VS2015 RTM has bugs with constexpr, so require min of VS2015 Update 3 (known good version)
+#if !defined(_MSC_VER) || _MSC_FULL_VER >= 190024210
+#define NAPI_HAS_CONSTEXPR 1
+#endif
+
+// VS2013 does not support char16_t literal strings, so we'll work around it using wchar_t strings
+// and casting them. This is safe as long as the character sizes are the same.
+#if defined(_MSC_VER) && _MSC_VER <= 1800
+static_assert(sizeof(char16_t) == sizeof(wchar_t), "Size mismatch between char16_t and wchar_t");
+#define NAPI_WIDE_TEXT(x) reinterpret_cast<char16_t*>(L ## x)
+#else
+#define NAPI_WIDE_TEXT(x) u ## x
+#endif
+
+// If C++ exceptions are not explicitly enabled or disabled, enable them
+// if exceptions were enabled in the compiler settings.
+#if !defined(NAPI_CPP_EXCEPTIONS) && !defined(NAPI_DISABLE_CPP_EXCEPTIONS)
+  #if defined(_CPPUNWIND) || defined (__EXCEPTIONS)
+    #define NAPI_CPP_EXCEPTIONS
+  #else
+    #error Exception support not detected. \
+      Define either NAPI_CPP_EXCEPTIONS or NAPI_DISABLE_CPP_EXCEPTIONS.
+  #endif
+#endif
+
+#ifdef _NOEXCEPT
+  #define NAPI_NOEXCEPT _NOEXCEPT
+#else
+  #define NAPI_NOEXCEPT noexcept
+#endif
+
+#ifdef NAPI_CPP_EXCEPTIONS
+
+// When C++ exceptions are enabled, Errors are thrown directly. There is no need
+// to return anything after the throw statements. The variadic parameter is an
+// optional return value that is ignored.
+// We need _VOID versions of the macros to avoid warnings resulting from
+// leaving the NAPI_THROW_* `...` argument empty.
+
+#define NAPI_THROW(e, ...)  throw e
+#define NAPI_THROW_VOID(e)  throw e
+
+#define NAPI_THROW_IF_FAILED(env, status, ...)           \
+  if ((status) != napi_ok) throw Napi::Error::New(env);
+
+#define NAPI_THROW_IF_FAILED_VOID(env, status)           \
+  if ((status) != napi_ok) throw Napi::Error::New(env);
+
+#else // NAPI_CPP_EXCEPTIONS
+
+// When C++ exceptions are disabled, Errors are thrown as JavaScript exceptions,
+// which are pending until the callback returns to JS.  The variadic parameter
+// is an optional return value; usually it is an empty result.
+// We need _VOID versions of the macros to avoid warnings resulting from
+// leaving the NAPI_THROW_* `...` argument empty.
+
+#define NAPI_THROW(e, ...)                               \
+  do {                                                   \
+    (e).ThrowAsJavaScriptException();                    \
+    return __VA_ARGS__;                                  \
+  } while (0)
+
+#define NAPI_THROW_VOID(e)                               \
+  do {                                                   \
+    (e).ThrowAsJavaScriptException();                    \
+    return;                                              \
+  } while (0)
+
+#define NAPI_THROW_IF_FAILED(env, status, ...)           \
+  if ((status) != napi_ok) {                             \
+    Napi::Error::New(env).ThrowAsJavaScriptException();  \
+    return __VA_ARGS__;                                  \
+  }
+
+#define NAPI_THROW_IF_FAILED_VOID(env, status)           \
+  if ((status) != napi_ok) {                             \
+    Napi::Error::New(env).ThrowAsJavaScriptException();  \
+    return;                                              \
+  }
+
+#endif // NAPI_CPP_EXCEPTIONS
+
+#define NAPI_FATAL_IF_FAILED(status, location, message)  \
+  do {                                                   \
+    if ((status) != napi_ok) {                           \
+      Napi::Error::Fatal((location), (message));         \
+    }                                                    \
+  } while (0)
+
+////////////////////////////////////////////////////////////////////////////////
+/// N-API C++ Wrapper Classes
+///
+/// These classes wrap the "N-API" ABI-stable C APIs for Node.js, providing a
+/// C++ object model and C++ exception-handling semantics with low overhead.
+/// The wrappers are all header-only so that they do not affect the ABI.
+////////////////////////////////////////////////////////////////////////////////
+namespace Napi {
+
+  // Forward declarations
+  class Env;
+  class Value;
+  class Boolean;
+  class Number;
+// currently experimental guard with version of NAPI_VERSION that it is
+// released in once it is no longer experimental
+#if (NAPI_VERSION > 2147483646)
+  class BigInt;
+#endif  // NAPI_EXPERIMENTAL
+  class String;
+  class Object;
+  class Array;
+  class Function;
+  template <typename T> class Buffer;
+  class Error;
+  class PropertyDescriptor;
+  class CallbackInfo;
+  template <typename T> class Reference;
+  class TypedArray;
+  template <typename T> class TypedArrayOf;
+
+  typedef TypedArrayOf<int8_t> Int8Array;     ///< Typed-array of signed 8-bit integers
+  typedef TypedArrayOf<uint8_t> Uint8Array;   ///< Typed-array of unsigned 8-bit integers
+  typedef TypedArrayOf<int16_t> Int16Array;   ///< Typed-array of signed 16-bit integers
+  typedef TypedArrayOf<uint16_t> Uint16Array; ///< Typed-array of unsigned 16-bit integers
+  typedef TypedArrayOf<int32_t> Int32Array;   ///< Typed-array of signed 32-bit integers
+  typedef TypedArrayOf<uint32_t> Uint32Array; ///< Typed-array of unsigned 32-bit integers
+  typedef TypedArrayOf<float> Float32Array;   ///< Typed-array of 32-bit floating-point values
+  typedef TypedArrayOf<double> Float64Array;  ///< Typed-array of 64-bit floating-point values
+// currently experimental guard with version of NAPI_VERSION that it is
+// released in once it is no longer experimental
+#if (NAPI_VERSION > 2147483646)
+  typedef TypedArrayOf<int64_t> BigInt64Array;   ///< Typed array of signed 64-bit integers
+  typedef TypedArrayOf<uint64_t> BigUint64Array; ///< Typed array of unsigned 64-bit integers
+#endif  // NAPI_EXPERIMENTAL
+
+  /// Defines the signature of a N-API C++ module's registration callback (init) function.
+  typedef Object (*ModuleRegisterCallback)(Env env, Object exports);
+
+  class MemoryManagement;
+
+  /// Environment for N-API values and operations.
+  ///
+  /// All N-API values and operations must be associated with an environment. An environment
+  /// instance is always provided to callback functions; that environment must then be used for any
+  /// creation of N-API values or other N-API operations within the callback. (Many methods infer
+  /// the environment from the `this` instance that the method is called on.)
+  ///
+  /// In the future, multiple environments per process may be supported, although current
+  /// implementations only support one environment per process.
+  ///
+  /// In the V8 JavaScript engine, a N-API environment approximately corresponds to an Isolate.
+  class Env {
+  public:
+    Env(napi_env env);
+
+    operator napi_env() const;
+
+    Object Global() const;
+    Value Undefined() const;
+    Value Null() const;
+
+    bool IsExceptionPending() const;
+    Error GetAndClearPendingException();
+
+  private:
+    napi_env _env;
+  };
+
+  /// A JavaScript value of unknown type.
+  ///
+  /// For type-specific operations, convert to one of the Value subclasses using a `To*` or `As()`
+  /// method. The `To*` methods do type coercion; the `As()` method does not.
+  ///
+  ///     Napi::Value value = ...
+  ///     if (!value.IsString()) throw Napi::TypeError::New(env, "Invalid arg...");
+  ///     Napi::String str = value.As<Napi::String>(); // Cast to a string value
+  ///
+  ///     Napi::Value anotherValue = ...
+  ///     bool isTruthy = anotherValue.ToBoolean(); // Coerce to a boolean value
+  class Value {
+  public:
+    Value();                               ///< Creates a new _empty_ Value instance.
+    Value(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
+
+    /// Creates a JS value from a C++ primitive.
+    ///
+    /// `value` may be any of:
+    /// - bool
+    /// - Any integer type
+    /// - Any floating point type
+    /// - const char* (encoded using UTF-8, null-terminated)
+    /// - const char16_t* (encoded using UTF-16-LE, null-terminated)
+    /// - std::string (encoded using UTF-8)
+    /// - std::u16string
+    /// - napi::Value
+    /// - napi_value
+    template <typename T>
+    static Value From(napi_env env, const T& value);
+
+    /// Converts to a N-API value primitive.
+    ///
+    /// If the instance is _empty_, this returns `nullptr`.
+    operator napi_value() const;
+
+    /// Tests if this value strictly equals another value.
+    bool operator ==(const Value& other) const;
+
+    /// Tests if this value does not strictly equal another value.
+    bool operator !=(const Value& other) const;
+
+    /// Tests if this value strictly equals another value.
+    bool StrictEquals(const Value& other) const;
+
+    /// Gets the environment the value is associated with.
+    Napi::Env Env() const;
+
+    /// Checks if the value is empty (uninitialized).
+    ///
+    /// An empty value is invalid, and most attempts to perform an operation on an empty value
+    /// will result in an exception. Note an empty value is distinct from JavaScript `null` or
+    /// `undefined`, which are valid values.
+    ///
+    /// When C++ exceptions are disabled at compile time, a method with a `Value` return type may
+    /// return an empty value to indicate a pending exception. So when not using C++ exceptions,
+    /// callers should check whether the value is empty before attempting to use it.
+    bool IsEmpty() const;
+
+    napi_valuetype Type() const; ///< Gets the type of the value.
+
+    bool IsUndefined() const;   ///< Tests if a value is an undefined JavaScript value.
+    bool IsNull() const;        ///< Tests if a value is a null JavaScript value.
+    bool IsBoolean() const;     ///< Tests if a value is a JavaScript boolean.
+    bool IsNumber() const;      ///< Tests if a value is a JavaScript number.
+// currently experimental guard with version of NAPI_VERSION that it is
+// released in once it is no longer experimental
+#if (NAPI_VERSION > 2147483646)
+    bool IsBigInt() const;      ///< Tests if a value is a JavaScript bigint.
+#endif  // NAPI_EXPERIMENTAL
+    bool IsString() const;      ///< Tests if a value is a JavaScript string.
+    bool IsSymbol() const;      ///< Tests if a value is a JavaScript symbol.
+    bool IsArray() const;       ///< Tests if a value is a JavaScript array.
+    bool IsArrayBuffer() const; ///< Tests if a value is a JavaScript array buffer.
+    bool IsTypedArray() const;  ///< Tests if a value is a JavaScript typed array.
+    bool IsObject() const;      ///< Tests if a value is a JavaScript object.
+    bool IsFunction() const;    ///< Tests if a value is a JavaScript function.
+    bool IsPromise() const;     ///< Tests if a value is a JavaScript promise.
+    bool IsDataView() const;    ///< Tests if a value is a JavaScript data view.
+    bool IsBuffer() const;      ///< Tests if a value is a Node buffer.
+    bool IsExternal() const;    ///< Tests if a value is a pointer to external data.
+
+    /// Casts to another type of `Napi::Value`, when the actual type is known or assumed.
+    ///
+    /// This conversion does NOT coerce the type. Calling any methods inappropriate for the actual
+    /// value type will throw `Napi::Error`.
+    template <typename T> T As() const;
+
+    Boolean ToBoolean() const; ///< Coerces a value to a JavaScript boolean.
+    Number ToNumber() const;   ///< Coerces a value to a JavaScript number.
+    String ToString() const;   ///< Coerces a value to a JavaScript string.
+    Object ToObject() const;   ///< Coerces a value to a JavaScript object.
+
+  protected:
+    /// !cond INTERNAL
+    napi_env _env;
+    napi_value _value;
+    /// !endcond
+  };
+
+  /// A JavaScript boolean value.
+  class Boolean : public Value {
+  public:
+    static Boolean New(
+      napi_env env, ///< N-API environment
+      bool value    ///< Boolean value
+    );
+
+    Boolean();                               ///< Creates a new _empty_ Boolean instance.
+    Boolean(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
+
+    operator bool() const; ///< Converts a Boolean value to a boolean primitive.
+    bool Value() const;    ///< Converts a Boolean value to a boolean primitive.
+  };
+
+  /// A JavaScript number value.
+  class Number : public Value {
+  public:
+    static Number New(
+      napi_env env, ///< N-API environment
+      double value  ///< Number value
+    );
+
+    Number();                               ///< Creates a new _empty_ Number instance.
+    Number(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
+
+    operator int32_t() const;  ///< Converts a Number value to a 32-bit signed integer value.
+    operator uint32_t() const; ///< Converts a Number value to a 32-bit unsigned integer value.
+    operator int64_t() const;  ///< Converts a Number value to a 64-bit signed integer value.
+    operator float() const;    ///< Converts a Number value to a 32-bit floating-point value.
+    operator double() const;   ///< Converts a Number value to a 64-bit floating-point value.
+
+    int32_t Int32Value() const;   ///< Converts a Number value to a 32-bit signed integer value.
+    uint32_t Uint32Value() const; ///< Converts a Number value to a 32-bit unsigned integer value.
+    int64_t Int64Value() const;   ///< Converts a Number value to a 64-bit signed integer value.
+    float FloatValue() const;     ///< Converts a Number value to a 32-bit floating-point value.
+    double DoubleValue() const;   ///< Converts a Number value to a 64-bit floating-point value.
+  };
+
+// currently experimental guard with version of NAPI_VERSION that it is
+// released in once it is no longer experimental
+#if (NAPI_VERSION > 2147483646)
+  /// A JavaScript bigint value.
+  class BigInt : public Value {
+  public:
+    static BigInt New(
+      napi_env env, ///< N-API environment
+      int64_t value ///< Number value
+    );
+    static BigInt New(
+      napi_env env,  ///< N-API environment
+      uint64_t value ///< Number value
+    );
+
+    /// Creates a new BigInt object using a specified sign bit and a
+    /// specified list of digits/words.
+    /// The resulting number is calculated as:
+    /// (-1)^sign_bit * (words[0] * (2^64)^0 + words[1] * (2^64)^1 + ...)
+    static BigInt New(
+      napi_env env,          ///< N-API environment
+      int sign_bit,          ///< Sign bit. 1 if negative.
+      size_t word_count,     ///< Number of words in array
+      const uint64_t* words  ///< Array of words
+    );
+
+    BigInt();                               ///< Creates a new _empty_ BigInt instance.
+    BigInt(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
+
+    int64_t Int64Value(bool* lossless) const;   ///< Converts a BigInt value to a 64-bit signed integer value.
+    uint64_t Uint64Value(bool* lossless) const; ///< Converts a BigInt value to a 64-bit unsigned integer value.
+
+    size_t WordCount() const; ///< The number of 64-bit words needed to store the result of ToWords().
+
+    /// Writes the contents of this BigInt to a specified memory location.
+    /// `sign_bit` must be provided and will be set to 1 if this BigInt is negative.
+    /// `*word_count` has to be initialized to the length of the `words` array.
+    /// Upon return, it will be set to the actual number of words that would
+    /// be needed to store this BigInt (i.e. the return value of `WordCount()`).
+    void ToWords(int* sign_bit, size_t* word_count, uint64_t* words);
+  };
+#endif  // NAPI_EXPERIMENTAL
+
+  /// A JavaScript string or symbol value (that can be used as a property name).
+  class Name : public Value {
+  public:
+    Name();                               ///< Creates a new _empty_ Name instance.
+    Name(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
+  };
+
+  /// A JavaScript string value.
+  class String : public Name {
+  public:
+    /// Creates a new String value from a UTF-8 encoded C++ string.
+    static String New(
+      napi_env env,            ///< N-API environment
+      const std::string& value ///< UTF-8 encoded C++ string
+    );
+
+    /// Creates a new String value from a UTF-16 encoded C++ string.
+    static String New(
+      napi_env env,               ///< N-API environment
+      const std::u16string& value ///< UTF-16 encoded C++ string
+    );
+
+    /// Creates a new String value from a UTF-8 encoded C string.
+    static String New(
+      napi_env env,     ///< N-API environment
+      const char* value ///< UTF-8 encoded null-terminated C string
+    );
+
+    /// Creates a new String value from a UTF-16 encoded C string.
+    static String New(
+      napi_env env,         ///< N-API environment
+      const char16_t* value ///< UTF-16 encoded null-terminated C string
+    );
+
+    /// Creates a new String value from a UTF-8 encoded C string with specified length.
+    static String New(
+      napi_env env,      ///< N-API environment
+      const char* value, ///< UTF-8 encoded C string (not necessarily null-terminated)
+      size_t length      ///< length of the string in bytes
+    );
+
+    /// Creates a new String value from a UTF-16 encoded C string with specified length.
+    static String New(
+      napi_env env,          ///< N-API environment
+      const char16_t* value, ///< UTF-16 encoded C string (not necessarily null-terminated)
+      size_t length          ///< Length of the string in 2-byte code units
+    );
+
+    /// Creates a new String based on the original object's type.
+    ///
+    /// `value` may be any of:
+    /// - const char* (encoded using UTF-8, null-terminated)
+    /// - const char16_t* (encoded using UTF-16-LE, null-terminated)
+    /// - std::string (encoded using UTF-8)
+    /// - std::u16string
+    template <typename T>
+    static String From(napi_env env, const T& value);
+
+    String();                               ///< Creates a new _empty_ String instance.
+    String(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
+
+    operator std::string() const;      ///< Converts a String value to a UTF-8 encoded C++ string.
+    operator std::u16string() const;   ///< Converts a String value to a UTF-16 encoded C++ string.
+    std::string Utf8Value() const;     ///< Converts a String value to a UTF-8 encoded C++ string.
+    std::u16string Utf16Value() const; ///< Converts a String value to a UTF-16 encoded C++ string.
+  };
+
+  /// A JavaScript symbol value.
+  class Symbol : public Name {
+  public:
+    /// Creates a new Symbol value with an optional description.
+    static Symbol New(
+      napi_env env,                     ///< N-API environment
+      const char* description = nullptr ///< Optional UTF-8 encoded null-terminated C string
+                                        ///  describing the symbol
+    );
+
+    /// Creates a new Symbol value with a description.
+    static Symbol New(
+      napi_env env,                  ///< N-API environment
+      const std::string& description ///< UTF-8 encoded C++ string describing the symbol
+    );
+
+    /// Creates a new Symbol value with a description.
+    static Symbol New(
+      napi_env env,      ///< N-API environment
+      String description ///< String value describing the symbol
+    );
+
+    /// Creates a new Symbol value with a description.
+    static Symbol New(
+      napi_env env,          ///< N-API environment
+      napi_value description ///< String value describing the symbol
+    );
+
+    /// Get a public Symbol (e.g. Symbol.iterator).
+    static Symbol WellKnown(napi_env, const std::string& name);
+
+    Symbol();                               ///< Creates a new _empty_ Symbol instance.
+    Symbol(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
+  };
+
+  /// A JavaScript object value.
+  class Object : public Value {
+  public:
+    /// Enables property and element assignments using indexing syntax.
+    ///
+    /// Example:
+    ///
+    ///     Napi::Value propertyValue = object1['A'];
+    ///     object2['A'] = propertyValue;
+    ///     Napi::Value elementValue = array[0];
+    ///     array[1] = elementValue;
+    template <typename Key>
+    class PropertyLValue {
+    public:
+      /// Converts an L-value to a value.
+      operator Value() const;
+
+      /// Assigns a value to the property. The type of value can be
+      /// anything supported by `Object::Set`.
+      template <typename ValueType>
+      PropertyLValue& operator =(ValueType value);
+
+    private:
+      PropertyLValue() = delete;
+      PropertyLValue(Object object, Key key);
+      napi_env _env;
+      napi_value _object;
+      Key _key;
+
+      friend class Napi::Object;
+    };
+
+    /// Creates a new Object value.
+    static Object New(
+      napi_env env ///< N-API environment
+    );
+
+    Object();                               ///< Creates a new _empty_ Object instance.
+    Object(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
+
+    /// Gets or sets a named property.
+    PropertyLValue<std::string> operator [](
+      const char* utf8name ///< UTF-8 encoded null-terminated property name
+    );
+
+    /// Gets or sets a named property.
+    PropertyLValue<std::string> operator [](
+      const std::string& utf8name ///< UTF-8 encoded property name
+    );
+
+    /// Gets or sets an indexed property or array element.
+    PropertyLValue<uint32_t> operator [](
+      uint32_t index /// Property / element index
+    );
+
+    /// Gets a named property.
+    Value operator [](
+      const char* utf8name ///< UTF-8 encoded null-terminated property name
+    ) const;
+
+    /// Gets a named property.
+    Value operator [](
+      const std::string& utf8name ///< UTF-8 encoded property name
+    ) const;
+
+    /// Gets an indexed property or array element.
+    Value operator [](
+      uint32_t index ///< Property / element index
+    ) const;
+
+    /// Checks whether a property is present.
+    bool Has(
+      napi_value key ///< Property key primitive
+    ) const;
+
+    /// Checks whether a property is present.
+    bool Has(
+      Value key ///< Property key
+    ) const;
+
+    /// Checks whether a named property is present.
+    bool Has(
+      const char* utf8name ///< UTF-8 encoded null-terminated property name
+    ) const;
+
+    /// Checks whether a named property is present.
+    bool Has(
+      const std::string& utf8name ///< UTF-8 encoded property name
+    ) const;
+
+    /// Checks whether a own property is present.
+    bool HasOwnProperty(
+      napi_value key ///< Property key primitive
+    ) const;
+
+    /// Checks whether a own property is present.
+    bool HasOwnProperty(
+      Value key ///< Property key
+    ) const;
+
+    /// Checks whether a own property is present.
+    bool HasOwnProperty(
+      const char* utf8name ///< UTF-8 encoded null-terminated property name
+    ) const;
+
+    /// Checks whether a own property is present.
+    bool HasOwnProperty(
+      const std::string& utf8name ///< UTF-8 encoded property name
+    ) const;
+
+    /// Gets a property.
+    Value Get(
+      napi_value key ///< Property key primitive
+    ) const;
+
+    /// Gets a property.
+    Value Get(
+      Value key ///< Property key
+    ) const;
+
+    /// Gets a named property.
+    Value Get(
+      const char* utf8name ///< UTF-8 encoded null-terminated property name
+    ) const;
+
+    /// Gets a named property.
+    Value Get(
+      const std::string& utf8name ///< UTF-8 encoded property name
+    ) const;
+
+    /// Sets a property.
+    template <typename ValueType>
+    void Set(
+      napi_value key,  ///< Property key primitive
+      const ValueType& value ///< Property value primitive
+    );
+
+    /// Sets a property.
+    template <typename ValueType>
+    void Set(
+      Value key,  ///< Property key
+      const ValueType& value ///< Property value
+    );
+
+    /// Sets a named property.
+    template <typename ValueType>
+    void Set(
+      const char* utf8name, ///< UTF-8 encoded null-terminated property name
+      const ValueType& value
+    );
+
+    /// Sets a named property.
+    template <typename ValueType>
+    void Set(
+      const std::string& utf8name, ///< UTF-8 encoded property name
+      const ValueType& value             ///< Property value primitive
+    );
+
+    /// Delete property.
+    bool Delete(
+      napi_value key ///< Property key primitive
+    );
+
+    /// Delete property.
+    bool Delete(
+      Value key ///< Property key
+    );
+
+    /// Delete property.
+    bool Delete(
+      const char* utf8name ///< UTF-8 encoded null-terminated property name
+    );
+
+    /// Delete property.
+    bool Delete(
+      const std::string& utf8name ///< UTF-8 encoded property name
+    );
+
+    /// Checks whether an indexed property is present.
+    bool Has(
+      uint32_t index ///< Property / element index
+    ) const;
+
+    /// Gets an indexed property or array element.
+    Value Get(
+      uint32_t index ///< Property / element index
+    ) const;
+
+    /// Sets an indexed property or array element.
+    template <typename ValueType>
+    void Set(
+      uint32_t index,  ///< Property / element index
+      const ValueType& value ///< Property value primitive
+    );
+
+    /// Deletes an indexed property or array element.
+    bool Delete(
+      uint32_t index ///< Property / element index
+    );
+
+    Array GetPropertyNames() const; ///< Get all property names
+
+    /// Defines a property on the object.
+    void DefineProperty(
+      const PropertyDescriptor& property ///< Descriptor for the property to be defined
+    );
+
+    /// Defines properties on the object.
+    void DefineProperties(
+      const std::initializer_list<PropertyDescriptor>& properties
+        ///< List of descriptors for the properties to be defined
+    );
+
+    /// Defines properties on the object.
+    void DefineProperties(
+      const std::vector<PropertyDescriptor>& properties
+        ///< Vector of descriptors for the properties to be defined
+    );
+
+    /// Checks if an object is an instance created by a constructor function.
+    ///
+    /// This is equivalent to the JavaScript `instanceof` operator.
+    bool InstanceOf(
+      const Function& constructor ///< Constructor function
+    ) const;
+  };
+
+  template <typename T>
+  class External : public Value {
+  public:
+    static External New(napi_env env, T* data);
+
+    // Finalizer must implement `void operator()(Env env, T* data)`.
+    template <typename Finalizer>
+    static External New(napi_env env,
+                        T* data,
+                        Finalizer finalizeCallback);
+    // Finalizer must implement `void operator()(Env env, T* data, Hint* hint)`.
+    template <typename Finalizer, typename Hint>
+    static External New(napi_env env,
+                        T* data,
+                        Finalizer finalizeCallback,
+                        Hint* finalizeHint);
+
+    External();
+    External(napi_env env, napi_value value);
+
+    T* Data() const;
+  };
+
+  class Array : public Object {
+  public:
+    static Array New(napi_env env);
+    static Array New(napi_env env, size_t length);
+
+    Array();
+    Array(napi_env env, napi_value value);
+
+    uint32_t Length() const;
+  };
+
+  /// A JavaScript array buffer value.
+  class ArrayBuffer : public Object {
+  public:
+    /// Creates a new ArrayBuffer instance over a new automatically-allocated buffer.
+    static ArrayBuffer New(
+      napi_env env,     ///< N-API environment
+      size_t byteLength ///< Length of the buffer to be allocated, in bytes
+    );
+
+    /// Creates a new ArrayBuffer instance, using an external buffer with specified byte length.
+    static ArrayBuffer New(
+      napi_env env,       ///< N-API environment
+      void* externalData, ///< Pointer to the external buffer to be used by the array
+      size_t byteLength   ///< Length of the external buffer to be used by the array, in bytes
+    );
+
+    /// Creates a new ArrayBuffer instance, using an external buffer with specified byte length.
+    template <typename Finalizer>
+    static ArrayBuffer New(
+      napi_env env,              ///< N-API environment
+      void* externalData,        ///< Pointer to the external buffer to be used by the array
+      size_t byteLength,         ///< Length of the external buffer to be used by the array,
+                                 ///  in bytes
+      Finalizer finalizeCallback ///< Function to be called when the array buffer is destroyed;
+                                 ///  must implement `void operator()(Env env, void* externalData)`
+    );
+
+    /// Creates a new ArrayBuffer instance, using an external buffer with specified byte length.
+    template <typename Finalizer, typename Hint>
+    static ArrayBuffer New(
+      napi_env env,               ///< N-API environment
+      void* externalData,         ///< Pointer to the external buffer to be used by the array
+      size_t byteLength,          ///< Length of the external buffer to be used by the array,
+                                  ///  in bytes
+      Finalizer finalizeCallback, ///< Function to be called when the array buffer is destroyed;
+                                  ///  must implement `void operator()(Env env, void* externalData, Hint* hint)`
+      Hint* finalizeHint          ///< Hint (second parameter) to be passed to the finalize callback
+    );
+
+    ArrayBuffer();                               ///< Creates a new _empty_ ArrayBuffer instance.
+    ArrayBuffer(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
+
+    void* Data();        ///< Gets a pointer to the data buffer.
+    size_t ByteLength(); ///< Gets the length of the array buffer in bytes.
+
+  private:
+    mutable void* _data;
+    mutable size_t _length;
+
+    ArrayBuffer(napi_env env, napi_value value, void* data, size_t length);
+    void EnsureInfo() const;
+  };
+
+  /// A JavaScript typed-array value with unknown array type.
+  ///
+  /// For type-specific operations, cast to a `TypedArrayOf<T>` instance using the `As()`
+  /// method:
+  ///
+  ///     Napi::TypedArray array = ...
+  ///     if (t.TypedArrayType() == napi_int32_array) {
+  ///         Napi::Int32Array int32Array = t.As<Napi::Int32Array>();
+  ///     }
+  class TypedArray : public Object {
+  public:
+    TypedArray();                               ///< Creates a new _empty_ TypedArray instance.
+    TypedArray(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
+
+    napi_typedarray_type TypedArrayType() const; ///< Gets the type of this typed-array.
+    Napi::ArrayBuffer ArrayBuffer() const;       ///< Gets the backing array buffer.
+
+    uint8_t ElementSize() const;  ///< Gets the size in bytes of one element in the array.
+    size_t ElementLength() const; ///< Gets the number of elements in the array.
+    size_t ByteOffset() const;    ///< Gets the offset into the buffer where the array starts.
+    size_t ByteLength() const;    ///< Gets the length of the array in bytes.
+
+  protected:
+    /// !cond INTERNAL
+    napi_typedarray_type _type;
+    size_t _length;
+
+    TypedArray(napi_env env, napi_value value, napi_typedarray_type type, size_t length);
+
+    static const napi_typedarray_type unknown_array_type = static_cast<napi_typedarray_type>(-1);
+
+    template <typename T>
+    static
+#if defined(NAPI_HAS_CONSTEXPR)
+    constexpr
+#endif
+    napi_typedarray_type TypedArrayTypeForPrimitiveType() {
+      return std::is_same<T, int8_t>::value ? napi_int8_array
+        : std::is_same<T, uint8_t>::value ? napi_uint8_array
+        : std::is_same<T, int16_t>::value ? napi_int16_array
+        : std::is_same<T, uint16_t>::value ? napi_uint16_array
+        : std::is_same<T, int32_t>::value ? napi_int32_array
+        : std::is_same<T, uint32_t>::value ? napi_uint32_array
+        : std::is_same<T, float>::value ? napi_float32_array
+        : std::is_same<T, double>::value ? napi_float64_array
+// currently experimental guard with version of NAPI_VERSION that it is
+// released in once it is no longer experimental
+#if (NAPI_VERSION > 2147483646)
+        : std::is_same<T, int64_t>::value ? napi_bigint64_array
+        : std::is_same<T, uint64_t>::value ? napi_biguint64_array
+#endif  // NAPI_EXPERIMENTAL
+        : unknown_array_type;
+    }
+    /// !endcond
+  };
+
+  /// A JavaScript typed-array value with known array type.
+  ///
+  /// Note while it is possible to create and access Uint8 "clamped" arrays using this class,
+  /// the _clamping_ behavior is only applied in JavaScript.
+  template <typename T>
+  class TypedArrayOf : public TypedArray {
+  public:
+    /// Creates a new TypedArray instance over a new automatically-allocated array buffer.
+    ///
+    /// The array type parameter can normally be omitted (because it is inferred from the template
+    /// parameter T), except when creating a "clamped" array:
+    ///
+    ///     Uint8Array::New(env, length, napi_uint8_clamped_array)
+    static TypedArrayOf New(
+      napi_env env,         ///< N-API environment
+      size_t elementLength, ///< Length of the created array, as a number of elements
+#if defined(NAPI_HAS_CONSTEXPR)
+      napi_typedarray_type type = TypedArray::TypedArrayTypeForPrimitiveType<T>()
+#else
+      napi_typedarray_type type
+#endif
+        ///< Type of array, if different from the default array type for the template parameter T.
+    );
+
+    /// Creates a new TypedArray instance over a provided array buffer.
+    ///
+    /// The array type parameter can normally be omitted (because it is inferred from the template
+    /// parameter T), except when creating a "clamped" array:
+    ///
+    ///     Uint8Array::New(env, length, buffer, 0, napi_uint8_clamped_array)
+    static TypedArrayOf New(
+      napi_env env,                  ///< N-API environment
+      size_t elementLength,          ///< Length of the created array, as a number of elements
+      Napi::ArrayBuffer arrayBuffer, ///< Backing array buffer instance to use
+      size_t bufferOffset,           ///< Offset into the array buffer where the typed-array starts
+#if defined(NAPI_HAS_CONSTEXPR)
+      napi_typedarray_type type = TypedArray::TypedArrayTypeForPrimitiveType<T>()
+#else
+      napi_typedarray_type type
+#endif
+        ///< Type of array, if different from the default array type for the template parameter T.
+    );
+
+    TypedArrayOf();                               ///< Creates a new _empty_ TypedArrayOf instance.
+    TypedArrayOf(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
+
+    T& operator [](size_t index);             ///< Gets or sets an element in the array.
+    const T& operator [](size_t index) const; ///< Gets an element in the array.
+
+    /// Gets a pointer to the array's backing buffer.
+    ///
+    /// This is not necessarily the same as the `ArrayBuffer::Data()` pointer, because the
+    /// typed-array may have a non-zero `ByteOffset()` into the `ArrayBuffer`.
+    T* Data();
+
+    /// Gets a pointer to the array's backing buffer.
+    ///
+    /// This is not necessarily the same as the `ArrayBuffer::Data()` pointer, because the
+    /// typed-array may have a non-zero `ByteOffset()` into the `ArrayBuffer`.
+    const T* Data() const;
+
+  private:
+    T* _data;
+
+    TypedArrayOf(napi_env env,
+                 napi_value value,
+                 napi_typedarray_type type,
+                 size_t length,
+                 T* data);
+  };
+
+  /// The DataView provides a low-level interface for reading/writing multiple
+  /// number types in an ArrayBuffer irrespective of the platform's endianness.
+  class DataView : public Object {
+  public:
+    static DataView New(napi_env env,
+                        Napi::ArrayBuffer arrayBuffer);
+    static DataView New(napi_env env,
+                        Napi::ArrayBuffer arrayBuffer,
+                        size_t byteOffset);
+    static DataView New(napi_env env,
+                        Napi::ArrayBuffer arrayBuffer,
+                        size_t byteOffset,
+                        size_t byteLength);
+
+    DataView();                               ///< Creates a new _empty_ DataView instance.
+    DataView(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
+
+    Napi::ArrayBuffer ArrayBuffer() const;    ///< Gets the backing array buffer.
+    size_t ByteOffset() const;    ///< Gets the offset into the buffer where the array starts.
+    size_t ByteLength() const;    ///< Gets the length of the array in bytes.
+
+    void* Data() const;
+
+    float GetFloat32(size_t byteOffset) const;
+    double GetFloat64(size_t byteOffset) const;
+    int8_t GetInt8(size_t byteOffset) const;
+    int16_t GetInt16(size_t byteOffset) const;
+    int32_t GetInt32(size_t byteOffset) const;
+    uint8_t GetUint8(size_t byteOffset) const;
+    uint16_t GetUint16(size_t byteOffset) const;
+    uint32_t GetUint32(size_t byteOffset) const;
+
+    void SetFloat32(size_t byteOffset, float value) const;
+    void SetFloat64(size_t byteOffset, double value) const;
+    void SetInt8(size_t byteOffset, int8_t value) const;
+    void SetInt16(size_t byteOffset, int16_t value) const;
+    void SetInt32(size_t byteOffset, int32_t value) const;
+    void SetUint8(size_t byteOffset, uint8_t value) const;
+    void SetUint16(size_t byteOffset, uint16_t value) const;
+    void SetUint32(size_t byteOffset, uint32_t value) const;
+
+  private:
+    template <typename T>
+    T ReadData(size_t byteOffset) const;
+
+    template <typename T>
+    void WriteData(size_t byteOffset, T value) const;
+
+    void* _data;
+    size_t _length;
+  };
+
+  class Function : public Object {
+  public:
+    /// Callable must implement operator() accepting a const CallbackInfo&
+    /// and return either void or Value.
+    template <typename Callable>
+    static Function New(napi_env env,
+                        Callable cb,
+                        const char* utf8name = nullptr,
+                        void* data = nullptr);
+    /// Callable must implement operator() accepting a const CallbackInfo&
+    /// and return either void or Value.
+    template <typename Callable>
+    static Function New(napi_env env,
+                        Callable cb,
+                        const std::string& utf8name,
+                        void* data = nullptr);
+
+    Function();
+    Function(napi_env env, napi_value value);
+
+    Value operator ()(const std::initializer_list<napi_value>& args) const;
+
+    Value Call(const std::initializer_list<napi_value>& args) const;
+    Value Call(const std::vector<napi_value>& args) const;
+    Value Call(size_t argc, const napi_value* args) const;
+    Value Call(napi_value recv, const std::initializer_list<napi_value>& args) const;
+    Value Call(napi_value recv, const std::vector<napi_value>& args) const;
+    Value Call(napi_value recv, size_t argc, const napi_value* args) const;
+
+    Value MakeCallback(napi_value recv,
+                       const std::initializer_list<napi_value>& args,
+                       napi_async_context context = nullptr) const;
+    Value MakeCallback(napi_value recv,
+                       const std::vector<napi_value>& args,
+                       napi_async_context context = nullptr) const;
+    Value MakeCallback(napi_value recv,
+                       size_t argc,
+                       const napi_value* args,
+                       napi_async_context context = nullptr) const;
+
+    Object New(const std::initializer_list<napi_value>& args) const;
+    Object New(const std::vector<napi_value>& args) const;
+    Object New(size_t argc, const napi_value* args) const;
+  };
+
+  class Promise : public Object {
+  public:
+    class Deferred {
+    public:
+      static Deferred New(napi_env env);
+      Deferred(napi_env env);
+
+      Napi::Promise Promise() const;
+      Napi::Env Env() const;
+
+      void Resolve(napi_value value) const;
+      void Reject(napi_value value) const;
+
+    private:
+      napi_env _env;
+      napi_deferred _deferred;
+      napi_value _promise;
+    };
+
+    Promise(napi_env env, napi_value value);
+  };
+
+  template <typename T>
+  class Buffer : public Uint8Array {
+  public:
+    static Buffer<T> New(napi_env env, size_t length);
+    static Buffer<T> New(napi_env env, T* data, size_t length);
+
+    // Finalizer must implement `void operator()(Env env, T* data)`.
+    template <typename Finalizer>
+    static Buffer<T> New(napi_env env, T* data,
+                         size_t length,
+                         Finalizer finalizeCallback);
+    // Finalizer must implement `void operator()(Env env, T* data, Hint* hint)`.
+    template <typename Finalizer, typename Hint>
+    static Buffer<T> New(napi_env env, T* data,
+                         size_t length,
+                         Finalizer finalizeCallback,
+                         Hint* finalizeHint);
+
+    static Buffer<T> Copy(napi_env env, const T* data, size_t length);
+
+    Buffer();
+    Buffer(napi_env env, napi_value value);
+    size_t Length() const;
+    T* Data() const;
+
+  private:
+    mutable size_t _length;
+    mutable T* _data;
+
+    Buffer(napi_env env, napi_value value, size_t length, T* data);
+    void EnsureInfo() const;
+  };
+
+  /// Holds a counted reference to a value; initially a weak reference unless otherwise specified,
+  /// may be changed to/from a strong reference by adjusting the refcount.
+  ///
+  /// The referenced value is not immediately destroyed when the reference count is zero; it is
+  /// merely then eligible for garbage-collection if there are no other references to the value.
+  template <typename T>
+  class Reference {
+  public:
+    static Reference<T> New(const T& value, uint32_t initialRefcount = 0);
+
+    Reference();
+    Reference(napi_env env, napi_ref ref);
+    ~Reference();
+
+    // A reference can be moved but cannot be copied.
+    Reference(Reference<T>&& other);
+    Reference<T>& operator =(Reference<T>&& other);
+    Reference<T>& operator =(Reference<T>&) = delete;
+
+    operator napi_ref() const;
+    bool operator ==(const Reference<T> &other) const;
+    bool operator !=(const Reference<T> &other) const;
+
+    Napi::Env Env() const;
+    bool IsEmpty() const;
+
+    // Note when getting the value of a Reference it is usually correct to do so
+    // within a HandleScope so that the value handle gets cleaned up efficiently.
+    T Value() const;
+
+    uint32_t Ref();
+    uint32_t Unref();
+    void Reset();
+    void Reset(const T& value, uint32_t refcount = 0);
+
+    // Call this on a reference that is declared as static data, to prevent its destructor
+    // from running at program shutdown time, which would attempt to reset the reference when
+    // the environment is no longer valid.
+    void SuppressDestruct();
+
+  protected:
+    Reference(const Reference<T>&);
+
+    /// !cond INTERNAL
+    napi_env _env;
+    napi_ref _ref;
+    /// !endcond
+
+  private:
+    bool _suppressDestruct;
+  };
+
+  class ObjectReference: public Reference<Object> {
+  public:
+    ObjectReference();
+    ObjectReference(napi_env env, napi_ref ref);
+
+    // A reference can be moved but cannot be copied.
+    ObjectReference(Reference<Object>&& other);
+    ObjectReference& operator =(Reference<Object>&& other);
+    ObjectReference(ObjectReference&& other);
+    ObjectReference& operator =(ObjectReference&& other);
+    ObjectReference& operator =(ObjectReference&) = delete;
+
+    Napi::Value Get(const char* utf8name) const;
+    Napi::Value Get(const std::string& utf8name) const;
+    void Set(const char* utf8name, napi_value value);
+    void Set(const char* utf8name, Napi::Value value);
+    void Set(const char* utf8name, const char* utf8value);
+    void Set(const char* utf8name, bool boolValue);
+    void Set(const char* utf8name, double numberValue);
+    void Set(const std::string& utf8name, napi_value value);
+    void Set(const std::string& utf8name, Napi::Value value);
+    void Set(const std::string& utf8name, std::string& utf8value);
+    void Set(const std::string& utf8name, bool boolValue);
+    void Set(const std::string& utf8name, double numberValue);
+
+    Napi::Value Get(uint32_t index) const;
+    void Set(uint32_t index, const napi_value value);
+    void Set(uint32_t index, const Napi::Value value);
+    void Set(uint32_t index, const char* utf8value);
+    void Set(uint32_t index, const std::string& utf8value);
+    void Set(uint32_t index, bool boolValue);
+    void Set(uint32_t index, double numberValue);
+
+  protected:
+    ObjectReference(const ObjectReference&);
+  };
+
+  class FunctionReference: public Reference<Function> {
+  public:
+    FunctionReference();
+    FunctionReference(napi_env env, napi_ref ref);
+
+    // A reference can be moved but cannot be copied.
+    FunctionReference(Reference<Function>&& other);
+    FunctionReference& operator =(Reference<Function>&& other);
+    FunctionReference(FunctionReference&& other);
+    FunctionReference& operator =(FunctionReference&& other);
+    FunctionReference(const FunctionReference&) = delete;
+    FunctionReference& operator =(FunctionReference&) = delete;
+
+    Napi::Value operator ()(const std::initializer_list<napi_value>& args) const;
+
+    Napi::Value Call(const std::initializer_list<napi_value>& args) const;
+    Napi::Value Call(const std::vector<napi_value>& args) const;
+    Napi::Value Call(napi_value recv, const std::initializer_list<napi_value>& args) const;
+    Napi::Value Call(napi_value recv, const std::vector<napi_value>& args) const;
+    Napi::Value Call(napi_value recv, size_t argc, const napi_value* args) const;
+
+    Napi::Value MakeCallback(napi_value recv,
+                             const std::initializer_list<napi_value>& args,
+                             napi_async_context context = nullptr) const;
+    Napi::Value MakeCallback(napi_value recv,
+                             const std::vector<napi_value>& args,
+                             napi_async_context context = nullptr) const;
+    Napi::Value MakeCallback(napi_value recv,
+                             size_t argc,
+                             const napi_value* args,
+                             napi_async_context context = nullptr) const;
+
+    Object New(const std::initializer_list<napi_value>& args) const;
+    Object New(const std::vector<napi_value>& args) const;
+  };
+
+  // Shortcuts to creating a new reference with inferred type and refcount = 0.
+  template <typename T> Reference<T> Weak(T value);
+  ObjectReference Weak(Object value);
+  FunctionReference Weak(Function value);
+
+  // Shortcuts to creating a new reference with inferred type and refcount = 1.
+  template <typename T> Reference<T> Persistent(T value);
+  ObjectReference Persistent(Object value);
+  FunctionReference Persistent(Function value);
+
+  /// A persistent reference to a JavaScript error object. Use of this class depends somewhat
+  /// on whether C++ exceptions are enabled at compile time.
+  ///
+  /// ### Handling Errors With C++ Exceptions
+  ///
+  /// If C++ exceptions are enabled, then the `Error` class extends `std::exception` and enables
+  /// integrated error-handling for C++ exceptions and JavaScript exceptions.
+  ///
+  /// If a N-API call fails without executing any JavaScript code (for example due to an invalid
+  /// argument), then the N-API wrapper automatically converts and throws the error as a C++
+  /// exception of type `Napi::Error`. Or if a JavaScript function called by C++ code via N-API
+  /// throws a JavaScript exception, then the N-API wrapper automatically converts and throws it as
+  /// a C++ exception of type `Napi::Error`.
+  ///
+  /// If a C++ exception of type `Napi::Error` escapes from a N-API C++ callback, then the N-API
+  /// wrapper automatically converts and throws it as a JavaScript exception. Therefore, catching
+  /// a C++ exception of type `Napi::Error` prevents a JavaScript exception from being thrown.
+  ///
+  /// #### Example 1A - Throwing a C++ exception:
+  ///
+  ///     Napi::Env env = ...
+  ///     throw Napi::Error::New(env, "Example exception");
+  ///
+  /// Following C++ statements will not be executed. The exception will bubble up as a C++
+  /// exception of type `Napi::Error`, until it is either caught while still in C++, or else
+  /// automatically propataged as a JavaScript exception when the callback returns to JavaScript.
+  ///
+  /// #### Example 2A - Propagating a N-API C++ exception:
+  ///
+  ///     Napi::Function jsFunctionThatThrows = someObj.As<Napi::Function>();
+  ///     Napi::Value result = jsFunctionThatThrows({ arg1, arg2 });
+  ///
+  /// Following C++ statements will not be executed. The exception will bubble up as a C++
+  /// exception of type `Napi::Error`, until it is either caught while still in C++, or else
+  /// automatically propagated as a JavaScript exception when the callback returns to JavaScript.
+  ///
+  /// #### Example 3A - Handling a N-API C++ exception:
+  ///
+  ///     Napi::Function jsFunctionThatThrows = someObj.As<Napi::Function>();
+  ///     Napi::Value result;
+  ///     try {
+  ///        result = jsFunctionThatThrows({ arg1, arg2 });
+  ///     } catch (const Napi::Error& e) {
+  ///       cerr << "Caught JavaScript exception: " + e.what();
+  ///     }
+  ///
+  /// Since the exception was caught here, it will not be propagated as a JavaScript exception.
+  ///
+  /// ### Handling Errors Without C++ Exceptions
+  ///
+  /// If C++ exceptions are disabled (by defining `NAPI_DISABLE_CPP_EXCEPTIONS`) then this class
+  /// does not extend `std::exception`, and APIs in the `Napi` namespace do not throw C++
+  /// exceptions when they fail. Instead, they raise _pending_ JavaScript exceptions and
+  /// return _empty_ `Value`s. Calling code should check `Value::IsEmpty()` before attempting
+  /// to use a returned value, and may use methods on the `Env` class to check for, get, and
+  /// clear a pending JavaScript exception. If the pending exception is not cleared, it will
+  /// be thrown when the native callback returns to JavaScript.
+  ///
+  /// #### Example 1B - Throwing a JS exception
+  ///
+  ///     Napi::Env env = ...
+  ///     Napi::Error::New(env, "Example exception").ThrowAsJavaScriptException();
+  ///     return;
+  ///
+  /// After throwing a JS exception, the code should generally return immediately from the native
+  /// callback, after performing any necessary cleanup.
+  ///
+  /// #### Example 2B - Propagating a N-API JS exception:
+  ///
+  ///     Napi::Function jsFunctionThatThrows = someObj.As<Napi::Function>();
+  ///     Napi::Value result = jsFunctionThatThrows({ arg1, arg2 });
+  ///     if (result.IsEmpty()) return;
+  ///
+  /// An empty value result from a N-API call indicates an error occurred, and a JavaScript
+  /// exception is pending. To let the exception propagate, the code should generally return
+  /// immediately from the native callback, after performing any necessary cleanup.
+  ///
+  /// #### Example 3B - Handling a N-API JS exception:
+  ///
+  ///     Napi::Function jsFunctionThatThrows = someObj.As<Napi::Function>();
+  ///     Napi::Value result = jsFunctionThatThrows({ arg1, arg2 });
+  ///     if (result.IsEmpty()) {
+  ///       Napi::Error e = env.GetAndClearPendingException();
+  ///       cerr << "Caught JavaScript exception: " + e.Message();
+  ///     }
+  ///
+  /// Since the exception was cleared here, it will not be propagated as a JavaScript exception
+  /// after the native callback returns.
+  class Error : public ObjectReference
+#ifdef NAPI_CPP_EXCEPTIONS
+    , public std::exception
+#endif // NAPI_CPP_EXCEPTIONS
+    {
+  public:
+    static Error New(napi_env env);
+    static Error New(napi_env env, const char* message);
+    static Error New(napi_env env, const std::string& message);
+
+    static NAPI_NO_RETURN void Fatal(const char* location, const char* message);
+
+    Error();
+    Error(napi_env env, napi_value value);
+
+    // An error can be moved or copied.
+    Error(Error&& other);
+    Error& operator =(Error&& other);
+    Error(const Error&);
+    Error& operator =(Error&);
+
+    const std::string& Message() const NAPI_NOEXCEPT;
+    void ThrowAsJavaScriptException() const;
+
+#ifdef NAPI_CPP_EXCEPTIONS
+    const char* what() const NAPI_NOEXCEPT override;
+#endif // NAPI_CPP_EXCEPTIONS
+
+  protected:
+    /// !cond INTERNAL
+    typedef napi_status (*create_error_fn)(napi_env envb, napi_value code, napi_value msg, napi_value* result);
+
+    template <typename TError>
+    static TError New(napi_env env,
+                      const char* message,
+                      size_t length,
+                      create_error_fn create_error);
+    /// !endcond
+
+  private:
+    mutable std::string _message;
+  };
+
+  class TypeError : public Error {
+  public:
+    static TypeError New(napi_env env, const char* message);
+    static TypeError New(napi_env env, const std::string& message);
+
+    TypeError();
+    TypeError(napi_env env, napi_value value);
+  };
+
+  class RangeError : public Error {
+  public:
+    static RangeError New(napi_env env, const char* message);
+    static RangeError New(napi_env env, const std::string& message);
+
+    RangeError();
+    RangeError(napi_env env, napi_value value);
+  };
+
+  class CallbackInfo {
+  public:
+    CallbackInfo(napi_env env, napi_callback_info info);
+    ~CallbackInfo();
+
+    // Disallow copying to prevent multiple free of _dynamicArgs
+    CallbackInfo(CallbackInfo const &) = delete;
+    void operator=(CallbackInfo const &) = delete;
+
+    Napi::Env Env() const;
+    Value NewTarget() const;
+    bool IsConstructCall() const;
+    size_t Length() const;
+    const Value operator [](size_t index) const;
+    Value This() const;
+    void* Data() const;
+    void SetData(void* data);
+
+  private:
+    const size_t _staticArgCount = 6;
+    napi_env _env;
+    napi_callback_info _info;
+    napi_value _this;
+    size_t _argc;
+    napi_value* _argv;
+    napi_value _staticArgs[6];
+    napi_value* _dynamicArgs;
+    void* _data;
+  };
+
+  class PropertyDescriptor {
+  public:
+#ifndef NODE_ADDON_API_DISABLE_DEPRECATED
+    template <typename Getter>
+    static PropertyDescriptor Accessor(const char* utf8name,
+                                       Getter getter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Getter>
+    static PropertyDescriptor Accessor(const std::string& utf8name,
+                                       Getter getter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Getter>
+    static PropertyDescriptor Accessor(napi_value name,
+                                       Getter getter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Getter>
+    static PropertyDescriptor Accessor(Name name,
+                                       Getter getter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Getter, typename Setter>
+    static PropertyDescriptor Accessor(const char* utf8name,
+                                       Getter getter,
+                                       Setter setter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Getter, typename Setter>
+    static PropertyDescriptor Accessor(const std::string& utf8name,
+                                       Getter getter,
+                                       Setter setter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Getter, typename Setter>
+    static PropertyDescriptor Accessor(napi_value name,
+                                       Getter getter,
+                                       Setter setter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Getter, typename Setter>
+    static PropertyDescriptor Accessor(Name name,
+                                       Getter getter,
+                                       Setter setter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Callable>
+    static PropertyDescriptor Function(const char* utf8name,
+                                       Callable cb,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Callable>
+    static PropertyDescriptor Function(const std::string& utf8name,
+                                       Callable cb,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Callable>
+    static PropertyDescriptor Function(napi_value name,
+                                       Callable cb,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Callable>
+    static PropertyDescriptor Function(Name name,
+                                       Callable cb,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+#endif // !NODE_ADDON_API_DISABLE_DEPRECATED
+
+    template <typename Getter>
+    static PropertyDescriptor Accessor(Napi::Env env,
+                                       Napi::Object object,
+                                       const char* utf8name,
+                                       Getter getter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Getter>
+    static PropertyDescriptor Accessor(Napi::Env env,
+                                       Napi::Object object,
+                                       const std::string& utf8name,
+                                       Getter getter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Getter>
+    static PropertyDescriptor Accessor(Napi::Env env,
+                                       Napi::Object object,
+                                       Name name,
+                                       Getter getter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Getter, typename Setter>
+    static PropertyDescriptor Accessor(Napi::Env env,
+                                       Napi::Object object,
+                                       const char* utf8name,
+                                       Getter getter,
+                                       Setter setter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Getter, typename Setter>
+    static PropertyDescriptor Accessor(Napi::Env env,
+                                       Napi::Object object,
+                                       const std::string& utf8name,
+                                       Getter getter,
+                                       Setter setter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Getter, typename Setter>
+    static PropertyDescriptor Accessor(Napi::Env env,
+                                       Napi::Object object,
+                                       Name name,
+                                       Getter getter,
+                                       Setter setter,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Callable>
+    static PropertyDescriptor Function(Napi::Env env,
+                                       Napi::Object object,
+                                       const char* utf8name,
+                                       Callable cb,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Callable>
+    static PropertyDescriptor Function(Napi::Env env,
+                                       Napi::Object object,
+                                       const std::string& utf8name,
+                                       Callable cb,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    template <typename Callable>
+    static PropertyDescriptor Function(Napi::Env env,
+                                       Napi::Object object,
+                                       Name name,
+                                       Callable cb,
+                                       napi_property_attributes attributes = napi_default,
+                                       void* data = nullptr);
+    static PropertyDescriptor Value(const char* utf8name,
+                                    napi_value value,
+                                    napi_property_attributes attributes = napi_default);
+    static PropertyDescriptor Value(const std::string& utf8name,
+                                    napi_value value,
+                                    napi_property_attributes attributes = napi_default);
+    static PropertyDescriptor Value(napi_value name,
+                                    napi_value value,
+                                    napi_property_attributes attributes = napi_default);
+    static PropertyDescriptor Value(Name name,
+                                    Napi::Value value,
+                                    napi_property_attributes attributes = napi_default);
+
+    PropertyDescriptor(napi_property_descriptor desc);
+
+    operator napi_property_descriptor&();
+    operator const napi_property_descriptor&() const;
+
+  private:
+    napi_property_descriptor _desc;
+  };
+
+  /// Property descriptor for use with `ObjectWrap::DefineClass()`.
+  ///
+  /// This is different from the standalone `PropertyDescriptor` because it is specific to each
+  /// `ObjectWrap<T>` subclass. This prevents using descriptors from a different class when
+  /// defining a new class (preventing the callbacks from having incorrect `this` pointers).
+  template <typename T>
+  class ClassPropertyDescriptor {
+  public:
+    ClassPropertyDescriptor(napi_property_descriptor desc) : _desc(desc) {}
+
+    operator napi_property_descriptor&() { return _desc; }
+    operator const napi_property_descriptor&() const { return _desc; }
+
+  private:
+    napi_property_descriptor _desc;
+  };
+
+  /// Base class to be extended by C++ classes exposed to JavaScript; each C++ class instance gets
+  /// "wrapped" by a JavaScript object that is managed by this class.
+  ///
+  /// At initialization time, the `DefineClass()` method must be used to
+  /// hook up the accessor and method callbacks. It takes a list of
+  /// property descriptors, which can be constructed via the various
+  /// static methods on the base class.
+  ///
+  /// #### Example:
+  ///
+  ///     class Example: public Napi::ObjectWrap<Example> {
+  ///       public:
+  ///         static void Initialize(Napi::Env& env, Napi::Object& target) {
+  ///           Napi::Function constructor = DefineClass(env, "Example", {
+  ///             InstanceAccessor("value", &Example::GetSomething, &Example::SetSomething),
+  ///             InstanceMethod("doSomething", &Example::DoSomething),
+  ///           });
+  ///           target.Set("Example", constructor);
+  ///         }
+  ///
+  ///         Example(const Napi::CallbackInfo& info); // Constructor
+  ///         Napi::Value GetSomething(const Napi::CallbackInfo& info);
+  ///         void SetSomething(const Napi::CallbackInfo& info, const Napi::Value& value);
+  ///         Napi::Value DoSomething(const Napi::CallbackInfo& info);
+  ///     }
+  template <typename T>
+  class ObjectWrap : public Reference<Object> {
+  public:
+    ObjectWrap(const CallbackInfo& callbackInfo);
+
+    static T* Unwrap(Object wrapper);
+
+    // Methods exposed to JavaScript must conform to one of these callback signatures.
+    typedef void (*StaticVoidMethodCallback)(const CallbackInfo& info);
+    typedef Napi::Value (*StaticMethodCallback)(const CallbackInfo& info);
+    typedef Napi::Value (*StaticGetterCallback)(const CallbackInfo& info);
+    typedef void (*StaticSetterCallback)(const CallbackInfo& info, const Napi::Value& value);
+    typedef void (T::*InstanceVoidMethodCallback)(const CallbackInfo& info);
+    typedef Napi::Value (T::*InstanceMethodCallback)(const CallbackInfo& info);
+    typedef Napi::Value (T::*InstanceGetterCallback)(const CallbackInfo& info);
+    typedef void (T::*InstanceSetterCallback)(const CallbackInfo& info, const Napi::Value& value);
+
+    typedef ClassPropertyDescriptor<T> PropertyDescriptor;
+
+    static Function DefineClass(Napi::Env env,
+                                const char* utf8name,
+                                const std::initializer_list<PropertyDescriptor>& properties,
+                                void* data = nullptr);
+    static Function DefineClass(Napi::Env env,
+                                const char* utf8name,
+                                const std::vector<PropertyDescriptor>& properties,
+                                void* data = nullptr);
+    static PropertyDescriptor StaticMethod(const char* utf8name,
+                                           StaticVoidMethodCallback method,
+                                           napi_property_attributes attributes = napi_default,
+                                           void* data = nullptr);
+    static PropertyDescriptor StaticMethod(const char* utf8name,
+                                           StaticMethodCallback method,
+                                           napi_property_attributes attributes = napi_default,
+                                           void* data = nullptr);
+    static PropertyDescriptor StaticMethod(Symbol name,
+                                           StaticVoidMethodCallback method,
+                                           napi_property_attributes attributes = napi_default,
+                                           void* data = nullptr);
+    static PropertyDescriptor StaticMethod(Symbol name,
+                                           StaticMethodCallback method,
+                                           napi_property_attributes attributes = napi_default,
+                                           void* data = nullptr);
+    static PropertyDescriptor StaticAccessor(const char* utf8name,
+                                             StaticGetterCallback getter,
+                                             StaticSetterCallback setter,
+                                             napi_property_attributes attributes = napi_default,
+                                             void* data = nullptr);
+    static PropertyDescriptor StaticAccessor(Symbol name,
+                                             StaticGetterCallback getter,
+                                             StaticSetterCallback setter,
+                                             napi_property_attributes attributes = napi_default,
+                                             void* data = nullptr);
+    static PropertyDescriptor InstanceMethod(const char* utf8name,
+                                             InstanceVoidMethodCallback method,
+                                             napi_property_attributes attributes = napi_default,
+                                             void* data = nullptr);
+    static PropertyDescriptor InstanceMethod(const char* utf8name,
+                                             InstanceMethodCallback method,
+                                             napi_property_attributes attributes = napi_default,
+                                             void* data = nullptr);
+    static PropertyDescriptor InstanceMethod(Symbol name,
+                                             InstanceVoidMethodCallback method,
+                                             napi_property_attributes attributes = napi_default,
+                                             void* data = nullptr);
+    static PropertyDescriptor InstanceMethod(Symbol name,
+                                             InstanceMethodCallback method,
+                                             napi_property_attributes attributes = napi_default,
+                                             void* data = nullptr);
+    static PropertyDescriptor InstanceAccessor(const char* utf8name,
+                                               InstanceGetterCallback getter,
+                                               InstanceSetterCallback setter,
+                                               napi_property_attributes attributes = napi_default,
+                                               void* data = nullptr);
+    static PropertyDescriptor InstanceAccessor(Symbol name,
+                                               InstanceGetterCallback getter,
+                                               InstanceSetterCallback setter,
+                                               napi_property_attributes attributes = napi_default,
+                                               void* data = nullptr);
+    static PropertyDescriptor StaticValue(const char* utf8name,
+                                          Napi::Value value,
+                                          napi_property_attributes attributes = napi_default);
+    static PropertyDescriptor StaticValue(Symbol name,
+                                          Napi::Value value,
+                                          napi_property_attributes attributes = napi_default);
+    static PropertyDescriptor InstanceValue(const char* utf8name,
+                                            Napi::Value value,
+                                            napi_property_attributes attributes = napi_default);
+    static PropertyDescriptor InstanceValue(Symbol name,
+                                            Napi::Value value,
+                                            napi_property_attributes attributes = napi_default);
+
+  private:
+    static napi_value ConstructorCallbackWrapper(napi_env env, napi_callback_info info);
+    static napi_value StaticVoidMethodCallbackWrapper(napi_env env, napi_callback_info info);
+    static napi_value StaticMethodCallbackWrapper(napi_env env, napi_callback_info info);
+    static napi_value StaticGetterCallbackWrapper(napi_env env, napi_callback_info info);
+    static napi_value StaticSetterCallbackWrapper(napi_env env, napi_callback_info info);
+    static napi_value InstanceVoidMethodCallbackWrapper(napi_env env, napi_callback_info info);
+    static napi_value InstanceMethodCallbackWrapper(napi_env env, napi_callback_info info);
+    static napi_value InstanceGetterCallbackWrapper(napi_env env, napi_callback_info info);
+    static napi_value InstanceSetterCallbackWrapper(napi_env env, napi_callback_info info);
+    static void FinalizeCallback(napi_env env, void* data, void* hint);
+    static Function DefineClass(Napi::Env env,
+                                const char* utf8name,
+                                const size_t props_count,
+                                const napi_property_descriptor* props,
+                                void* data = nullptr);
+
+    template <typename TCallback>
+    struct MethodCallbackData {
+      TCallback callback;
+      void* data;
+    };
+    typedef MethodCallbackData<StaticVoidMethodCallback> StaticVoidMethodCallbackData;
+    typedef MethodCallbackData<StaticMethodCallback> StaticMethodCallbackData;
+    typedef MethodCallbackData<InstanceVoidMethodCallback> InstanceVoidMethodCallbackData;
+    typedef MethodCallbackData<InstanceMethodCallback> InstanceMethodCallbackData;
+
+    template <typename TGetterCallback, typename TSetterCallback>
+    struct AccessorCallbackData {
+      TGetterCallback getterCallback;
+      TSetterCallback setterCallback;
+      void* data;
+    };
+    typedef AccessorCallbackData<StaticGetterCallback, StaticSetterCallback>
+      StaticAccessorCallbackData;
+    typedef AccessorCallbackData<InstanceGetterCallback, InstanceSetterCallback>
+      InstanceAccessorCallbackData;
+  };
+
+  class HandleScope {
+  public:
+    HandleScope(napi_env env, napi_handle_scope scope);
+    explicit HandleScope(Napi::Env env);
+    ~HandleScope();
+
+    operator napi_handle_scope() const;
+
+    Napi::Env Env() const;
+
+  private:
+    napi_env _env;
+    napi_handle_scope _scope;
+  };
+
+  class EscapableHandleScope {
+  public:
+    EscapableHandleScope(napi_env env, napi_escapable_handle_scope scope);
+    explicit EscapableHandleScope(Napi::Env env);
+    ~EscapableHandleScope();
+
+    operator napi_escapable_handle_scope() const;
+
+    Napi::Env Env() const;
+    Value Escape(napi_value escapee);
+
+  private:
+    napi_env _env;
+    napi_escapable_handle_scope _scope;
+  };
+
+#if (NAPI_VERSION > 2)
+  class CallbackScope {
+  public:
+    CallbackScope(napi_env env, napi_callback_scope scope);
+    CallbackScope(napi_env env, napi_async_context context);
+    virtual ~CallbackScope();
+
+    operator napi_callback_scope() const;
+
+    Napi::Env Env() const;
+
+  private:
+    napi_env _env;
+    napi_callback_scope _scope;
+  };
+#endif
+
+  class AsyncContext {
+  public:
+    explicit AsyncContext(napi_env env, const char* resource_name);
+    explicit AsyncContext(napi_env env, const char* resource_name, const Object& resource);
+    virtual ~AsyncContext();
+
+    AsyncContext(AsyncContext&& other);
+    AsyncContext& operator =(AsyncContext&& other);
+    AsyncContext(const AsyncContext&) = delete;
+    AsyncContext& operator =(AsyncContext&) = delete;
+
+    operator napi_async_context() const;
+
+  private:
+    napi_env _env;
+    napi_async_context _context;
+  };
+
+  class AsyncWorker {
+  public:
+    virtual ~AsyncWorker();
+
+    // An async worker can be moved but cannot be copied.
+    AsyncWorker(AsyncWorker&& other);
+    AsyncWorker& operator =(AsyncWorker&& other);
+    AsyncWorker(const AsyncWorker&) = delete;
+    AsyncWorker& operator =(AsyncWorker&) = delete;
+
+    operator napi_async_work() const;
+
+    Napi::Env Env() const;
+
+    void Queue();
+    void Cancel();
+    void SuppressDestruct();
+
+    ObjectReference& Receiver();
+    FunctionReference& Callback();
+
+  protected:
+    explicit AsyncWorker(const Function& callback);
+    explicit AsyncWorker(const Function& callback,
+                         const char* resource_name);
+    explicit AsyncWorker(const Function& callback,
+                         const char* resource_name,
+                         const Object& resource);
+    explicit AsyncWorker(const Object& receiver,
+                         const Function& callback);
+    explicit AsyncWorker(const Object& receiver,
+                         const Function& callback,
+                         const char* resource_name);
+    explicit AsyncWorker(const Object& receiver,
+                         const Function& callback,
+                         const char* resource_name,
+                         const Object& resource);
+
+    explicit AsyncWorker(Napi::Env env);
+    explicit AsyncWorker(Napi::Env env,
+                         const char* resource_name);
+    explicit AsyncWorker(Napi::Env env,
+                         const char* resource_name,
+                         const Object& resource);
+
+    virtual void Execute() = 0;
+    virtual void OnOK();
+    virtual void OnError(const Error& e);
+    virtual void Destroy();
+    virtual std::vector<napi_value> GetResult(Napi::Env env);
+
+    void SetError(const std::string& error);
+
+  private:
+    static void OnExecute(napi_env env, void* this_pointer);
+    static void OnWorkComplete(napi_env env,
+                               napi_status status,
+                               void* this_pointer);
+
+    napi_env _env;
+    napi_async_work _work;
+    ObjectReference _receiver;
+    FunctionReference _callback;
+    std::string _error;
+    bool _suppress_destruct;
+  };
+
+  #if (NAPI_VERSION > 3)
+  class ThreadSafeFunction {
+  public:
+    // This API may only be called from the main thread.
+    template <typename ResourceString>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount);
+
+    // This API may only be called from the main thread.
+    template <typename ResourceString, typename ContextType>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  ContextType* context);
+
+    // This API may only be called from the main thread.
+    template <typename ResourceString, typename Finalizer>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  Finalizer finalizeCallback);
+
+    // This API may only be called from the main thread.
+    template <typename ResourceString, typename Finalizer,
+              typename FinalizerDataType>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  Finalizer finalizeCallback,
+                                  FinalizerDataType* data);
+
+    // This API may only be called from the main thread.
+    template <typename ResourceString, typename ContextType, typename Finalizer>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  ContextType* context,
+                                  Finalizer finalizeCallback);
+
+    // This API may only be called from the main thread.
+    template <typename ResourceString, typename ContextType,
+              typename Finalizer, typename FinalizerDataType>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  ContextType* context,
+                                  Finalizer finalizeCallback,
+                                  FinalizerDataType* data);
+
+    // This API may only be called from the main thread.
+    template <typename ResourceString>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  const Object& resource,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount);
+
+    // This API may only be called from the main thread.
+    template <typename ResourceString, typename ContextType>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  const Object& resource,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  ContextType* context);
+
+    // This API may only be called from the main thread.
+    template <typename ResourceString, typename Finalizer>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  const Object& resource,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  Finalizer finalizeCallback);
+
+    // This API may only be called from the main thread.
+    template <typename ResourceString, typename Finalizer,
+              typename FinalizerDataType>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  const Object& resource,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  Finalizer finalizeCallback,
+                                  FinalizerDataType* data);
+
+    // This API may only be called from the main thread.
+    template <typename ResourceString, typename ContextType, typename Finalizer>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  const Object& resource,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  ContextType* context,
+                                  Finalizer finalizeCallback);
+
+    // This API may only be called from the main thread.
+    template <typename ResourceString, typename ContextType,
+              typename Finalizer, typename FinalizerDataType>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  const Object& resource,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  ContextType* context,
+                                  Finalizer finalizeCallback,
+                                  FinalizerDataType* data);
+
+    ThreadSafeFunction();
+    ThreadSafeFunction(napi_threadsafe_function tsFunctionValue);
+
+    ThreadSafeFunction(ThreadSafeFunction&& other);
+    ThreadSafeFunction& operator=(ThreadSafeFunction&& other);
+
+    // This API may be called from any thread.
+    napi_status BlockingCall() const;
+
+    // This API may be called from any thread.
+    template <typename Callback>
+    napi_status BlockingCall(Callback callback) const;
+
+    // This API may be called from any thread.
+    template <typename DataType, typename Callback>
+    napi_status BlockingCall(DataType* data, Callback callback) const;
+
+    // This API may be called from any thread.
+    napi_status NonBlockingCall() const;
+
+    // This API may be called from any thread.
+    template <typename Callback>
+    napi_status NonBlockingCall(Callback callback) const;
+
+    // This API may be called from any thread.
+    template <typename DataType, typename Callback>
+    napi_status NonBlockingCall(DataType* data, Callback callback) const;
+
+    // This API may be called from any thread.
+    napi_status Acquire() const;
+
+    // This API may be called from any thread.
+    napi_status Release();
+
+    // This API may be called from any thread.
+    napi_status Abort();
+
+    struct ConvertibleContext
+    {
+      template <class T>
+      operator T*() { return static_cast<T*>(context); }
+      void* context;
+    };
+
+    // This API may be called from any thread.
+    ConvertibleContext GetContext() const;
+
+  private:
+    using CallbackWrapper = std::function<void(Napi::Env, Napi::Function)>;
+
+    template <typename ResourceString, typename ContextType,
+              typename Finalizer, typename FinalizerDataType>
+    static ThreadSafeFunction New(napi_env env,
+                                  const Function& callback,
+                                  const Object& resource,
+                                  ResourceString resourceName,
+                                  size_t maxQueueSize,
+                                  size_t initialThreadCount,
+                                  ContextType* context,
+                                  Finalizer finalizeCallback,
+                                  FinalizerDataType* data,
+                                  napi_finalize wrapper);
+
+    napi_status CallInternal(CallbackWrapper* callbackWrapper,
+                        napi_threadsafe_function_call_mode mode) const;
+
+    static void CallJS(napi_env env,
+                       napi_value jsCallback,
+                       void* context,
+                       void* data);
+
+    std::unique_ptr<napi_threadsafe_function> _tsfn;
+  };
+  #endif
+
+  // Memory management.
+  class MemoryManagement {
+    public:
+      static int64_t AdjustExternalMemory(Env env, int64_t change_in_bytes);
+  };
+
+  // Version management
+  class VersionManagement {
+    public:
+      static uint32_t GetNapiVersion(Env env);
+      static const napi_node_version* GetNodeVersion(Env env);
+  };
+
+} // namespace Napi
+
+// Inline implementations of all the above class methods are included here.
+#include "napi-inl.h"
+
+#endif // SRC_NAPI_H_
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index afcdd1f463e..29727b3c87f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -42,6 +42,11 @@ if(NOT QT_FEATURE_system_zlib)
 endif()
 qt_install_3rdparty_library_wrap_config_extra_file(BundledZLIB)
 
+if(OHOS)
+    add_subdirectory(3rdparty/node-addon-api)
+    add_subdirectory(openharmony)
+endif()
+
 add_subdirectory(corelib)
 
 # Needs to be after corelib, because some of them reference Core.
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index 4784a310f79..e0a55c77814 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -772,7 +772,7 @@ qt_internal_extend_target(Core CONDITION APPLE
         text/qlocale_mac.mm
 )
 
-qt_internal_extend_target(Core CONDITION UNIX AND NOT APPLE
+qt_internal_extend_target(Core CONDITION UNIX AND NOT APPLE AND NOT OHOS
     SOURCES
         text/qlocale_unix.cpp
 )
@@ -856,7 +856,12 @@ qt_internal_extend_target(Core CONDITION QT_FEATURE_timezone AND ANDROID AND NOT
         time/qtimezoneprivate_android.cpp
 )
 
-qt_internal_extend_target(Core CONDITION QT_FEATURE_timezone AND UNIX AND NOT ANDROID AND NOT APPLE
+qt_internal_extend_target(Core CONDITION QT_FEATURE_timezone AND OHOS AND NOT APPLE
+    SOURCES
+        time/qtimezoneprivate_openharmony.cpp
+)
+
+qt_internal_extend_target(Core CONDITION QT_FEATURE_timezone AND UNIX AND NOT ANDROID AND NOT OHOS AND NOT APPLE
     SOURCES
         time/qtimezoneprivate_tz.cpp
 )
@@ -993,6 +998,45 @@ qt_internal_extend_target(Core CONDITION ANDROID
         # place to put them.
 )
 
+qt_internal_extend_target(Core CONDITION OHOS
+    SOURCES
+        global/qoperatingsystemversion_openharmony.cpp
+        kernel/qohutility.h
+        kernel/qohutility.cpp
+        kernel/qohoswatchdog.h
+        kernel/qohoswatchdog.cpp
+        kernel/qjsobject.h
+        kernel/qjsobject_p.h
+        kernel/qjsobject.cpp
+        kernel/qjsmodule.h
+        kernel/qjsmodule.cpp
+        kernel/qjspromise_p.h
+        kernel/qjspromise.cpp
+        kernel/qopenharmony.h
+        kernel/qopenharmony.cpp
+        kernel/qopenharmony_p.h
+        kernel/qopenharmonydefines.h
+        kernel/qohhiappevent_p.h
+        kernel/qnapi.h
+        io/qsettings_openharmony.cpp
+        io/qstandardpaths_openharmony.cpp
+        io/qstorageinfo_unix.cpp
+        text/qlocale_harmony.cpp
+        kernel/qpermissions_openharmony.cpp
+    PUBLIC_LIBRARIES
+        deviceinfo_ndk.z
+        ace_napi.z
+        hilog_ndk.z
+        ohhicollie
+        deviceinfo_ndk.z
+        ohfileuri
+        uv
+        asset_ndk.z
+        bundle_ndk.z
+        ohenvironment
+)
+
+
 qt_internal_extend_target(Core CONDITION WIN32
     SOURCES
         platform/windows/qfactorycacheregistration_p.h
@@ -1008,7 +1052,7 @@ qt_internal_extend_target(Core CONDITION HAIKU AND NOT ANDROID
         be
 )
 
-qt_internal_extend_target(Core CONDITION UNIX AND NOT APPLE AND NOT HAIKU AND NOT ANDROID
+qt_internal_extend_target(Core CONDITION UNIX AND NOT APPLE AND NOT HAIKU AND NOT ANDROID AND NOT OHOS
     SOURCES
         io/qstandardpaths_unix.cpp
         io/qstorageinfo_unix.cpp
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake
index f7f658d5afe..f965f0ab1cd 100644
--- a/src/corelib/Qt6CoreMacros.cmake
+++ b/src/corelib/Qt6CoreMacros.cmake
@@ -599,6 +599,21 @@ function(_qt_internal_create_executable target)
                      PROPERTY _qt_android_apply_arch_suffix_called_from_qt_impl TRUE)
         qt6_android_apply_arch_suffix("${target}")
         set_property(TARGET "${target}" PROPERTY _qt_is_android_executable TRUE)
+    # elseif(OHOS)
+    #     list(REMOVE_ITEM ARGN "WIN32" "MACOSX_BUNDLE")
+    #     add_library("${target}" MODULE ${ARGN})
+    #     # On our qmake builds we do don't compile the executables with
+    #     # visibility=hidden. Not having this flag set will cause the
+    #     # executable to have main() hidden and can then no longer be loaded
+    #     # through dlopen()
+    #     set_property(TARGET "${target}" PROPERTY C_VISIBILITY_PRESET default)
+    #     set_property(TARGET "${target}" PROPERTY CXX_VISIBILITY_PRESET default)
+    #     set_property(TARGET "${target}" PROPERTY OBJC_VISIBILITY_PRESET default)
+    #     set_property(TARGET "${target}" PROPERTY OBJCXX_VISIBILITY_PRESET default)
+    #     set_property(TARGET "${target}"
+    #                  PROPERTY _qt_openharmony_apply_arch_suffix_called_from_qt_impl TRUE)
+    #     qt6_openharmony_apply_arch_suffix("${target}")
+    #     set_property(TARGET "${target}" PROPERTY _qt_is_openharmony_executable TRUE)
     else()
         add_executable("${target}" ${ARGN})
     endif()
@@ -740,8 +755,9 @@ function(qt6_finalize_target target)
     _qt_internal_expose_deferred_files_to_ide(${target})
     get_target_property(target_type ${target} TYPE)
     get_target_property(is_android_executable "${target}" _qt_is_android_executable)
+    get_target_property(is_openharmony_executable "${target}" _is_openharmony_executable)
 
-    if(target_type STREQUAL "EXECUTABLE" OR is_android_executable)
+    if(target_type STREQUAL "EXECUTABLE" OR is_android_executable OR is_openharmony_executable)
         _qt_internal_finalize_executable(${ARGV})
     endif()
 
@@ -2374,6 +2390,11 @@ function(_qt_internal_add_library target)
                      PROPERTY _qt_android_apply_arch_suffix_called_from_qt_impl TRUE)
         qt6_android_apply_arch_suffix("${target}")
     endif()
+    # if(OHOS)
+    #     set_property(TARGET "${target}"
+    #                  PROPERTY _qt_openharmony_apply_arch_suffix_called_from_qt_impl TRUE)
+    #     qt6_openharmony_apply_arch_suffix("${target}")
+    # endif()
 endfunction()
 
 if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
diff --git a/src/corelib/Qt6OpenHarmonyMacros.cmake b/src/corelib/Qt6OpenHarmonyMacros.cmake
new file mode 100644
index 00000000000..d17cda07c3d
--- /dev/null
+++ b/src/corelib/Qt6OpenHarmonyMacros.cmake
@@ -0,0 +1,18 @@
+function(qt6_openharmony_apply_arch_suffix target)
+    get_target_property(called_from_qt_impl
+        ${target} _qt_openharmony_apply_arch_suffix_called_from_qt_impl)
+    if(called_from_qt_impl)
+        # Don't show deprecation when called by our own function implementations.
+    else()
+        message(DEPRECATION
+            "Calling qt_openharmony_apply_arch_suffix directly is deprecated since Qt 6.5. "
+            "Use qt_add_executable or qt_add_library instead.")
+    endif()
+
+    get_target_property(target_type ${target} TYPE)
+    if (target_type STREQUAL "SHARED_LIBRARY" OR target_type STREQUAL "MODULE_LIBRARY")
+        set_property(TARGET "${target}" PROPERTY SUFFIX "_${CMAKE_OPENHARMONY_ARCH_ABI}.so")
+    elseif (target_type STREQUAL "STATIC_LIBRARY")
+        set_property(TARGET "${target}" PROPERTY SUFFIX "_${CMAKE_OPENHARMONY_ARCH_ABI}.a")
+    endif()
+endfunction()
diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake
index 8a4674b9bb5..deadc3f2da8 100644
--- a/src/corelib/configure.cmake
+++ b/src/corelib/configure.cmake
@@ -705,7 +705,7 @@ qt_feature("sharedmemory" PUBLIC
     SECTION "Kernel"
     LABEL "QSharedMemory"
     PURPOSE "Provides access to a shared memory segment."
-    CONDITION ( ANDROID OR WIN32 OR ( NOT VXWORKS AND ( TEST_ipc_sysv OR TEST_ipc_posix ) ) )
+    CONDITION (OHOS OR ANDROID OR WIN32 OR ( NOT VXWORKS AND ( TEST_ipc_sysv OR TEST_ipc_posix ) ) )
 )
 qt_feature_definition("sharedmemory" "QT_NO_SHAREDMEMORY" NEGATE VALUE "1")
 qt_feature("shortcut" PUBLIC
@@ -718,7 +718,7 @@ qt_feature("systemsemaphore" PUBLIC
     SECTION "Kernel"
     LABEL "QSystemSemaphore"
     PURPOSE "Provides a general counting system semaphore."
-    CONDITION ( NOT INTEGRITY AND NOT VXWORKS AND NOT rtems ) AND ( ANDROID OR WIN32 OR TEST_ipc_sysv OR TEST_ipc_posix )
+    CONDITION ( NOT INTEGRITY AND NOT VXWORKS AND NOT rtems ) AND (OHOS OR ANDROID OR WIN32 OR TEST_ipc_sysv OR TEST_ipc_posix )
 )
 qt_feature_definition("systemsemaphore" "QT_NO_SYSTEMSEMAPHORE" NEGATE VALUE "1")
 qt_feature("xmlstream" PUBLIC
@@ -963,7 +963,7 @@ qt_feature("permissions" PUBLIC
     SECTION "Utilities"
     LABEL "Application permissions"
     PURPOSE "Provides support for requesting user permission to access restricted data or APIs"
-    CONDITION APPLE OR ANDROID OR WASM
+    CONDITION APPLE OR ANDROID OR WASM OR OHOS
 )
 qt_configure_add_summary_section(NAME "Qt Core")
 qt_configure_add_summary_entry(ARGS "backtrace")
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 6461c1ca8a5..cc5cde19ae6 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1854,6 +1854,38 @@ static bool android_default_message_handler(QtMsgType type,
 }
 #endif //Q_OS_ANDROID
 
+#ifdef Q_OS_OPENHARMONY
+#include <hilog/log.h>
+#define APP_LOG_DOMAIN 0xf000
+#define APP_LOG_TAG "QtForOpenHarmony"
+
+static bool openharmony_default_message_handler(QtMsgType type,
+                                                const QMessageLogContext &context,
+                                                const QString &message)
+{
+#if 0
+    if (shouldLogToStderr())
+        return false; // Leave logging up to stderr handler
+#endif
+
+    QString formattedMessage = qFormatLogMessage(type, context, message);
+
+    LogLevel priority = LOG_INFO;
+    switch (type) {
+    //LOG_DEBUG unable to print, temporarily use LOG_ INFO replace.
+    case QtDebugMsg: priority = LOG_INFO; break;
+    case QtInfoMsg: priority = LOG_INFO; break;
+    case QtWarningMsg: priority = LOG_WARN; break;
+    case QtCriticalMsg: priority = LOG_ERROR; break;
+    case QtFatalMsg: priority = LOG_FATAL; break;
+    };
+
+    OH_LOG_Print(LOG_APP, priority, APP_LOG_DOMAIN, APP_LOG_TAG, "%{public}s %{public}s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(formattedMessage));
+
+    return true; // Prevent further output to stderr
+}
+#endif
+
 #ifdef Q_OS_WIN
 static void win_outputDebugString_helper(const QString &message)
 {
@@ -1965,6 +1997,8 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con
     handledStderr |= AppleUnifiedLogger::messageHandler(type, context, message);
 # elif defined Q_OS_WASM
     handledStderr |= wasm_default_message_handler(type, context, message);
+#elif defined Q_OS_OPENHARMONY
+    handledStderr |= openharmony_default_message_handler(type, context, message);
 # endif
 #endif
 
diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h
index ea1c68b168c..3ade264ea77 100644
--- a/src/corelib/global/qlogging.h
+++ b/src/corelib/global/qlogging.h
@@ -5,6 +5,13 @@
 
 #ifndef QLOGGING_H
 #define QLOGGING_H
+#ifdef Q_OS_OPENHARMONY
+#include <cstdarg>
+#include <array>
+#include <cstring>
+#include <stdio.h>
+#include <hitrace/trace.h>
+#endif
 
 #if 0
 // header is automatically included in qglobal.h
@@ -190,5 +197,29 @@ Q_CORE_EXPORT QString qFormatLogMessage(QtMsgType type, const QMessageLogContext
 Q_DECL_COLD_FUNCTION
 Q_CORE_EXPORT QString qt_error_string(int errorCode = -1);
 
+#ifdef Q_OS_OPENHARMONY
+class HiTracer {
+public:
+    HiTracer(const char *format, ...)
+    {
+        va_list ap;
+        va_start(ap, format);
+        std::array<char, 256> msgBuffer;
+        if (vsnprintf(msgBuffer.data(), msgBuffer.size(), format, ap) < 0) {
+            snprintf(msgBuffer.data(), msgBuffer.size(), "[error formatting label: %s]", format);
+        }
+        OH_HiTrace_StartTrace(msgBuffer.data());
+        va_end(ap);
+    }
+
+    ~HiTracer()
+    {
+        OH_HiTrace_FinishTrace();
+    }
+
+    HiTracer(const HiTracer&) = delete;
+    HiTracer& operator=(const HiTracer&) = delete;
+};
+#endif
 QT_END_NAMESPACE
 #endif // QLOGGING_H
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 8a2769a3ed9..669fdf30bb6 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -215,6 +215,7 @@ namespace Qt {
         SubWindow = 0x00000012,
         ForeignWindow = 0x00000020 | Window,
         CoverWindow = 0x00000040 | Window,
+        Floating = 0x00000080 | Window,
 
         WindowType_Mask = 0x000000ff,
         MSWindowsFixedSizeDialogHint = 0x00000100,
diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp
index 0a68846f2f3..daeb683c3d6 100644
--- a/src/corelib/global/qoperatingsystemversion.cpp
+++ b/src/corelib/global/qoperatingsystemversion.cpp
@@ -126,7 +126,7 @@ QOperatingSystemVersionBase QOperatingSystemVersionBase::current()
     return v;
 }
 
-#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
+#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN) && !defined(Q_OS_OPENHARMONY)
 QOperatingSystemVersionBase QOperatingSystemVersionBase::current_impl()
 {
     QOperatingSystemVersionBase version;
@@ -336,6 +336,8 @@ QString QOperatingSystemVersionBase::name(QOperatingSystemVersionBase osversion)
         return QStringLiteral("watchOS");
     case QOperatingSystemVersionBase::Android:
         return QStringLiteral("Android");
+    case QOperatingSystemVersionBase::OpenHarmony:
+        return QStringLiteral("OpenHarmony");
     case QOperatingSystemVersionBase::Unknown:
     default:
         return QString();
@@ -681,6 +683,7 @@ const QOperatingSystemVersion QOperatingSystemVersion::Android10 =
 const QOperatingSystemVersion QOperatingSystemVersion::Android11 =
     QOperatingSystemVersion(QOperatingSystemVersion::Android, 11, 0);
 
+
 /*!
     \variable QOperatingSystemVersion::Android12
     \brief a version corresponding to Android 12 (version 12.0, API level 31).
@@ -702,6 +705,22 @@ const QOperatingSystemVersionBase QOperatingSystemVersion::Android12L;
  */
 const QOperatingSystemVersionBase QOperatingSystemVersion::Android13;
 
+/*!
+    \variable QOperatingSystemVersion::OpenHarmony4
+    \brief a version corresponding to OpenHarmony 4 (version 4.0).
+    \since 6.5.5
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::OpenHarmony4 =
+        QOperatingSystemVersion(QOperatingSystemVersion::OpenHarmony, 4, 0);
+
+/*!
+    \variable QOperatingSystemVersion::OpenHarmony5
+    \brief a version corresponding to OpenHarmony 5 (version 5.0).
+    \since 6.5.5
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::OpenHarmony5 =
+        QOperatingSystemVersion(QOperatingSystemVersion::OpenHarmony, 5, 0);
+
 #endif // !QT_BOOTSTRAPPED
 
 #ifndef QT_NO_DEBUG_STREAM
diff --git a/src/corelib/global/qoperatingsystemversion.h b/src/corelib/global/qoperatingsystemversion.h
index dc830f9736b..e28ea78b335 100644
--- a/src/corelib/global/qoperatingsystemversion.h
+++ b/src/corelib/global/qoperatingsystemversion.h
@@ -23,7 +23,8 @@ public:
         IOS,
         TvOS,
         WatchOS,
-        Android
+        Android,
+        OpenHarmony
     };
 
     constexpr QOperatingSystemVersionBase(OSType osType,
@@ -52,6 +53,8 @@ public:
         return WatchOS;
 #elif defined(Q_OS_ANDROID)
         return Android;
+#elif defined(Q_OS_OPENHARMONY)
+        return OpenHarmony;
 #else
         return Unknown;
 #endif
@@ -113,7 +116,8 @@ public:
         IOS,
         TvOS,
         WatchOS,
-        Android
+        Android,
+        OpenHarmony
     };
 #endif
 
@@ -152,6 +156,8 @@ public:
     static const QOperatingSystemVersion AndroidPie;
     static const QOperatingSystemVersion Android10;
     static const QOperatingSystemVersion Android11;
+    static const QOperatingSystemVersion OpenHarmony4;
+    static const QOperatingSystemVersion OpenHarmony5;
 #else
     static constexpr QOperatingSystemVersionBase Windows7 { QOperatingSystemVersionBase::Windows, 6, 1 };
     static constexpr QOperatingSystemVersionBase Windows8 { QOperatingSystemVersionBase::Windows, 6, 2 };
@@ -182,6 +188,8 @@ public:
     static constexpr QOperatingSystemVersionBase AndroidPie { QOperatingSystemVersionBase::Android, 9, 0 };
     static constexpr QOperatingSystemVersionBase Android10 { QOperatingSystemVersionBase::Android, 10, 0 };
     static constexpr QOperatingSystemVersionBase Android11 { QOperatingSystemVersionBase::Android, 11, 0 };
+    static constexpr QOperatingSystemVersionBase OpenHarmony15 { QOperatingSystemVersionBase::OpenHarmony, 4, 0 };
+    static constexpr QOperatingSystemVersionBase OpenHarmony16 { QOperatingSystemVersionBase::OpenHarmony, 5, 0 };
 #endif // New (static constexpr) entries go here, only cherry-pick as far back as 6.3 (QTBUG-97808):
 
     static constexpr QOperatingSystemVersionBase Windows10_1809 { QOperatingSystemVersionBase::Windows, 10, 0, 17763 }; // RS5
diff --git a/src/corelib/global/qoperatingsystemversion_openharmony.cpp b/src/corelib/global/qoperatingsystemversion_openharmony.cpp
new file mode 100644
index 00000000000..93c2bc4cee8
--- /dev/null
+++ b/src/corelib/global/qoperatingsystemversion_openharmony.cpp
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qoperatingsystemversion.h"
+#include "qohutility.h"
+
+#include <QVersionNumber>
+
+QT_BEGIN_NAMESPACE
+
+QOperatingSystemVersionBase QOperatingSystemVersionBase::current_impl()
+{
+    QOperatingSystemVersionBase version;
+    version.m_os = currentType();
+    const QVersionNumber v = QVersionNumber::fromString(QtOh::Utility::distributionOSVersion());
+    if (!v.isNull()) {
+        version.m_major = v.majorVersion();
+        version.m_minor = v.minorVersion();
+        version.m_micro = v.microVersion();
+        return version;
+    }
+    version.m_major = -1;
+    version.m_minor = -1;
+    version.m_micro = -1;
+    return version;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qsysinfo.cpp b/src/corelib/global/qsysinfo.cpp
index 87f6d5a0db0..29703235c6d 100644
--- a/src/corelib/global/qsysinfo.cpp
+++ b/src/corelib/global/qsysinfo.cpp
@@ -474,6 +474,13 @@ static const char *osVer_helper(QOperatingSystemVersion)
 }
 #endif
 
+#ifdef Q_OS_OPENHARMONY
+static const char *osVer_helper(QOperatingSystemVersion)
+{
+    return "";
+}
+#endif
+
 /*!
     \since 5.4
 
@@ -779,6 +786,9 @@ QString QSysInfo::productType()
 #elif defined(Q_OS_ANDROID)
     return QStringLiteral("android");
 
+#elif defined(Q_OS_OPENHARMONY)
+    return QStringLiteral("openharmony");
+
 #elif defined(Q_OS_IOS)
     return QStringLiteral("ios");
 #elif defined(Q_OS_TVOS)
@@ -838,6 +848,9 @@ QString QSysInfo::productVersion()
 #if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN)
     const auto version = QOperatingSystemVersion::current();
     return QString::asprintf("%d.%d", version.majorVersion(), version.minorVersion());
+#elif defined(Q_OS_OPENHARMONY)
+    const auto version = QOperatingSystemVersion::current();
+    return QString::asprintf("%d.%d.%d", version.majorVersion(), version.minorVersion(), version.microVersion());
 #elif defined(Q_OS_WIN)
     const char *version = osVer_helper();
     if (version) {
@@ -873,7 +886,7 @@ QString QSysInfo::productVersion()
 */
 QString QSysInfo::prettyProductName()
 {
-#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN)
+#if defined(Q_OS_ANDROID) || defined(Q_OS_OPENHARMONY) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN)
     const auto version = QOperatingSystemVersion::current();
     const int majorVersion = version.majorVersion();
     const QString versionString = QString::asprintf("%d.%d", majorVersion, version.minorVersion());
diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h
index 2ec017152a4..94aa255222a 100644
--- a/src/corelib/global/qsystemdetection.h
+++ b/src/corelib/global/qsystemdetection.h
@@ -88,6 +88,9 @@
 #elif defined(__ANDROID__) || defined(ANDROID)
 #  define Q_OS_ANDROID
 #  define Q_OS_LINUX
+#elif defined(__OHOS__) || defined(OPENHARMONY)
+#  define Q_OS_OPENHARMONY
+#  define Q_OS_LINUX
 #elif defined(__CYGWIN__)
 #  define Q_OS_CYGWIN
 #elif !defined(SAG_COM) && (!defined(WINAPI_FAMILY) || WINAPI_FAMILY==WINAPI_FAMILY_DESKTOP_APP) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index ec67ca6f483..2a5ce3d8bc4 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -768,7 +768,7 @@ QFile::copy(const QString &newName)
                 d->setError(QFile::CopyError, tr("Cannot open %1 for input").arg(d->fileName));
             } else {
                 const auto fileTemplate = "%1/qt_temp.XXXXXX"_L1;
-#ifdef QT_NO_TEMPORARYFILE
+#if defined(QT_NO_TEMPORARYFILE) || defined(Q_OS_OPENHARMONY)
                 QFile out(fileTemplate.arg(QFileInfo(newName).path()));
                 if (!out.open(QIODevice::ReadWrite))
                     error = true;
@@ -820,7 +820,7 @@ QFile::copy(const QString &newName)
                                         .arg(newName, out.errorString()));
                         }
                     }
-#ifdef QT_NO_TEMPORARYFILE
+#if defined(QT_NO_TEMPORARYFILE) || defined(Q_OS_OPENHARMONY)
                     if (error)
                         out.remove();
 #else
diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp
index 7f5480c2749..14c85977122 100644
--- a/src/corelib/io/qfileselector.cpp
+++ b/src/corelib/io/qfileselector.cpp
@@ -165,6 +165,9 @@ static bool isLocalScheme(const QString &file)
     bool local = file == "qrc"_L1;
 #ifdef Q_OS_ANDROID
     local |= file == "assets"_L1;
+#endif
+#ifdef Q_OS_OPENHARMONY
+    local |= file == QLatin1String("rawfile");
 #endif
     return local;
 }
@@ -189,7 +192,10 @@ QUrl QFileSelector::select(const QUrl &filePath) const
         if (filePath.scheme() == "assets"_L1)
             scheme = "assets:"_L1;
 #endif
-
+#ifdef Q_OS_OPENHARMONY
+        if (filePath.scheme() == QLatin1String("rawfile"))
+            scheme = QLatin1String("rawfile:");
+#endif
         QString equivalentPath = scheme + filePath.path();
         QString selectedPath = d->select(equivalentPath);
         ret.setPath(selectedPath.remove(0, scheme.size()));
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 58cc9e503fb..bbe09df6a7d 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -72,6 +72,15 @@ extern "C" NSString *NSTemporaryDirectory();
 #  undef STATX_BASIC_STATS
 #endif
 
+#ifdef Q_OS_OPENHARMONY
+#if OHOS_SDK_VERSION >= 17
+#include "qjsmodule.h"
+#include "private/qopenharmony_p.h"
+#include "private/qjspromise_p.h"
+#include <filemanagement/file_uri/oh_file_uri.h>
+#endif
+#endif
+
 #ifndef STATX_ALL
 struct statx { mode_t stx_mode; };      // dummy
 #endif
@@ -1275,7 +1284,29 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source,
         return false;
     }
     const QString sourcePath = sourceInfo.absoluteFilePath();
+#if defined(Q_OS_OPENHARMONY) && (OHOS_SDK_VERSION >= 17)
+    if (qApp && !qApp->inherits("QGuiApplication")) {
+        error = QSystemError(ENOENT, QSystemError::NativeError);
+        return false;
+    }
+    QString targetPath = QtOh::runOnJsUIThreadWithPromise<QString>([](auto p, const QString &filePath){
+        static QJsModule fileManagerService(QString::fromUtf8("@hms.filemanagement.fileManagerService"));
+        QString uri = QtOh::uriFromPath(filePath);
+        if (uri.isEmpty()) {
+            p->set_value(QString());
+            return;
+        }
 
+        Napi::Promise result = fileManagerService.call(QString::fromUtf8("deleteToTrash"), {Napi::Value::From(fileManagerService.env(), uri.toStdString())}).As<Napi::Promise>();
+        QJsPromise promise(result);
+        promise.onThen([p](const Napi::CallbackInfo &info){
+            QString fileName = QString::fromStdString(info[0].ToString());
+            p->set_value(QtOh::pathFromUri(fileName));
+        }).onCatch([p](const Napi::CallbackInfo &info){
+            p->set_value(QString());
+        });
+    }, sourcePath);
+#else
     QDir trashDir(freeDesktopTrashLocation(sourcePath));
     if (!trashDir.exists())
         return false;
@@ -1363,7 +1394,7 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source,
             + "\n";
     infoFile.write(info);
     infoFile.close();
-
+#endif
     newLocation = QFileSystemEntry(targetPath);
     return true;
 #endif // QT_BOOTSTRAPPED
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 3c74fcb634d..803f7d2245d 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -272,7 +272,7 @@ QString QSettingsPrivate::normalizedKey(QAnyStringView key)
 
 // see also qsettings_win.cpp and qsettings_mac.cpp
 
-#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) && !defined(Q_OS_WASM)
+#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) && !defined(Q_OS_WASM) && !defined(Q_OS_OPENHARMONY)
 QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope,
                                            const QString &organization, const QString &application)
 {
@@ -280,7 +280,7 @@ QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::
 }
 #endif
 
-#if !defined(Q_OS_WIN)
+#if !defined(Q_OS_WIN) && !defined(Q_OS_OPENHARMONY)
 QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format)
 {
     return new QConfFileSettingsPrivate(fileName, format);
@@ -1432,7 +1432,7 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
         ensureAllSectionsParsed(confFile);
         ParsedSettingsMap mergedKeys = confFile->mergedKeyMap();
 
-#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(temporaryfile)
+#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(temporaryfile) && !defined(Q_OS_OPENHARMONY)
         QSaveFile sf(confFile->name);
         sf.setDirectWriteFallback(!atomicSyncOnly);
 #    ifdef Q_OS_ANDROID
@@ -1466,7 +1466,7 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
             ok = writeFunc(sf, tempOriginalKeys);
         }
 
-#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(temporaryfile)
+#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(temporaryfile) && !defined(Q_OS_OPENHARMONY)
         if (ok)
             ok = sf.commit();
 #endif
diff --git a/src/corelib/io/qsettings_openharmony.cpp b/src/corelib/io/qsettings_openharmony.cpp
new file mode 100644
index 00000000000..671cd961615
--- /dev/null
+++ b/src/corelib/io/qsettings_openharmony.cpp
@@ -0,0 +1,778 @@
+#include "qsettings.h"
+#include "qsettings_p.h"
+#include <asset/asset_api.h>
+// #include <QDebug>
+#include <QCborValue>
+QT_BEGIN_NAMESPACE
+
+/**
+ * @brief 官方API约束限制
+ * @note 批量查询出的关键资产需要通过IPC通道传输给业务,受IPC缓冲区大小限制,
+ * 建议对查询超过40条关键资产时,进行分批查询,且每次查询数量不超过40条
+ *
+ * @see https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/asset-native-query-V5
+ */
+constexpr Asset_Attr GlobalReturnLimitAttr = { ASSET_TAG_RETURN_LIMIT, { .u32 = 40 } };
+constexpr char GlobalLabel[] = "QOhAssetStore";
+const Asset_Attr GlobalAssetStoreLabelAttr = { ASSET_TAG_DATA_LABEL_NORMAL_1,
+    { .blob = {static_cast<quint32>(strlen(GlobalLabel)), reinterpret_cast<quint8 *>(const_cast<char *>(GlobalLabel))} }
+};
+
+static Asset_ResultCode retCode = ASSET_SUCCESS;
+using AssetResultSetCallback = std::function<void(const Asset_ResultSet&)>;
+
+class QOhAssetStoreHelper {
+
+public:
+
+public:
+    // class iterator {
+    // public:
+    //     using value_type = QPair<QString, QVariant>;
+    //     explicit iterator(int idx = 0);
+    //     value_type operator*() const;
+    //     QString key() const;
+    //     QVariant value() const;
+    //     iterator &operator++();
+    //     bool operator!=(const iterator &) const;
+    // private:
+    //     QStringList m_keys = {};
+    //     int m_index = -1;
+    // };
+
+    // class reference : public QVariant {
+    // public:
+    //     explicit reference(const QString &);
+    //     reference &operator=(const QVariant &);
+    // private:
+    //     QString m_key = QString();
+    // };
+
+    // iterator begin() const;
+    // iterator end()   const;
+
+    // reference operator[](const QString &key);
+    // QVariant operator[](const QString &key) const;
+
+    QOhAssetStoreHelper(const QOhAssetStoreHelper &) = delete;
+    QOhAssetStoreHelper &operator=(const QOhAssetStoreHelper &) = delete;
+
+    QOhAssetStoreHelper(QOhAssetStoreHelper &&) = delete;
+    QOhAssetStoreHelper &operator=(QOhAssetStoreHelper &&) = delete;
+
+    /**
+     * @brief instance
+     * @return QOhAssetStoreHelper 的单例实例
+     */
+    static QOhAssetStoreHelper &instance();
+    /**
+     * @brief insert 插入或更新一个别名和对应的秘密数据
+     * @param alias 关键资产别名,每条关键资产的唯一索引
+     * @param secret 关键资产明文,可以是任意 QVariant 类型
+     * @return 成功插入或更新返回 true,否则返回 false
+     */
+    bool insert(const QString &alias, const QVariant &secret);
+    /**
+     * @brief remove 从存储中移除指定别名的资产
+     * @param alias 关键资产别名
+     * @return 成功移除返回 true,否则返回 false
+     */
+    bool remove(const QString &alias);
+    /**
+     * @brief contains 检查存储中是否存在指定别名的资产
+     * @param alias 关键资产别名
+     * @return 存在返回 true,否则返回 false
+     */
+    bool contains(const QString &alias) const;
+    /**
+     * @brief value 获取指定别名的资产值
+     * @param alias 关键资产别名
+     * @return 资产值,如果不存在则返回无效 QVariant
+     */
+    QVariant value(const QString &alias) const;
+    /**
+     * @brief value 获取指定别名的资产值,如果不存在则返回默认值
+     * @param alias 关键资产别名
+     * @param defaultValue 默认值
+     * @return 资产值,如果不存在则返回 defaultValue
+     */
+    QVariant value(const QString &alias, const QVariant &defaultValue) const;
+    /**
+     * @brief keys 获取存储中所有资产的别名列表
+     * @return 别名列表
+     */
+    QStringList keys() const;
+    /**
+     * @brief size 获取存储中资产的数量
+     * @return 资产数量
+     */
+    int size() const;
+    /**
+     * @brief clear 清空存储中的所有资产
+     * @return 成功清空返回 true,否则返回 false
+     */
+    bool clear();
+    /**
+     * @brief lastError 获取最近一次操作的错误信息
+     * @return 错误信息字符串,如果没有错误则返回空字符串
+     */
+    QString lastError() const;
+
+private:
+    QOhAssetStoreHelper();
+};
+/**
+ * @brief deserialize 将序列化字符串反序列化为 QVariant
+ * @param str 序列化的字符串
+ * @return 反序列化后的 QVariant
+ */
+static QVariant deserialize(const QByteArray &byteArray)
+{
+    if (byteArray.isEmpty()) return QVariant();
+    return QCborValue::fromCbor(byteArray).toVariant();
+}
+
+/**
+ * @brief serialize 将 QVariant 序列化为 QByteArray 字符串
+ * @param value 待序列化的 QVariant
+ * @return 序列化字符串
+ */
+static QByteArray serialize(const QVariant &value)
+{
+    if (!value.isValid()) return QByteArray();
+    return QCborValue::fromVariant(value).toCbor();
+}
+/**
+ * @brief createBlob 创建一个 Asset_Blob 对象
+ * @param data 待转换的 QByteArray 数据
+ * @return 返回创建的 Asset_Blob 对象
+ */
+static Asset_Blob createBlob(const QByteArray &data)
+{
+    return Asset_Blob{static_cast<quint32>(data.size()), reinterpret_cast<quint8 *>(const_cast<char *>(data.data()))};
+}
+/**
+ * @brief blobToByteArray 将 Asset_Blob 转换为 QByteArray
+ * @param blob 待转换的 Asset_Blob 对象
+ * @return 返回转换后的 QByteArray,如果 blob 为空则返回空 QByteArray
+ */
+static QByteArray blobToByteArray(const Asset_Blob &blob)
+{
+    if (!blob.data || blob.size == 0) return QByteArray();
+    return QByteArray(reinterpret_cast<const char *>(blob.data), blob.size);
+}
+/**
+ * @brief removeAsset 根据指定的过滤条件和标签从存储中移除资产
+ * @param filter 过滤条件字符串
+ * @param filterTag 过滤标签
+ * @return 成功移除返回 true,否则返回 false
+ */
+static bool removeAsset(const QString &filter,  const quint32 &filterTag)
+{
+    const int count = 1;
+    Asset_Attr attrs[count];
+    QByteArray filterByte = filter.toUtf8();
+    attrs[0] = { filterTag, { .blob = createBlob(filterByte) } };
+    retCode = (Asset_ResultCode)OH_Asset_Remove(attrs, count);
+    return retCode == ASSET_SUCCESS;
+}
+/**
+ * @brief queryAsset 根据别名查询资产,并通过回调函数返回结果集
+ * @param alias 资产别名
+ * @param callback 查询结果的回调函数
+ * @param retType 返回类型,决定返回的属性集
+ */
+static void queryAsset(const QString &alias, AssetResultSetCallback callback, const quint32 &retType)
+{
+    const int count = 2;
+    Asset_Attr filter[count];
+    QByteArray aliasByte = alias.toUtf8();
+    filter[0] = { ASSET_TAG_ALIAS, { .blob = createBlob(aliasByte) } };
+    filter[1] = { ASSET_TAG_RETURN_TYPE, { .u32 = retType } };
+
+    Asset_ResultSet rs = {0};
+    if (retCode = (Asset_ResultCode)OH_Asset_Query(filter, count, &rs); retCode == ASSET_SUCCESS && rs.count > 0) {
+        callback(rs);
+    }
+    OH_Asset_FreeResultSet(&rs);
+}
+/**
+ * @brief batchQuery 批量查询资产,并通过回调函数返回结果集
+ * @param callback 查询结果的回调函数
+ * @param retType 返回类型,决定返回的属性集
+ */
+static void batchQuery(AssetResultSetCallback callback, const quint32 &retType)
+{
+    quint32 offset = 0;
+    /*
+     * filter by ASSET_TAG_DATA_LABEL_NORMAL_1 with pagination
+     */
+    const int count = 5;
+    while (true) {
+        Asset_Attr filter[count];
+        filter[0] = GlobalAssetStoreLabelAttr;
+        filter[1] = { ASSET_TAG_RETURN_TYPE, { .u32 = retType } };
+        filter[2] = GlobalReturnLimitAttr;
+        filter[3] = { ASSET_TAG_RETURN_OFFSET, { .u32 = offset } };
+        filter[4] = { ASSET_TAG_RETURN_ORDERED_BY, { .u32 = ASSET_TAG_DATA_LABEL_NORMAL_1 } };
+
+        Asset_ResultSet rs = {0};
+
+        if (retCode = (Asset_ResultCode)OH_Asset_Query(filter, count, &rs); retCode == ASSET_SUCCESS && rs.count > 0) {
+            callback(rs);
+            OH_Asset_FreeResultSet(&rs);
+            if (rs.count < GlobalReturnLimitAttr.value.u32) break;
+            offset += GlobalReturnLimitAttr.value.u32;
+            continue;
+        }
+        else {
+            OH_Asset_FreeResultSet(&rs);
+            break;
+        }
+    }
+}
+/**
+ * @brief qohAssetGetBlob 从查询结果中获取指定标签的 Blob 数据
+ * @param result 查询结果集
+ * @param tag 指定的标签
+ * @return 返回对应标签的 Blob 数据,如果未找到则返回空 QByteArray
+ */
+static QByteArray qohAssetGetBlob(const Asset_Result *result, const Asset_Tag tag)
+{
+    if (auto *assetAttr = OH_Asset_ParseAttr(result, tag)) return blobToByteArray(assetAttr->value.blob);
+    return QByteArray();
+}
+
+QOhAssetStoreHelper::QOhAssetStoreHelper() {}
+
+// QOhAssetStoreHelper::iterator QOhAssetStoreHelper::begin() const { return iterator(); }
+
+// QOhAssetStoreHelper::iterator QOhAssetStoreHelper::end() const { return iterator(-1); }
+
+
+// QOhAssetStoreHelper::reference QOhAssetStoreHelper::operator[](const QString &key) {
+//     return reference(key);
+// }
+
+// QVariant QOhAssetStoreHelper::operator[](const QString &key) const {
+//     return reference(key);
+// }
+
+QOhAssetStoreHelper &QOhAssetStoreHelper::instance()
+{
+    static QOhAssetStoreHelper s_instance;
+    return s_instance;
+}
+
+bool QOhAssetStoreHelper::insert(const QString &alias, const QVariant &secret)
+{
+    QByteArray secreByte = serialize(secret);
+    QByteArray aliasByte = alias.toUtf8();
+    
+    const uint32_t count = 4;
+    Asset_Attr attrs[count];
+    attrs[0] = GlobalAssetStoreLabelAttr;
+    attrs[1] = { ASSET_TAG_CONFLICT_RESOLUTION, { .u32 = ASSET_CONFLICT_OVERWRITE } };
+    attrs[2] = { ASSET_TAG_ALIAS, { .blob = createBlob(aliasByte) } };
+    attrs[3] = { ASSET_TAG_SECRET, { .blob = createBlob(secreByte) } };
+    
+    int32_t code = OH_Asset_Add(attrs, sizeof(attrs) / sizeof(attrs[0]));
+    retCode  = (Asset_ResultCode)(code);
+    return retCode == ASSET_SUCCESS;
+}
+
+bool QOhAssetStoreHelper::remove(const QString &alias)
+{
+    return removeAsset(alias, ASSET_TAG_ALIAS);
+}
+
+bool QOhAssetStoreHelper::contains(const QString &alias) const
+{
+    bool found = false;
+    queryAsset(alias, [&found](const Asset_ResultSet &rs) { found = rs.count > 0; }, ASSET_RETURN_ATTRIBUTES);
+    return found;
+}
+
+QVariant QOhAssetStoreHelper::value(const QString &alias) const
+{
+    QVariant secret;
+    queryAsset(alias, [&secret](const auto &rs) {
+        secret = deserialize(qohAssetGetBlob(rs.results, ASSET_TAG_SECRET));
+    }, ASSET_RETURN_ALL);
+    return secret;
+}
+
+QVariant QOhAssetStoreHelper::value(const QString &alias, const QVariant &defaultValue) const
+{
+    if (QVariant secret = value(alias); secret.isValid()) return secret;
+    return defaultValue;
+}
+
+QStringList QOhAssetStoreHelper::keys() const
+{
+    QStringList list;
+    batchQuery([&list](const auto &rs) {
+        for (quint32 i = 0; i < rs.count; ++i)
+            list.append(qohAssetGetBlob(rs.results + i, ASSET_TAG_ALIAS));
+    }, ASSET_RETURN_ATTRIBUTES);
+    return list;
+}
+
+int QOhAssetStoreHelper::size() const
+{
+    int total = 0;
+    batchQuery([&total](const auto &rs) {total += rs.count;}, ASSET_RETURN_ATTRIBUTES);
+    return total;
+}
+
+bool QOhAssetStoreHelper::clear()
+{
+    return removeAsset(GlobalLabel, ASSET_TAG_DATA_LABEL_NORMAL_1);
+}
+
+QString QOhAssetStoreHelper::lastError() const
+{
+    switch (retCode) {
+    case ASSET_SUCCESS:
+        return QString();
+    case ASSET_PERMISSION_DENIED:
+        return QStringLiteral("The caller doesn't have the permission.");
+    case ASSET_INVALID_ARGUMENT:
+        return QStringLiteral("The parameter is invalid.");
+    case ASSET_SERVICE_UNAVAILABLE:
+        return QStringLiteral("The ASSET service is unavailable.");
+    case ASSET_NOT_FOUND:
+        return QStringLiteral("The asset is not found.");
+    case ASSET_DUPLICATED:
+        return QStringLiteral("The asset already exists.");
+    case ASSET_ACCESS_DENIED:
+        return QStringLiteral("Access to the asset is denied.");
+    case ASSET_STATUS_MISMATCH:
+        return QStringLiteral("The status of the asset does not match.");
+    case ASSET_OUT_OF_MEMORY:
+        return QStringLiteral("The system runs out of memory.");
+    case ASSET_DATA_CORRUPTED:
+        return QStringLiteral("The asset data is corrupted.");
+    case ASSET_DATABASE_ERROR:
+        return QStringLiteral("The database operation failed.");
+    case ASSET_CRYPTO_ERROR:
+        return QStringLiteral("The cryptography operation failed.");
+    case ASSET_IPC_ERROR:
+        return QStringLiteral("IPC failed.");
+    case ASSET_BMS_ERROR:
+        return QStringLiteral("Calling the Bundle Manager service failed.");
+    case ASSET_ACCOUNT_ERROR:
+        return QStringLiteral("Calling the OS Account service failed.");
+    case ASSET_ACCESS_TOKEN_ERROR:
+        return QStringLiteral("Calling the Access Token service failed.");
+    case ASSET_FILE_OPERATION_ERROR:
+        return QStringLiteral("The file operation failed.");
+    case ASSET_GET_SYSTEM_TIME_ERROR:
+        return QStringLiteral("Getting the system time failed.");
+    case ASSET_LIMIT_EXCEEDED:
+        return QStringLiteral("The cache exceeds the limit.");
+    case ASSET_UNSUPPORTED:
+        return QStringLiteral("The capability is not supported.");
+    }
+}
+
+// QOhAssetStoreHelper::iterator::iterator(int idx)
+//     : m_keys(QOhAssetStoreHelper::instance().keys()), m_index(idx)
+// {
+//     if (m_index < 0)
+//         m_index = m_keys.size();
+// }
+
+// QOhAssetStoreHelper::iterator::value_type QOhAssetStoreHelper::iterator::operator*() const {
+//     const QString &k = m_keys[m_index];
+//     return { k, QOhAssetStoreHelper::instance().value(k) };
+// }
+
+// QString QOhAssetStoreHelper::iterator::key() const {
+//     return m_keys[m_index];
+// }
+
+// QVariant QOhAssetStoreHelper::iterator::value() const {
+//     return QOhAssetStoreHelper::instance().value(m_keys[m_index]);
+// }
+
+// QOhAssetStoreHelper::iterator &QOhAssetStoreHelper::iterator::operator++() {
+//     ++m_index;
+//     return *this;
+// }
+
+// bool QOhAssetStoreHelper::iterator::operator!=(const iterator &other) const {
+//     return m_index != other.m_index;
+// }
+
+// QOhAssetStoreHelper::reference::reference(const QString &k)
+//     : m_key(k)
+// {
+//     setValue(QOhAssetStoreHelper::instance().value(m_key, QVariant()));
+// }
+
+// QOhAssetStoreHelper::reference &QOhAssetStoreHelper::reference::operator=(const QVariant &v) {
+//     if(QOhAssetStoreHelper::instance().insert(m_key, v)) setValue(v);
+//     return *this;
+// }
+
+/*
+ * 使用QHash<QString, QVariant>最小化的QSettings实现,仅用于通过基础测试,后切换到 QOhAssetStoreHelper
+ */
+#define USE_ASSET_STORE
+#ifdef USE_ASSET_STORE
+static auto &globalStorage = QOhAssetStoreHelper::instance();
+#else
+static QHash<QString, QVariant> globalStorage;
+#endif
+
+class QOhSettingsPrivate : public QSettingsPrivate
+{
+public:
+    QOhSettingsPrivate(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application);
+    QOhSettingsPrivate(const QString &rKey);
+    ~QOhSettingsPrivate();
+    
+    void remove(const QString &key) override;
+    void set(const QString &key, const QVariant &value) override;
+    std::optional<QVariant> get(const QString &key) const override;
+    QStringList children(const QString &prefix, ChildSpec spec) const override;
+    void clear() override;
+    void sync() override;
+    void flush() override;
+    bool isWritable() const override;
+    QString fileName() const override;
+
+private:
+    QString qSettingsInit;
+};
+
+QOhSettingsPrivate::QOhSettingsPrivate(QSettings::Format format, QSettings::Scope scope,
+                                          const QString &organization, const QString &application)
+    : QSettingsPrivate(format, scope, organization, application)
+{
+    if (organization.isEmpty()) {
+        setStatus(QSettings::AccessError);
+        return;
+    }
+
+    qSettingsInit = organization;
+    if (!application.isEmpty()) {
+        qSettingsInit += "/" + application;
+    }
+
+    switch (scope) {
+    case QSettings::UserScope:
+        qSettingsInit = QString::fromLatin1("QOhSettings.User/") + qSettingsInit;
+        break;
+    case QSettings::SystemScope:
+        qSettingsInit = QString::fromLatin1("QOhSettings.System/") + qSettingsInit;
+        break;
+    }
+    /*
+     * 调试信息
+     */
+    // qDebug() << "QOhSettingsPrivate constructor1 - qSettingsInit:" << qSettingsInit;
+}
+
+QOhSettingsPrivate::QOhSettingsPrivate(const QString &rKey)
+    : QSettingsPrivate(QSettings::NativeFormat)
+{
+    if (!rKey.isEmpty()) {
+        /*
+         * 对于OpenHarmony,fileName就是我们的qSettingsInit
+         * 确保使用相同的键格式,以便不同构造方式的实例能共享数据
+         */
+        qSettingsInit = rKey;
+    } else {
+        setStatus(QSettings::AccessError);
+    }
+    /*
+     * 调试信息
+     */
+    // qDebug() << "QOhSettingsPrivate constructor2 - qSettingsInit:" << qSettingsInit;
+}
+
+QOhSettingsPrivate::~QOhSettingsPrivate()
+{
+
+}
+
+void QOhSettingsPrivate::remove(const QString &uKey)
+{
+    if (uKey.isEmpty()) {
+        return;
+    }
+    /*
+     * 构建完整的键,不要重复添加groupPrefix,因为QSettings已经处理了
+     */
+    QString fullKey = qSettingsInit + "/" + uKey;
+    /*
+     * 删除指定的键
+     */
+    globalStorage.remove(fullKey);
+    /*
+     * 删除所有以该键为前缀的子键
+     */
+    QString keyPrefix = fullKey + "/";
+    // QStringList keysToRemove;
+    
+    auto keys = globalStorage.keys();
+    for(const auto &key : keys) {
+        if (key.startsWith(keyPrefix)) {
+            // keysToRemove << key;
+            globalStorage.remove(key);
+        }
+    }
+    // for (auto it = globalStorage.begin(); it != globalStorage.end(); ++it) {
+    //     if (it.key().startsWith(keyPrefix)) {
+    //         keysToRemove << it.key();
+    //     }
+    // }
+    
+    // for (const QString &key : keysToRemove) {
+    //     globalStorage.remove(key);
+    // }
+    
+    /*
+     * 调试信息
+     */
+    // qDebug() << "QOhSettingsPrivate::remove - removed key:" << fullKey << "and" << keysToRemove.size() << "subkeys" << "groupPrefix:" << groupPrefix;
+}
+
+void QOhSettingsPrivate::set(const QString &uKey, const QVariant &value)
+{
+    if (uKey.isEmpty()) {
+        return;
+    }
+    
+    if (!value.isValid()) {
+        remove(uKey);
+        return;
+    }
+    /*
+     * 构建完整的键,不要重复添加groupPrefix,因为QSettings已经处理了
+     */
+    QString fullKey = qSettingsInit + "/" + uKey;
+    
+    // globalStorage[fullKey] = value;
+    globalStorage.insert(fullKey, value);
+    
+    /*
+     * 调试信息
+     */
+    // qDebug() << "QOhSettingsPrivate::set - qSettingsInit:" << qSettingsInit << "stored key:" << fullKey << "value:" << value;
+}
+
+std::optional<QVariant> QOhSettingsPrivate::get(const QString &uKey) const
+{
+    std::optional<QVariant> result;
+    if (uKey.isEmpty() ) {
+        return result;
+    }
+    
+    /*
+     * 构建完整的键,不要重复添加groupPrefix,因为QSettings已经处理了
+     */
+    QString fullKey = qSettingsInit + "/" + uKey;
+    auto getOrFind = [&result](const QString &key) -> bool {
+        if (const auto va = globalStorage.value(key); va.isValid()) {
+            result = va;
+            return true;
+        } else {
+            if(globalStorage.contains(key))
+                return true;
+        }
+        return false;
+    };
+    /*
+     * 首先尝试直接查找
+     */
+    if (bool ret = getOrFind(fullKey)) return ret;
+    /*
+     * 只有在启用fallback时才进行fallback查找
+     */
+    if (!fallbacks) {
+        return false;
+    }
+    /*
+     * 优先级1: 同一scope内的no-app fallback (最高优先级)
+     */
+    QStringList parts = fullKey.split("/");
+    if (parts.size() >= 4) {            // scope / organization / application / key
+        QString sameScope = parts[0];   // QOhSettings.User / QOhSettings.System
+        QString noAppSameScopeKey = sameScope + "/" + parts[1] + "/" + parts.mid(3).join("/");
+        if (bool ret = getOrFind(noAppSameScopeKey)) return result;
+    }
+    /*
+     * 优先级2: 跨scope完全匹配 fallback (只对UserScope)
+     */
+    if (qSettingsInit.contains("QOhSettings.User")) {
+        QString fallbackKey = fullKey;
+        fallbackKey.replace(0, QString("QOhSettings.User").length(), "QOhSettings.System");
+        if (bool ret = getOrFind(fallbackKey)) return result;
+        /*
+         * 优先级3: 跨scope no-app fallback (最低优先级)
+         */
+        if (parts.size() >= 4) {
+            QString noAppCrossScopeKey = "QOhSettings.System/" + parts[1] + "/" + parts.mid(3).join("/");
+            if (bool ret = getOrFind(noAppCrossScopeKey)) return result;
+        }
+    }
+    /*
+     * 简化的fallback:如果当前键包含路径分隔符且没有组前缀,直接尝试
+     */
+    if (groupPrefix.isEmpty() && uKey.contains("/")) {
+        QString directKey = qSettingsInit + "/" + uKey;
+        if (bool ret = getOrFind(directKey)) return result;
+    }
+    
+    return false;
+}
+
+QStringList QOhSettingsPrivate::children(const QString &uKey, ChildSpec spec) const
+{
+    /*
+     * uKey 实际上就是 groupPrefix,是完整的组路径
+     * 构建完整的前缀
+     */
+    QString prefix = qSettingsInit;
+    if (!uKey.isEmpty()) {
+        /*
+         * 移除 uKey 末尾的斜杠(如果有的话)
+         */
+        QString cleanKey = uKey;
+        if (cleanKey.endsWith("/")) {
+            cleanKey.chop(1);
+        }
+        prefix += "/" + cleanKey;
+    }
+    /*
+     * 确保前缀以"/"结尾,用于精确匹配
+     */
+    QString searchPrefix = prefix + "/";
+    
+    QStringList result;
+    /*
+     * 扫描全局存储中的所有键
+     */
+    auto keys = globalStorage.keys();
+    for (const auto &key : keys) {
+        /*
+         * 检查键是否以我们的前缀开始,或者完全匹配前缀
+         */
+        bool isMatch = false;
+        QString relativePath;
+        if (key == prefix) {
+            /*
+             * 完全匹配前缀本身,跳过
+             */
+            continue;
+        } else if (key.startsWith(searchPrefix)) {
+            /*
+             * 键以"prefix/"开头
+             */
+            relativePath = key.mid(searchPrefix.length());
+            isMatch = true;
+        }
+        
+        if (!isMatch || relativePath.isEmpty()) {
+            continue;
+        }
+        int slashPos = relativePath.indexOf('/');
+        switch (spec) {
+            /*
+             * 对于AllKeys,添加所有相对路径
+             */
+            case AllKeys: {
+                if (!result.contains(relativePath))
+                    result << relativePath;
+                break;
+            }
+            /*
+             * 直接子键
+             */
+            case ChildKeys: {
+                if(slashPos == -1 && !result.contains(relativePath))
+                    result << relativePath;
+                break;
+            }
+            /*
+             * 子组
+             */
+            case ChildGroups: {
+                QString groupName = relativePath.left(slashPos);
+                if (slashPos != -1 && !result.contains(groupName))
+                    result << groupName;
+                break;
+            }
+        }
+    }
+    
+    // result.sort();
+    /*
+     * 调试信息
+     */
+    // qDebug() << "QOhSettingsPrivate::children - qSettingsInit:" << qSettingsInit << "uKey:" << uKey << "prefix:" << prefix << "searchPrefix:" << searchPrefix << "spec:" << spec;
+    // qDebug() << "QOhSettingsPrivate::children - global storage contents:";
+    // for (auto it = globalStorage.begin(); it != globalStorage.end(); ++it) {
+    //     qDebug() << "  " << it.key() << " = " << it.value();
+    // }
+    // qDebug() << "QOhSettingsPrivate::children - result:" << result;
+
+    return result;
+}
+
+void QOhSettingsPrivate::clear()
+{
+    globalStorage.clear();
+}
+
+void QOhSettingsPrivate::sync()
+{
+    /*
+     * OpenHarmony QSettings实现不需要sync操作
+     */
+}
+
+void QOhSettingsPrivate::flush()
+{
+    /*
+     * OpenHarmony QSettings实现不需要flush操作
+     */
+}
+
+bool QOhSettingsPrivate::isWritable() const
+{
+    return true;
+}
+
+QString QOhSettingsPrivate::fileName() const
+{
+    return qSettingsInit;
+}
+
+QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope,
+                                             const QString &organization, const QString &application)
+{
+    switch (format) {
+    case QSettings::NativeFormat:
+        return new QOhSettingsPrivate(format, scope, organization, application);
+    default:
+        return new QConfFileSettingsPrivate(format, scope, organization, application);
+    }
+}
+
+#ifdef Q_OS_OPENHARMONY
+QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format)
+{
+    switch (format) {
+    case QSettings::NativeFormat:
+        return new QOhSettingsPrivate(fileName);
+    default:
+        return new QConfFileSettingsPrivate(fileName, format);
+    }
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qstandardpaths_openharmony.cpp b/src/corelib/io/qstandardpaths_openharmony.cpp
new file mode 100644
index 00000000000..5c18917ed0c
--- /dev/null
+++ b/src/corelib/io/qstandardpaths_openharmony.cpp
@@ -0,0 +1,144 @@
+#include "qstandardpaths.h"
+
+#ifndef QT_NO_STANDARDPATHS
+
+#include <QtCore/qmap.h>
+#include <QtCore/qopenharmony.h>
+#include <QDir>
+#include <filemanagement/environment/oh_environment.h>
+
+QT_BEGIN_NAMESPACE
+
+typedef QMap<QString, QString> OpenHarmonyDirCache;
+Q_GLOBAL_STATIC(OpenHarmonyDirCache, openHarmonyDirCache)
+
+static QString testDir()
+{
+    return QStandardPaths::isTestModeEnabled() ? QLatin1String("/qttest")
+                                               : QLatin1String("");
+}
+
+/*
+ * Locations where applications can place persistent files it owns.
+ * E.g., /storage/org.app/Music
+ */
+static QString getDir(const char *directoryField = 0)
+{
+    QString &path = (*openHarmonyDirCache)[QString(QLatin1String("APPNAME_%1")).arg(QLatin1String(directoryField))];
+    if (!path.isEmpty())
+        return path;
+
+
+    QString id = QString::fromLatin1(directoryField);
+    QString result;
+    char *path_to_get = nullptr;
+    if (id == "DIRECTORY_DOCUMENTS") {
+        OH_Environment_GetUserDocumentDir(&path_to_get);
+    } else if (id == "DIRECTORY_DOWNLOADS") {
+        OH_Environment_GetUserDownloadDir(&path_to_get);
+    } else if (id == "DIRECTORY_DESKTOP") {
+        OH_Environment_GetUserDesktopDir(&path_to_get);
+    } else {
+        result = QtOh::dir(id);
+    }
+    if (path_to_get != nullptr) {
+        result = QString::fromUtf8(path_to_get);
+        free(path_to_get);
+    }
+
+    path = result;
+    return result;
+}
+
+QString QStandardPaths::writableLocation(StandardLocation type)
+{
+    switch (type) {
+    case QStandardPaths::MusicLocation:
+        return QDir::homePath() + "/Music";
+    case QStandardPaths::MoviesLocation:
+        return QDir::homePath() + "/Videos";
+    case QStandardPaths::PicturesLocation:
+        return QDir::homePath() + "/Images";
+    case QStandardPaths::DocumentsLocation:
+        return getDir("DIRECTORY_DOCUMENTS");
+    case QStandardPaths::DownloadLocation:
+       return getDir("DIRECTORY_DOWNLOADS");
+    case QStandardPaths::GenericConfigLocation:
+    case QStandardPaths::ConfigLocation:
+    case QStandardPaths::AppConfigLocation:
+        return getDir("DIRECTORY_CACHE") + testDir() + QLatin1String("/settings");
+    case QStandardPaths::GenericDataLocation:
+        return getDir("DIRECTORY_CACHE") + testDir();
+    case QStandardPaths::AppDataLocation:
+    case QStandardPaths::AppLocalDataLocation:
+        return getDir("DIRECTORY_FILES") + testDir();
+    case QStandardPaths::RuntimeLocation:
+        return getDir("DIRECTORY_CACHE");
+    case QStandardPaths::TempLocation:
+        return getDir("DIRECTORY_TEMP");
+    case QStandardPaths::GenericCacheLocation:
+    case QStandardPaths::CacheLocation:
+        return getDir("DIRECTORY_CACHE");
+    case QStandardPaths::DesktopLocation:
+        return QDir::homePath() + "/Desktop";
+    case QStandardPaths::HomeLocation:
+       return QDir::homePath();
+    case QStandardPaths::ApplicationsLocation:
+    case QStandardPaths::FontsLocation:
+    default:
+        break;
+    }
+
+    return QString();
+}
+
+QStringList QStandardPaths::standardLocations(StandardLocation type)
+{
+    if (type == MusicLocation) {
+        return QStringList() << writableLocation(type);
+    }
+
+    if (type == MoviesLocation) {
+        return QStringList() << writableLocation(type);
+    }
+
+    if (type == PicturesLocation) {
+        return QStringList()  << writableLocation(type);
+    }
+
+    if (type == DocumentsLocation) {
+        return QStringList() << writableLocation(type);
+    }
+
+    if (type == DownloadLocation) {
+        return QStringList() << writableLocation(type);
+    }
+
+    if (type == AppDataLocation || type == AppLocalDataLocation) {
+        return QStringList() << writableLocation(type);
+    }
+
+    if (type == CacheLocation) {
+        return QStringList() << writableLocation(type);
+    }
+
+    if (type == FontsLocation) {
+        QString &fontLocation = (*openHarmonyDirCache)[QStringLiteral("FONT_LOCATION")];
+        if (!fontLocation.isEmpty())
+            return QStringList(fontLocation);
+
+        const QByteArray ba = qgetenv("QT_OpenHarmony_FONT_LOCATION");
+        if (!ba.isEmpty())
+            return QStringList((fontLocation = QDir::cleanPath(QString::fromLocal8Bit(ba))));
+
+        // Don't cache the fallback, as we might just have been called before
+        // QT_OpenHarmony_FONT_LOCATION has been set.
+        return QStringList(QLatin1String("/system/fonts"));
+    }
+
+    return QStringList(writableLocation(type));
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STANDARDPATHS
diff --git a/src/corelib/io/qtemporaryfile_p.h b/src/corelib/io/qtemporaryfile_p.h
index 3a2ed73cf96..0c2a7d8c2bd 100644
--- a/src/corelib/io/qtemporaryfile_p.h
+++ b/src/corelib/io/qtemporaryfile_p.h
@@ -22,7 +22,7 @@
 #include "private/qfile_p.h"
 #include "qtemporaryfile.h"
 
-#if defined(Q_OS_LINUX) && QT_CONFIG(linkat)
+#if defined(Q_OS_LINUX) && QT_CONFIG(linkat) && !defined(Q_OS_OPENHARMONY)
 #  include <fcntl.h>
 #  ifdef O_TMPFILE
 // some early libc support had the wrong values for O_TMPFILE
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 73df3ccc8df..7c9aa23e2a3 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -4,6 +4,10 @@
 
 #include "qcoreapplication.h"
 #include "qcoreapplication_p.h"
+#ifdef Q_OS_OPENHARMONY
+// QtWatchdog
+#include "qohoswatchdog.h"
+#endif
 
 #ifndef QT_NO_QOBJECT
 #include "qabstracteventdispatcher.h"
@@ -1388,6 +1392,11 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int m
     }
 }
 
+#ifdef Q_OS_OPENHARMONY
+// TODO QtWatchdog
+std::shared_ptr<QtOhosWatchdog::QOhosWatchdog> qohoswatchdog_;
+#endif
+
 /*****************************************************************************
   Main event loop wrappers
  *****************************************************************************/
@@ -1432,6 +1441,13 @@ int QCoreApplication::exec()
         qWarning("QCoreApplication::exec: The event loop is already running");
         return -1;
     }
+#ifdef Q_OS_OPENHARMONY
+    // QtWatchdog
+    qWarning("QCoreApplication: exec start.");
+    qohoswatchdog_ = std::make_shared<QtOhosWatchdog::QOhosWatchdog>();
+    qohoswatchdog_->Init();
+    qWarning("QCoreApplication: exec end.");
+#endif
 
     threadData->quitNow = false;
     QEventLoop eventLoop;
@@ -2024,9 +2040,29 @@ void QCoreApplicationPrivate::removePostedEvent(QEvent * event)
 bool QCoreApplication::event(QEvent *e)
 {
     if (e->type() == QEvent::Quit) {
+#ifdef Q_OS_OPENHARMONY
+        // QtWatchdog
+        if (qohoswatchdog_ != nullptr) {
+            qohoswatchdog_->Stop();
+            qohoswatchdog_ = nullptr;
+        }
+#endif
         exit(0);
         return true;
     }
+#ifdef Q_OS_OPENHARMONY
+    // QtWatchdog
+    if (e->type() == QEvent::CheckMainThreadIsAlive) {
+        qWarning("QCoreApplication: receive check main thread event start.");
+        if (qohoswatchdog_ == nullptr) {
+            qWarning("QCoreApplication: Qt Watch dog is nullptr.");
+        } else {
+            qohoswatchdog_->SetAppMainThreadState(true);
+            qohoswatchdog_->AllowReportEvent();
+        }
+        return true;
+    }
+#endif
     return QObject::event(e);
 }
 
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index f1f3e926e54..f09b75f8a97 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -287,6 +287,9 @@ public:
         // 512 reserved for Qt Jambi's MetaCall event
         // 513 reserved for Qt Jambi's DeleteOnMainThread event
 
+        // QtWatchdog
+        CheckMainThreadIsAlive = 601,           // oh watch dog
+
         User = 1000,                            // first user event id
         MaxUser = 65535                         // last user event id
     };
diff --git a/src/corelib/kernel/qjsmodule.cpp b/src/corelib/kernel/qjsmodule.cpp
new file mode 100644
index 00000000000..636b915a4ba
--- /dev/null
+++ b/src/corelib/kernel/qjsmodule.cpp
@@ -0,0 +1,45 @@
+#include <QHash>
+#include <QByteArray>
+#include <QReadWriteLock>
+
+#include "qjsmodule.h"
+#include "qopenharmonydefines.h"
+
+QT_BEGIN_NAMESPACE
+inline static QReadWriteLock g_locker;
+inline static QHash<QString, Napi::Object> g_modules{};
+QJsModule::QJsModule(const QString &module)
+{
+    auto creator = [this, module]{
+        {
+            QReadLocker locker(&g_locker);
+            if (g_modules.contains(module)) {
+                setObject(g_modules.value(module));
+                return;
+            }
+        }
+
+        napi_value result;
+        const QByteArray data = module.toLatin1();
+        QString path = QtOh::bundleName() + "/" + QtOh::moduleName();
+        QByteArray pathByteArray = path.toUtf8();
+        Napi::Env env = QtOh::uiEnv();
+
+        napi_status status = napi_load_module_with_info(env,
+                                                        data.constData(), pathByteArray.constData(), &result);
+        if (status == napi_ok && result != nullptr) {
+            Napi::Object obj(env, result);
+            setObject(obj);
+            {
+                QWriteLocker locke(&g_locker);
+                g_modules.insert(module, obj);
+            }
+        }
+        LOGI("load js module: [%{public}s], napi_status: [%{public}d], result: [%{public}p, [%{public}s]]",
+             module.toLocal8Bit().data(), status, result, path.toLocal8Bit().data());
+    };
+
+    QtOh::runOnJsUIThreadAndWait(creator);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qjsmodule.h b/src/corelib/kernel/qjsmodule.h
new file mode 100644
index 00000000000..3e5c1081090
--- /dev/null
+++ b/src/corelib/kernel/qjsmodule.h
@@ -0,0 +1,16 @@
+#ifndef QJSMODULE_H
+#define QJSMODULE_H
+
+#include <QString>
+#include <qjsobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QJsModule : public QJsObject
+{
+public:
+    QJsModule(const QString &module);
+};
+
+QT_END_NAMESPACE
+#endif // QJSMODULE_H
diff --git a/src/corelib/kernel/qjsobject.cpp b/src/corelib/kernel/qjsobject.cpp
new file mode 100644
index 00000000000..d90e8ba8b9f
--- /dev/null
+++ b/src/corelib/kernel/qjsobject.cpp
@@ -0,0 +1,169 @@
+#include <QDebug>
+#include <QMapIterator>
+
+#include "qjsobject.h"
+#include "qjsobject_p.h"
+#include "qopenharmony_p.h"
+#include "qopenharmonydefines.h"
+
+QT_BEGIN_NAMESPACE
+
+QJsObjectPrivate::QJsObjectPrivate(QJsObject * const qq)
+    : q_ptr(qq)
+{
+}
+
+QJsObjectPrivate::QJsObjectPrivate(QJsObject * const qq, Napi::Object jsObject)
+    : QJsObjectPrivate(qq)
+{
+    setObjectImpl(jsObject);
+}
+
+QJsObjectPrivate::QJsObjectPrivate(QJsObject * const qq, Napi::Value constructor, const std::initializer_list<napi_value>& args)
+    : QJsObjectPrivate(qq)
+{
+    setConstructor(constructor, args);
+}
+
+QJsObjectPrivate::~QJsObjectPrivate()
+{
+
+}
+
+bool QJsObjectPrivate::isCallFromUiThread() const
+{
+    return QtOh::uiThreadId() == std::this_thread::get_id();
+}
+
+void QJsObjectPrivate::setObjectImpl(Napi::Object jsObject)
+{
+    m_ref = Napi::Persistent(jsObject);
+}
+
+void QJsObjectPrivate::setConstructor(Napi::Value constructor, const std::initializer_list<napi_value>& args)
+{
+    napi_value instance;
+    napi_env env = constructor.Env();
+    napi_status status = napi_new_instance(env, constructor, args.size(), args.begin(), &instance);
+    if (status == napi_ok) {
+        setObjectImpl(Napi::Object(env, instance));
+    }
+}
+
+QJsObject::QJsObject(Napi::Value constructor, const std::initializer_list<napi_value> &args)
+    : QJsObject(*(new QJsObjectPrivate(this, constructor, args)))
+{
+}
+
+QJsObject::QJsObject(Napi::Object jsObject)
+    : QJsObject(*(new QJsObjectPrivate(this, jsObject)))
+{
+}
+
+QJsObject::~QJsObject()
+{
+    Q_D(QJsObject);
+    QtOh::runOnJsUIThreadAndWait([d]{
+        d->m_ref.SuppressDestruct();
+        d->m_ref.Reset();
+    });
+}
+
+Napi::Env QJsObject::env() const
+{
+    Q_D(const QJsObject);
+    return d->m_ref.Env();
+}
+
+Napi::Object QJsObject::object() const
+{
+    Q_D(const QJsObject);
+    return d->m_ref.Value();
+}
+
+QJsObject::operator Napi::Object() const
+{
+    return object();
+}
+
+void QJsObject::setObject(Napi::Object object)
+{
+    Q_D(QJsObject);
+    d->setObjectImpl(object);
+}
+
+Napi::Value QJsObject::get(const QString &key) const
+{
+    clearError();
+    return object().Get(key.toStdString());
+}
+
+bool QJsObject::hasError() const
+{
+    return env().IsExceptionPending();
+}
+
+void QJsObject::clearError() const
+{
+    Q_D(const QJsObject);
+    if (hasError()) {
+        d->m_errorString.clear();
+        Napi::Error e = env().GetAndClearPendingException();
+        if (!e.IsEmpty())
+            d->m_errorString = QString::fromStdString(e.Message());
+    }
+}
+
+QString QJsObject::lastError() const
+{
+    Q_D(const QJsObject);
+    return d->m_errorString;
+}
+
+bool QJsObject::shouldExecInUIJsThread() const
+{
+    Q_D(const QJsObject);
+    return !d->isCallFromUiThread();
+}
+
+Napi::Value QJsObject::callImpl(const QString &function, const std::initializer_list<napi_value>& args) const
+{
+    clearError();
+    Napi::Value functionValue = object().Get(function.toStdString());
+    if (!functionValue.IsFunction()) {
+        LOGW("Method '%{public}s' not found or not a function", qPrintable(function));
+        if (hasError()) {
+            clearError();
+            LOGE("js func error:%{public}s", qPrintable(lastError()));
+        }
+        return env().Null();
+    }
+
+    Napi::Function func = functionValue.As<Napi::Function>();
+    if (func.IsNull())
+        return env().Null();
+
+    Napi::Value result = func.Call(object(), args);
+    if (hasError()) {
+        clearError();
+        LOGE("call %{public}s has error: %{public}s", qPrintable(function), qPrintable(lastError()));
+    }
+    return result;
+}
+
+QJsObject::QJsObject(QJsObjectPrivate &dd, Napi::Value constructor)
+    : d_ptr(&dd)
+{
+}
+
+QJsObject::QJsObject(QJsObjectPrivate &dd, Napi::Object jsObject)
+    : d_ptr(&dd)
+{
+}
+
+QJsSubEvent::QJsSubEvent(const QString &type, QJsObject::QNapiCallBack callback, napi_env env)
+    : type(type.toStdString()), callback(Napi::Function::New(env, callback))
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qjsobject.h b/src/corelib/kernel/qjsobject.h
new file mode 100644
index 00000000000..2a139730272
--- /dev/null
+++ b/src/corelib/kernel/qjsobject.h
@@ -0,0 +1,91 @@
+#ifndef QJSOBJECT_H
+#define QJSOBJECT_H
+
+#include <QString>
+#include <functional>
+#include <QVariantMap>
+#include <qopenharmony.h>
+#include <qnapi.h>
+
+QT_BEGIN_NAMESPACE
+
+class QJsObjectPrivate;
+class Q_CORE_EXPORT QJsObject
+{
+    Q_DECLARE_PRIVATE(QJsObject)
+    Q_DISABLE_COPY_MOVE(QJsObject)
+
+public:
+    using QNapiCallBack = std::function<void(const Napi::CallbackInfo &)>;
+    explicit QJsObject(Napi::Value constructor, const std::initializer_list<napi_value>& args = std::initializer_list<napi_value>());
+    explicit QJsObject(Napi::Object jsObject = Napi::Object());
+    virtual ~QJsObject();
+
+    Napi::Env env() const;
+    Napi::Object object() const;
+    operator Napi::Object() const;
+    void setObject(Napi::Object object);
+
+    Napi::Value get(const QString &key) const;
+    template <typename RET>
+    typename std::enable_if<std::is_default_constructible<RET>::value, RET>::type
+    get(const QString &key) const;
+
+    bool hasError() const;
+    void clearError() const;
+    QString lastError() const;
+    bool shouldExecInUIJsThread() const;
+
+    template <typename ValueType>
+    void set(const QString &key, const ValueType &value);
+
+    template<typename RET = Napi::Value, typename... Args>
+    inline typename std::enable_if<(sizeof...(Args) > 0), RET>::type
+    call(const QString &function, Args&&... args) const {
+        auto result = callImpl(function, { QNapi::create(std::forward<Args>(args))... });
+        return QNapi::get<RET>(result);
+    }
+    template<typename RET = Napi::Value>
+    inline RET call(const QString &function, const std::initializer_list<napi_value>& args = {}) const {
+        auto result = callImpl(function, args);
+        return QNapi::get<RET>(result);
+    }
+protected:
+    Napi::Value callImpl(const QString &function, const std::initializer_list<napi_value>& args) const;
+    QScopedPointer<QJsObjectPrivate> d_ptr;
+    explicit QJsObject(QJsObjectPrivate &dd, Napi::Value constructor);
+    explicit QJsObject(QJsObjectPrivate &dd, Napi::Object jsObject = Napi::Object());
+};
+
+template<typename RET>
+typename std::enable_if<std::is_default_constructible<RET>::value, RET>::type
+QJsObject::get(const QString &key) const
+{
+    RET result{};
+    QtOh::runOnJsUIThreadAndWait([this, key, &result]{
+        clearError();
+        result = QNapi::get<RET>(object(), key);
+    });
+    return result;
+}
+
+template<typename ValueType>
+inline void QJsObject::set(const QString &key, const ValueType &value)
+{
+    QtOh::runOnJsUIThreadAndWait([this, key, &value]{
+        clearError();
+        object().Set(key.toStdString(), QNapi::create(value));
+    });
+}
+
+class Q_CORE_EXPORT QJsSubEvent
+{
+public:
+    QJsSubEvent(const QString &type, QJsObject::QNapiCallBack callback, napi_env env);
+    const std::string type;
+    const Napi::Function callback;
+};
+
+QT_END_NAMESPACE
+#endif // QJSOBJECT_H
+
diff --git a/src/corelib/kernel/qjsobject_p.h b/src/corelib/kernel/qjsobject_p.h
new file mode 100644
index 00000000000..efdee8c10b4
--- /dev/null
+++ b/src/corelib/kernel/qjsobject_p.h
@@ -0,0 +1,35 @@
+#ifndef QJSOBJECT_P_H
+#define QJSOBJECT_P_H
+
+#include <QString>
+#include <qglobal.h>
+#include <qopenharmony.h>
+
+QT_BEGIN_NAMESPACE
+class QJsObject;
+
+class Q_CORE_EXPORT QJsObjectPrivate
+{
+    Q_DECLARE_PUBLIC(QJsObject)
+    Q_DISABLE_COPY_MOVE(QJsObjectPrivate)
+
+public:
+    explicit QJsObjectPrivate(QJsObject *const qq);
+    explicit QJsObjectPrivate(QJsObject *const qq, Napi::Object jsObject);
+    explicit QJsObjectPrivate(QJsObject *const qq, Napi::Value constructor, const std::initializer_list<napi_value> &args);
+    virtual ~QJsObjectPrivate();
+
+protected:
+    QJsObject *const q_ptr;
+    Napi::ObjectReference m_ref;
+    mutable QString m_errorString;
+
+private:
+    bool isCallFromUiThread() const;
+    void setObjectImpl(Napi::Object jsObject);
+    void setConstructor(Napi::Value constructor, const std::initializer_list<napi_value> &args);
+};
+
+QT_END_NAMESPACE
+
+#endif //QJSOBJECT_P_H
diff --git a/src/corelib/kernel/qjspromise.cpp b/src/corelib/kernel/qjspromise.cpp
new file mode 100644
index 00000000000..2b11cc28b6e
--- /dev/null
+++ b/src/corelib/kernel/qjspromise.cpp
@@ -0,0 +1,53 @@
+#include "qjspromise_p.h"
+#include "qjsobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QJsPromisePrivate : public QJsObjectPrivate
+{
+    Q_DECLARE_PUBLIC(QJsPromise)
+public:
+    QJsPromisePrivate(QJsObject *const qq, const Napi::Promise &promise);
+    Napi::Function createCallback(std::function<void(const Napi::CallbackInfo&)>& callback,
+                                              const char* name);
+};
+
+QJsPromise::QJsPromise(const Napi::Promise &promise)
+    : QJsObject(*new QJsPromisePrivate(this, promise))
+{
+}
+
+QJsPromise &QJsPromise::onThen(std::function<void(const Napi::CallbackInfo&)> callback)
+{
+    Q_D(QJsPromise);
+    call("then", {d->createCallback(callback, "resolvedResult")});
+    return *this;
+}
+
+QJsPromise& QJsPromise::onCatch(std::function<void(const Napi::CallbackInfo&)> callback)
+{
+    Q_D(QJsPromise);
+    call("catch", {d->createCallback(callback, "catchResult")});
+    return *this;
+}
+
+QJsPromisePrivate::QJsPromisePrivate(QJsObject *const qq, const Napi::Promise &promise)
+    : QJsObjectPrivate(qq, promise)
+{
+
+}
+
+Napi::Function QJsPromisePrivate::createCallback(std::function<void (const Napi::CallbackInfo &)> &callback, const char *name) {
+    Q_Q(QJsPromise);
+    return Napi::Function::New(
+                q->env(),
+                [cb = std::move(callback)](const Napi::CallbackInfo& info) {
+        if (cb) {
+            cb(info);
+        }
+    }, name);
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/corelib/kernel/qjspromise_p.h b/src/corelib/kernel/qjspromise_p.h
new file mode 100644
index 00000000000..d9ede7a195a
--- /dev/null
+++ b/src/corelib/kernel/qjspromise_p.h
@@ -0,0 +1,22 @@
+#ifndef QJSPROMISE_P_H
+#define QJSPROMISE_P_H
+
+#include <QJsObject>
+
+QT_BEGIN_NAMESPACE
+class QJsPromisePrivate;
+
+class Q_CORE_EXPORT QJsPromise : public QJsObject
+{
+    Q_DECLARE_PRIVATE(QJsPromise)
+public:
+    QJsPromise(const Napi::Promise& promise);
+
+    QJsPromise &onThen(std::function<void(const Napi::CallbackInfo&)> callback);
+
+    QJsPromise& onCatch(std::function<void(const Napi::CallbackInfo&)> callback);
+};
+
+QT_END_NAMESPACE
+
+#endif //QJSPROMISE_P_H
diff --git a/src/corelib/kernel/qnapi.h b/src/corelib/kernel/qnapi.h
new file mode 100644
index 00000000000..ea94180b43f
--- /dev/null
+++ b/src/corelib/kernel/qnapi.h
@@ -0,0 +1,841 @@
+#ifndef QNAPI_H
+#define QNAPI_H
+#include <qopenharmony.h>
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include <QtCore/QVariantMap>
+#include <QtCore/QStringList>
+#include <QtCore/QVariantList>
+
+QT_BEGIN_NAMESPACE
+
+namespace QNapi {
+
+inline Napi::Value variant2Value(const QVariant& variant);
+
+inline Napi::Object createObject()
+{
+    return Napi::Object::New(QtOh::uiEnv());
+}
+
+//#if __cplusplus >= 201703L
+//template<typename T>
+//inline std::enable_if_t<std::is_enum_v<std::decay_t<T>>, Napi::Value>
+//create(T value)
+//{
+//    return Napi::Value::From(QtOh::uiEnv(), static_cast<std::underlying_type_t<T>>(value));
+//}
+
+//template<typename T>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<T>, QString>, Napi::Value>
+//create(T&& value)
+//{
+//    return Napi::String::New(QtOh::uiEnv(), value.toStdString());
+//}
+
+//template<typename T>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<T>, QStringList>, Napi::Value>
+//create(T&& value)
+//{
+//    auto env = QtOh::uiEnv();
+//    auto jsArray = Napi::Array::New(env, value.size());
+
+//    for (int i = 0; i < value.size(); ++i) {
+//        jsArray.Set(i, create(value[i]));
+//    }
+
+//    return jsArray;
+//}
+
+//template<typename T>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<T>, QVariantList>, Napi::Value>
+//create(T&& value)
+//{
+//    auto env = QtOh::uiEnv();
+//    auto jsArray = Napi::Array::New(env, value.size());
+
+//    for (int i = 0; i < value.size(); ++i) {
+//        jsArray.Set(i, variant2Value(value[i]));
+//    }
+
+//    return jsArray;
+//}
+
+//template<typename T>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<T>, Napi::Function>, Napi::Function>
+//create(T&& value)
+//{
+//    return std::forward<T>(value);
+//}
+
+//template<typename Callable>
+//inline std::enable_if_t<std::is_invocable_v<Callable, const Napi::CallbackInfo&>, Napi::Function>
+//create(Callable&& cb, const char* utf8name = nullptr, void* data = nullptr)
+//{
+//    return Napi::Function::New(QtOh::uiEnv(), std::forward<Callable>(cb), utf8name, data);
+//}
+
+//template<typename Callable>
+//inline std::enable_if_t<std::is_invocable_v<Callable, const Napi::CallbackInfo&>, Napi::Function>
+//create(Callable&& cb, const QString& utf8name, void* data = nullptr)
+//{
+//    return Napi::Function::New(QtOh::uiEnv(), std::forward<Callable>(cb), utf8name.toUtf8().constData(), data);
+//}
+
+//template<typename T>
+//inline std::enable_if_t<!std::is_enum_v<std::decay_t<T>> &&
+//                                !std::is_same_v<std::decay_t<T>, QString> &&
+//                                !std::is_same_v<std::decay_t<T>, QStringList> &&
+//                                !std::is_same_v<std::decay_t<T>, QVariantMap> &&
+//                                !std::is_same_v<std::decay_t<T>, QVariantList> &&
+//                                !std::is_same_v<std::decay_t<T>, Napi::Function> &&
+//                                !std::is_invocable_v<T, const Napi::CallbackInfo&>, Napi::Value>
+//create(T&& value) {
+//    return Napi::Value::From(QtOh::uiEnv(), std::forward<T>(value));
+//}
+
+//template<typename T>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<T>, QVariantMap>, Napi::Value>
+//create(T&& value) {
+//    auto env = QtOh::uiEnv();
+//    auto obj = Napi::Object::New(env);
+
+//    for (auto it = value.constBegin(); it != value.constEnd(); ++it) {
+//        std::string key = it.key().toStdString();
+//        obj.Set(key, variant2Value(it.value()));
+//    }
+//    return obj;
+//}
+
+//inline Napi::Value variant2Value(const QVariant& variant) {
+//    if (variant.isNull() || !variant.isValid()) {
+//        return Napi::Env(QtOh::uiEnv()).Null();
+//    }
+
+//    switch (variant.type()) {
+//    case QVariant::String:
+//        return create(variant.toString());
+//    case QVariant::Int:
+//        return create(variant.toInt());
+//    case QVariant::Double:
+//        return create(variant.toDouble());
+//    case QVariant::Bool:
+//        return create(variant.toBool());
+//    case QVariant::Map:
+//        return create(variant.toMap());
+//    case QVariant::List:
+//        return create(variant.toList());
+//    case QVariant::StringList:
+//        return create(variant.toStringList());
+//    default:
+//        if (variant.canConvert<int>()) {
+//            return create(variant.toInt());
+//        }
+//        return create(variant.toString());
+//    }
+//}
+
+//inline QVariant value2Variant(const Napi::Value& value);
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_integral_v<std::decay_t<RET>> &&
+//                                !std::is_same_v<std::decay_t<RET>, bool>, RET>
+//get(const Napi::Value& value)
+//{
+//    if (!value.IsNumber()) {
+//        return RET{};
+//    }
+//    return static_cast<RET>(value.As<Napi::Number>().Int32Value());
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_enum_v<std::decay_t<RET>>, RET>
+//get(const Napi::Value& value)
+//{
+//    using DecayRET = std::decay_t<RET>;
+//    using UnderlyingType = std::underlying_type_t<DecayRET>;
+//    UnderlyingType underlying = get<UnderlyingType>(value);
+//    return static_cast<DecayRET>(underlying);
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<RET>, QString>, RET>
+//get(const Napi::Value& value)
+//{
+//    if (!value.IsString()) {
+//        return QString();
+//    }
+//    std::string str = value.As<Napi::String>();
+//    return QString::fromStdString(str);
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<RET>, QByteArray>, RET>
+//get(const Napi::Value& value)
+//{
+//    if (!value.IsString()) {
+//        return QByteArray();
+//    }
+//    std::string str = value.As<Napi::String>();
+//    return QByteArray::fromStdString(str);
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<RET>, QVariantMap>, RET>
+//get(const Napi::Value& value)
+//{
+//    QVariantMap result;
+//    if (!value.IsObject()) {
+//        return result;
+//    }
+
+//    Napi::Object obj = value.As<Napi::Object>();
+//    auto propertyNames = obj.GetPropertyNames();
+//    uint32_t length = propertyNames.Length();
+
+//    for (uint32_t i = 0; i < length; ++i) {
+//        Napi::Value key = propertyNames.Get(i);
+//        Napi::Value val = obj.Get(key);
+
+//        if (key.IsString()) {
+//            QString qKey = QString::fromStdString(key.As<Napi::String>());
+//            QVariant qValue = value2Variant(val);
+//            result.insert(qKey, qValue);
+//        }
+//    }
+//    return result;
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<RET>, QVariantList>, RET>
+//get(const Napi::Value& value)
+//{
+//    QVariantList result;
+//    if (!value.IsArray()) {
+//        return result;
+//    }
+
+//    Napi::Array array = value.As<Napi::Array>();
+//    uint32_t length = array.Length();
+
+//    for (uint32_t i = 0; i < length; ++i) {
+//        Napi::Value element = array.Get(i);
+//        result.append(value2Variant(element));
+//    }
+//    return result;
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<RET>, QStringList>, RET>
+//get(const Napi::Value& value)
+//{
+//    QStringList result;
+//    if (!value.IsArray()) {
+//        return result;
+//    }
+
+//    Napi::Array array = value.As<Napi::Array>();
+//    uint32_t length = array.Length();
+
+//    for (uint32_t i = 0; i < length; ++i) {
+//        Napi::Value element = array.Get(i);
+//        result << get<QString>(element);
+//    }
+//    return result;
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<RET>, QVariant>, RET>
+//get(const Napi::Value& value)
+//{
+//    return value2Variant(value);
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<RET>, bool>, RET>
+//get(const Napi::Value& value)
+//{
+//    if (!value.IsBoolean()) {
+//        return false;
+//    }
+//    return value.As<Napi::Boolean>();
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_floating_point_v<std::decay_t<RET>>, RET>
+//get(const Napi::Value& value)
+//{
+//    if (!value.IsNumber()) {
+//        return RET{};
+//    }
+//    return static_cast<RET>(value.As<Napi::Number>().DoubleValue());
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_same_v<std::decay_t<RET>, std::string>, RET>
+//get(const Napi::Value& value)
+//{
+//    if (!value.IsString()) {
+//        return std::string{};
+//    }
+//    return value.As<Napi::String>();
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<!std::is_enum_v<std::decay_t<RET>> &&
+//                                !std::is_same_v<std::decay_t<RET>, QString> &&
+//                                !std::is_same_v<std::decay_t<RET>, QByteArray> &&
+//                                !std::is_same_v<std::decay_t<RET>, QVariantMap> &&
+//                                !std::is_same_v<std::decay_t<RET>, QVariantList> &&
+//                                !std::is_same_v<std::decay_t<RET>, QStringList> &&
+//                                !std::is_same_v<std::decay_t<RET>, QVariant> &&
+//                                !std::is_same_v<std::decay_t<RET>, bool> &&
+//                                !std::is_integral_v<std::decay_t<RET>> &&
+//                                !std::is_floating_point_v<std::decay_t<RET>> &&
+//                                !std::is_same_v<std::decay_t<RET>, std::string>, RET>
+//get(const Napi::Value& value)
+//{
+//    return value.As<RET>();
+//}
+
+//inline QVariant value2Variant(const Napi::Value& value)
+//{
+//    if (value.IsNull() || value.IsUndefined()) {
+//        return QVariant();
+//    } else if (value.IsBoolean()) {
+//        return QVariant(get<bool>(value));
+//    } else if (value.IsNumber()) {
+//        double num = value.As<Napi::Number>().DoubleValue();
+//        if (std::floor(num) == num && num >= std::numeric_limits<int>::min() && num <= std::numeric_limits<int>::max()) {
+//            return QVariant(get<int>(value));
+//        } else {
+//            return QVariant(get<double>(value));
+//        }
+//    } else if (value.IsString()) {
+//        return QVariant(get<QString>(value));
+//    } else if (value.IsArray()) {
+//        return QVariant(get<QVariantList>(value));
+//    } else if (value.IsObject()) {
+//        return QVariant(get<QVariantMap>(value));
+//    }
+//    return QVariant(get<QString>(value.ToString()));
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_default_constructible_v<RET>, RET>
+//get(const Napi::Object& object, const char *property)
+//{
+//    if (!object.Has(property)) {
+//        return RET{};
+//    }
+//    Napi::Value value = object.Get(property);
+//    return get<RET>(value);
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_default_constructible_v<RET>, RET>
+//get(const Napi::Object& object, const QString& property)
+//{
+//    return get<RET>(object, property.toUtf8().constData());
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_default_constructible_v<RET>, RET>
+//get(const Napi::Value& value, const char *property)
+//{
+//    if (!value.IsObject()) {
+//        return RET{};
+//    }
+
+//    Napi::Object object = value.As<Napi::Object>();
+//    return get<RET>(object, property);
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_default_constructible_v<RET>, RET>
+//get(const Napi::Value& value, const QString& property)
+//{
+//    return get<RET>(value, property.toUtf8().constData());
+//}
+
+//template<typename RET>
+//inline RET getOrDefault(const Napi::Object& object, const char *property, const RET& defaultValue)
+//{
+//    if (!object.Has(property)) {
+//        return defaultValue;
+//    }
+
+//    Napi::Value propertyValue = object.Get(property);
+//    return get<RET>(propertyValue);
+//}
+
+//template<typename RET>
+//inline RET getOrDefault(const Napi::Value& value, const char *property, const RET& defaultValue)
+//{
+//    if (!value.IsObject()) {
+//        return defaultValue;
+//    }
+
+//    Napi::Object object = value.As<Napi::Object>();
+//    if (!object.Has(property)) {
+//        return defaultValue;
+//    }
+
+//    Napi::Value propertyValue = object.Get(property);
+//    return get<RET>(propertyValue);
+//}
+
+//template<typename T>
+//inline void set(Napi::Object& object, const char *property, T&& value)
+//{
+//    object.Set(property, create(std::forward<T>(value)));
+//}
+
+//template<typename T>
+//inline void set(Napi::Object& object, const QString &property, T&& value)
+//{
+//    object.Set(property.toStdString(), create(std::forward<T>(value)));
+//}
+
+//template<typename RET>
+//inline std::enable_if_t<std::is_default_constructible_v<RET>, RET>
+//getFirst(const Napi::CallbackInfo &info)
+//{
+//    if (info.Length() < 1)
+//        return RET{};
+//    return get<RET>(info[0]);
+//}
+//#else
+template<typename T>
+inline typename std::enable_if<std::is_enum<typename std::decay<T>::type>::value, Napi::Value>::type
+create(T value)
+{
+    return Napi::Value::From(QtOh::uiEnv(), static_cast<typename std::underlying_type<typename std::decay<T>::type>::type>(value));
+}
+
+template<typename T>
+inline typename std::enable_if<std::is_same<typename std::decay<T>::type, QString>::value, Napi::Value>::type
+create(T&& value)
+{
+    return Napi::String::New(QtOh::uiEnv(), value.toStdString());
+}
+
+template<typename T>
+inline typename std::enable_if<std::is_same<typename std::decay<T>::type, QStringList>::value, Napi::Value>::type
+create(T&& value)
+{
+    auto env = QtOh::uiEnv();
+    auto jsArray = Napi::Array::New(env, value.size());
+
+    for (int i = 0; i < value.size(); ++i) {
+        jsArray.Set(i, create(value[i]));
+    }
+
+    return jsArray;
+}
+
+template<typename T>
+inline typename std::enable_if<std::is_same<typename std::decay<T>::type, QVariantList>::value, Napi::Value>::type
+create(T&& value)
+{
+    auto env = QtOh::uiEnv();
+    auto jsArray = Napi::Array::New(env, value.size());
+
+    for (int i = 0; i < value.size(); ++i) {
+        jsArray.Set(i, variant2Value(value[i]));
+    }
+
+    return jsArray;
+}
+
+template<typename T>
+inline typename std::enable_if<std::is_same<typename std::decay<T>::type, Napi::Function>::value, Napi::Function>::type
+create(T&& value)
+{
+    return std::forward<T>(value);
+}
+
+template<typename T, typename = void>
+struct is_invocable : std::false_type {};
+
+template<typename T>
+struct is_invocable<T, typename std::enable_if<
+                               std::is_convertible<
+                                       decltype(std::declval<T>()(std::declval<const Napi::CallbackInfo&>())),
+                                       Napi::Value
+                                       >::value ||
+                               std::is_same<
+                                       decltype(std::declval<T>()(std::declval<const Napi::CallbackInfo&>())),
+                                       void
+                                       >::value
+                               >::type> : std::true_type {};
+
+template<>
+struct is_invocable<Napi::Value(*)(const Napi::CallbackInfo&)> : std::true_type {};
+
+template<>
+struct is_invocable<void(*)(const Napi::CallbackInfo&)> : std::true_type {};
+
+template<typename Callable>
+inline typename std::enable_if<
+        is_invocable<typename std::decay<Callable>::type>::value &&
+                !std::is_same<typename std::decay<Callable>::type, Napi::Function>::value,
+        Napi::Function
+        >::type
+create(Callable&& cb)
+{
+    return Napi::Function::New(QtOh::uiEnv(), std::forward<Callable>(cb));
+}
+
+template<typename Callable>
+inline typename std::enable_if<
+        is_invocable<typename std::decay<Callable>::type>::value &&
+                !std::is_same<typename std::decay<Callable>::type, Napi::Function>::value,
+        Napi::Function
+        >::type
+create(Callable&& cb, const char* utf8name, void* data)
+{
+    return Napi::Function::New(QtOh::uiEnv(), std::forward<Callable>(cb), utf8name, data);
+}
+
+template<typename Callable>
+inline typename std::enable_if<
+        is_invocable<typename std::decay<Callable>::type>::value &&
+                !std::is_same<typename std::decay<Callable>::type, Napi::Function>::value,
+        Napi::Function
+        >::type
+create(Callable&& cb, const QString& utf8name, void* data)
+{
+    return Napi::Function::New(QtOh::uiEnv(), std::forward<Callable>(cb), utf8name.toUtf8().constData(), data);
+}
+
+template<typename T>
+inline typename std::enable_if<!std::is_enum<typename std::decay<T>::type>::value &&
+                                       !std::is_same<typename std::decay<T>::type, QString>::value &&
+                                       !std::is_same<typename std::decay<T>::type, QStringList>::value &&
+                                       !std::is_same<typename std::decay<T>::type, QVariantMap>::value &&
+                                       !std::is_same<typename std::decay<T>::type, QVariantList>::value &&
+                                       !std::is_same<typename std::decay<T>::type, Napi::Function>::value &&
+                                       !is_invocable<T>::value, Napi::Value>::type
+create(T&& value) {
+    return Napi::Value::From(QtOh::uiEnv(), std::forward<T>(value));
+}
+
+template<typename T>
+inline typename std::enable_if<std::is_same<typename std::decay<T>::type, QVariantMap>::value, Napi::Value>::type
+create(T&& value) {
+    auto env = QtOh::uiEnv();
+    auto obj = Napi::Object::New(env);
+
+    for (auto it = value.constBegin(); it != value.constEnd(); ++it) {
+        std::string key = it.key().toStdString();
+        obj.Set(key, variant2Value(it.value()));
+    }
+    return obj;
+}
+
+inline Napi::Value variant2Value(const QVariant& variant) {
+    if (variant.isNull() || !variant.isValid()) {
+        return Napi::Env(QtOh::uiEnv()).Null();
+    }
+
+    switch (variant.type()) {
+    case QVariant::String:
+        return create(variant.toString());
+    case QVariant::Int:
+        return create(variant.toInt());
+    case QVariant::Double:
+        return create(variant.toDouble());
+    case QVariant::Bool:
+        return create(variant.toBool());
+    case QVariant::Map:
+        return create(variant.toMap());
+    case QVariant::List:
+        return create(variant.toList());
+    case QVariant::StringList:
+        return create(variant.toStringList());
+    default:
+        if (variant.canConvert<int>()) {
+            return create(variant.toInt());
+        }
+        return create(variant.toString());
+    }
+}
+
+inline QVariant value2Variant(const Napi::Value& value);
+
+template<typename RET>
+inline typename std::enable_if<std::is_integral<typename std::decay<RET>::type>::value &&
+                                       !std::is_same<typename std::decay<RET>::type, bool>::value, RET>::type
+get(const Napi::Value& value)
+{
+    if (!value.IsNumber()) {
+        return RET{};
+    }
+    return static_cast<RET>(value.As<Napi::Number>().Int32Value());
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_enum<typename std::decay<RET>::type>::value, RET>::type
+get(const Napi::Value& value)
+{
+    using DecayRET = typename std::decay<RET>::type;
+    using UnderlyingType = typename std::underlying_type<DecayRET>::type;
+    UnderlyingType underlying = get<UnderlyingType>(value);
+    return static_cast<DecayRET>(underlying);
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_same<typename std::decay<RET>::type, QString>::value, RET>::type
+get(const Napi::Value& value)
+{
+    if (!value.IsString()) {
+        return QString();
+    }
+    std::string str = value.As<Napi::String>();
+    return QString::fromStdString(str);
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_same<typename std::decay<RET>::type, QByteArray>::value, RET>::type
+get(const Napi::Value& value)
+{
+    if (!value.IsString()) {
+        return QByteArray();
+    }
+    std::string str = value.As<Napi::String>();
+    return QByteArray::fromStdString(str);
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_same<typename std::decay<RET>::type, QVariantMap>::value, RET>::type
+get(const Napi::Value& value)
+{
+    QVariantMap result;
+    if (!value.IsObject()) {
+        return result;
+    }
+
+    Napi::Object obj = value.As<Napi::Object>();
+    auto propertyNames = obj.GetPropertyNames();
+    uint32_t length = propertyNames.Length();
+
+    for (uint32_t i = 0; i < length; ++i) {
+        Napi::Value key = propertyNames.Get(i);
+        Napi::Value val = obj.Get(key);
+
+        if (key.IsString()) {
+            QString qKey = QString::fromStdString(key.As<Napi::String>());
+            QVariant qValue = value2Variant(val);
+            result.insert(qKey, qValue);
+        }
+    }
+    return result;
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_same<typename std::decay<RET>::type, QVariantList>::value, RET>::type
+get(const Napi::Value& value)
+{
+    QVariantList result;
+    if (!value.IsArray()) {
+        return result;
+    }
+
+    Napi::Array array = value.As<Napi::Array>();
+    uint32_t length = array.Length();
+
+    for (uint32_t i = 0; i < length; ++i) {
+        Napi::Value element = array.Get(i);
+        result.append(value2Variant(element));
+    }
+    return result;
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_same<typename std::decay<RET>::type, QStringList>::value, RET>::type
+get(const Napi::Value& value)
+{
+    QStringList result;
+    if (!value.IsArray()) {
+        return result;
+    }
+
+    Napi::Array array = value.As<Napi::Array>();
+    uint32_t length = array.Length();
+
+    for (uint32_t i = 0; i < length; ++i) {
+        Napi::Value element = array.Get(i);
+        result << get<QString>(element);
+    }
+    return result;
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_same<typename std::decay<RET>::type, QVariant>::value, RET>::type
+get(const Napi::Value& value)
+{
+    return value2Variant(value);
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_same<typename std::decay<RET>::type, bool>::value, RET>::type
+get(const Napi::Value& value)
+{
+    if (!value.IsBoolean()) {
+        return false;
+    }
+    return value.ToBoolean();
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_floating_point<typename std::decay<RET>::type>::value, RET>::type
+get(const Napi::Value& value)
+{
+    if (!value.IsNumber()) {
+        return RET{};
+    }
+    return static_cast<RET>(value.As<Napi::Number>().DoubleValue());
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_same<typename std::decay<RET>::type, std::string>::value, RET>::type
+get(const Napi::Value& value)
+{
+    if (!value.IsString()) {
+        return std::string{};
+    }
+    return value.As<Napi::String>();
+}
+
+template<typename RET>
+inline typename std::enable_if<!std::is_enum<typename std::decay<RET>::type>::value &&
+                                       !std::is_same<typename std::decay<RET>::type, QString>::value &&
+                                       !std::is_same<typename std::decay<RET>::type, QByteArray>::value &&
+                                       !std::is_same<typename std::decay<RET>::type, QVariantMap>::value &&
+                                       !std::is_same<typename std::decay<RET>::type, QVariantList>::value &&
+                                       !std::is_same<typename std::decay<RET>::type, QStringList>::value &&
+                                       !std::is_same<typename std::decay<RET>::type, QVariant>::value &&
+                                       !std::is_same<typename std::decay<RET>::type, bool>::value &&
+                                       !std::is_integral<typename std::decay<RET>::type>::value &&
+                                       !std::is_floating_point<typename std::decay<RET>::type>::value &&
+                                       !std::is_same<typename std::decay<RET>::type, std::string>::value, RET>::type
+get(const Napi::Value& value)
+{
+    return value.As<RET>();
+}
+
+inline QVariant value2Variant(const Napi::Value& value)
+{
+    if (value.IsNull() || value.IsUndefined()) {
+        return QVariant();
+    } else if (value.IsBoolean()) {
+        return QVariant(get<bool>(value));
+    } else if (value.IsNumber()) {
+        double num = value.As<Napi::Number>().DoubleValue();
+        if (std::floor(num) == num && num >= std::numeric_limits<int>::min() && num <= std::numeric_limits<int>::max()) {
+            return QVariant(get<int>(value));
+        } else {
+            return QVariant(get<double>(value));
+        }
+    } else if (value.IsString()) {
+        return QVariant(get<QString>(value));
+    } else if (value.IsArray()) {
+        return QVariant(get<QVariantList>(value));
+    } else if (value.IsObject()) {
+        return QVariant(get<QVariantMap>(value));
+    }
+    return QVariant(get<QString>(value.ToString()));
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_default_constructible<RET>::value, RET>::type
+get(const Napi::Object& object, const char *property)
+{
+    if (!object.Has(property)) {
+        return RET{};
+    }
+    Napi::Value value = object.Get(property);
+    return get<RET>(value);
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_default_constructible<RET>::value, RET>::type
+get(const Napi::Object& object, const QString& property)
+{
+    return get<RET>(object, property.toUtf8().constData());
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_default_constructible<RET>::value, RET>::type
+get(const Napi::Value& value, const char *property)
+{
+    if (!value.IsObject()) {
+        return RET{};
+    }
+
+    Napi::Object object = value.As<Napi::Object>();
+    return get<RET>(object, property);
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_default_constructible<RET>::value, RET>::type
+get(const Napi::Value& value, const QString& property)
+{
+    return get<RET>(value, property.toUtf8().constData());
+}
+
+template<typename RET>
+inline RET getOrDefault(const Napi::Object& object, const char *property, const RET& defaultValue)
+{
+    if (!object.Has(property)) {
+        return defaultValue;
+    }
+
+    Napi::Value propertyValue = object.Get(property);
+    return get<RET>(propertyValue);
+}
+
+template<typename RET>
+inline RET getOrDefault(const Napi::Value& value, const char *property, const RET& defaultValue)
+{
+    if (!value.IsObject()) {
+        return defaultValue;
+    }
+
+    Napi::Object object = value.As<Napi::Object>();
+    if (!object.Has(property)) {
+        return defaultValue;
+    }
+
+    Napi::Value propertyValue = object.Get(property);
+    return get<RET>(propertyValue);
+}
+
+template<typename T>
+inline void set(Napi::Object& object, const char *property, T&& value)
+{
+    object.Set(property, create(std::forward<T>(value)));
+}
+
+template<typename T>
+inline void set(Napi::Object& object, const QString &property, T&& value)
+{
+    object.Set(property.toStdString(), create(std::forward<T>(value)));
+}
+
+template<typename RET>
+inline typename std::enable_if<std::is_default_constructible<RET>::value, RET>::type
+getFirst(const Napi::CallbackInfo &info)
+{
+    if (info.Length() < 1)
+        return RET{};
+    return get<RET>(info[0]);
+}
+
+//#endif
+}
+
+QT_END_NAMESPACE
+#endif // QNAPI_H
+
diff --git a/src/corelib/kernel/qohhiappevent_p.h b/src/corelib/kernel/qohhiappevent_p.h
new file mode 100644
index 00000000000..5c87b55df98
--- /dev/null
+++ b/src/corelib/kernel/qohhiappevent_p.h
@@ -0,0 +1,51 @@
+#ifndef QOHHIAPPEVENT_P_H
+#define QOHHIAPPEVENT_P_H
+
+#include <mutex>
+#include <memory>
+#include <string>
+#include <qglobal.h>
+#include <QJsModule>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtOhosWatchdog
+{
+class Q_CORE_EXPORT QOhHiAppEvent {
+    friend class QOhosWatchdog;
+    Q_DISABLE_COPY_MOVE(QOhHiAppEvent)
+
+    std::atomic<bool> m_dogReported;
+    std::unique_ptr<QJsModule> m_jsHiApp {nullptr};
+
+    inline static std::once_flag sm_once;
+    inline static std::unique_ptr<QOhHiAppEvent> sm_self {nullptr};
+
+    explicit QOhHiAppEvent();
+
+    enum {
+        FAULT = 1,     /* 故障类型事件 */
+        STATISTIC = 2, /* 统计类型事件 */
+        SECURITY = 3,  /* 安全类型事件 */
+        BEHAVIOR = 4,  /* 行为类型事件 */
+    };
+public:
+    ~QOhHiAppEvent() {};
+
+    static QOhHiAppEvent *instance() {
+        std::call_once(sm_once, []{
+            sm_self.reset(new QOhHiAppEvent());
+        });
+        return sm_self.get();
+    }
+
+    void writeDataTag(const std::string &txt);
+
+protected:
+    void writeDataTagImple(const std::string &txt, bool reported = false, bool inner = false);
+};
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/kernel/qohoswatchdog.cpp b/src/corelib/kernel/qohoswatchdog.cpp
new file mode 100644
index 00000000000..11196712af8
--- /dev/null
+++ b/src/corelib/kernel/qohoswatchdog.cpp
@@ -0,0 +1,247 @@
+/****************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <dlfcn.h>
+#include <unistd.h>
+#include <QDateTime>
+#include <qopenharmony.h>
+#include <QLoggingCategory>
+#include <qopenharmonydefines.h>
+#include <QtCore/qcoreapplication.h>
+
+#include "qohoswatchdog.h"
+#include "qohhiappevent_p.h"
+
+Q_LOGGING_CATEGORY(ohoswatchdog, "qt.ohos.watchdog")
+QT_BEGIN_NAMESPACE
+
+namespace QtOhosWatchdog
+{
+
+QOhHiAppEvent::QOhHiAppEvent()
+{
+    m_dogReported.exchange(false);
+    m_jsHiApp.reset(new QJsModule("@ohos.hiviewdfx.hiAppEvent"));
+}
+
+void QOhHiAppEvent::writeDataTag(const std::string &txt)
+{
+    writeDataTagImple(txt);
+}
+
+void QOhHiAppEvent::writeDataTagImple(const std::string &txt, bool reported, bool inner)
+{
+    QtOh::runOnJsUIThreadAndWait([this, txt, reported, inner] {
+        Napi::HandleScope scope(this->m_jsHiApp->env());
+        Napi::Object appInfo = Napi::Object::New(this->m_jsHiApp->env());
+        Napi::Object params = Napi::Object::New(this->m_jsHiApp->env());
+        params.Set("app", Napi::String::New(this->m_jsHiApp->env(), qAppName().toStdString()));
+        params.Set("timestamp", Napi::Number::New(this->m_jsHiApp->env(), QDateTime::currentMSecsSinceEpoch()));
+
+        appInfo.Set("params", params);
+        appInfo.Set("name", Napi::String::New(this->m_jsHiApp->env(), txt));
+        appInfo.Set("eventType", Napi::Number::New(this->m_jsHiApp->env(), BEHAVIOR));
+        appInfo.Set("domain", Napi::String::New(this->m_jsHiApp->env(), "QOhosWatchdog"));
+        Napi::Function asyncCallback = Napi::Function::New(this->m_jsHiApp->env(), [this, txt, reported, inner](const Napi::CallbackInfo &info) {
+            Napi::Object error = info[0].As<Napi::Object>();
+            if (!error.IsNull()) {
+                Napi::Number code = error.Get("code").ToNumber();
+                Napi::String message = error.Get("message").ToString();
+                LOGW("%{public}s hiAppEvent result code: %{public}d message: %{public}s",
+                     txt.c_str(),
+                     code.Int32Value(),
+                     message.Utf8Value().c_str());
+            } else {
+                LOGW("%{public}s hiAppEvent success to write event.", txt.c_str());
+            }
+
+            if (inner)
+                m_dogReported.exchange(reported);
+        });
+        m_jsHiApp->call("write", {appInfo, asyncCallback});
+    });
+}
+
+namespace
+{
+constexpr uint32_t CHECK_MAIN_THREAD_IS_ALIVE = 1;
+constexpr int RESET_RATIO = 2;
+constexpr int32_t BACKGROUND_REPORT_COUNT_MAX = 5;
+
+#ifdef SUPPORT_ASAN
+constexpr uint32_t CHECK_INTERVAL_TIME = 45000;
+#else
+constexpr uint32_t CHECK_INTERVAL_TIME = 3000;
+#endif
+}
+
+QOhosWatchdog* globalQtWatchdog = nullptr;
+
+QOhosWatchdog::~QOhosWatchdog()
+{
+    globalQtWatchdog = nullptr;
+}
+
+QOhosWatchdog::QOhosWatchdog()
+{
+    globalQtWatchdog = this;
+}
+
+void OH_HiCollie_Task() {
+    globalQtWatchdog->Timer();
+}
+
+void QOhosWatchdog::Init()
+{
+    qCDebug(ohoswatchdog, "QOhosWatchdog:: init.");
+    std::unique_lock<std::mutex> lock(cvMutex_);
+    QCoreApplication::postEvent(QCoreApplication::instance(),
+        new QEvent(QEvent::CheckMainThreadIsAlive), Qt::HighEventPriority);
+    lastWatchTime_ = 0;
+    OH_HiCollie_Init_StuckDetection(OH_HiCollie_Task);
+    qCDebug(ohoswatchdog,"QOhosWatchdog:: init end.");
+}
+
+void QOhosWatchdog::Stop()
+{
+    qCDebug(ohoswatchdog,"QOhosWatchdog:: Stop.");
+    std::unique_lock<std::mutex> lock(cvMutex_);
+    if (stopWatchdog_->load()) {
+        qCWarning(ohoswatchdog,"QOhosWatchdog:: has stoped.");
+        return;
+    }
+    stopWatchdog_->store(true);
+    cvWatchdog_.notify_all();
+}
+
+void QOhosWatchdog::SetAppMainThreadState(const bool appMainThreadState)
+{
+    qCDebug(ohoswatchdog,"QOhosWatchdog:: SetAppMainThreadState. %d", appMainThreadState);
+    std::unique_lock<std::mutex> lock(cvMutex_);
+    appMainThreadIsAlive_->store(appMainThreadState);
+}
+
+void QOhosWatchdog::AllowReportEvent()
+{
+    qCDebug(ohoswatchdog,"QOhosWatchdog:: AllowReportEvent.");
+    std::unique_lock<std::mutex> lock(cvMutex_);
+    needReport_->store(true);
+    isSixSecondEvent_->store(false);
+    backgroundReportCount_->store(0);
+    QOhHiAppEvent::instance()->writeDataTagImple("AllowReportEvent", false, true);
+}
+
+bool QOhosWatchdog::IsReportEvent()
+{
+    qCDebug(ohoswatchdog,"QOhosWatchdog:: IsReportEvent.");
+    if (appMainThreadIsAlive_->load()) {
+        qCWarning(ohoswatchdog,"QOhosWatchdog:: IsReportEvent store false.");
+        appMainThreadIsAlive_->store(false);
+        return false;
+    }
+    qCDebug(ohoswatchdog,"QOhosWatchdog:: AppMainThread is not alive.");
+    return true;
+}
+
+void QOhosWatchdog::Timer()
+{
+    qCDebug(ohoswatchdog,"QOhosWatchdog:: Timer start.");
+    std::unique_lock<std::mutex> lock(cvMutex_, std::defer_lock);
+    if (!lock.owns_lock()) {
+        return;
+    }
+
+    if (stopWatchdog_->load()) {
+        qCWarning(ohoswatchdog,"QOhosWatchdog:: QOhosWatchdog has stoped.");
+        return;
+    }
+    if (!needReport_->load()) {
+        qCWarning(ohoswatchdog,"QOhosWatchdog:: QOhosWatchdog timeout, wait for the handler to recover, and do not send event.");
+        return;
+    }
+
+    if (IsReportEvent()) {
+        ReportEvent();
+    }
+
+    QCoreApplication::postEvent(QCoreApplication::instance(),
+        new QEvent(QEvent::CheckMainThreadIsAlive), Qt::HighEventPriority);
+
+    int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::
+        system_clock::now().time_since_epoch()).count();
+    if ((now - lastWatchTime_) >= (CHECK_INTERVAL_TIME / RESET_RATIO)) {
+        lastWatchTime_ = now;
+    }
+    qCDebug(ohoswatchdog,"QOhosWatchdog:: Timer end.");
+}
+
+void QOhosWatchdog::ReportEvent()
+{
+    qCDebug(ohoswatchdog,"QOhosWatchdog:: ReportEvent start.");
+    int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::
+        system_clock::now().time_since_epoch()).count();
+    if ((now - lastWatchTime_) > (RESET_RATIO * CHECK_INTERVAL_TIME) ||
+        (now - lastWatchTime_) < (CHECK_INTERVAL_TIME / RESET_RATIO)) {
+        qCWarning(ohoswatchdog,"QOhosWatchdog: Thread may be blocked, do not report this time. currTime: %llu, lastTime: %llu",
+            static_cast<unsigned long long>(now), static_cast<unsigned long long>(lastWatchTime_));
+        return;
+    }
+
+    if (!needReport_->load()) {
+        qCWarning(ohoswatchdog,"QOhosWatchdog:: ReportEvent return.");
+        return;
+    }
+
+#ifndef APP_NO_RESPONSE_DIALOG
+    if (isSixSecondEvent_->load()) {
+        needReport_->store(false);
+    }
+#endif
+    qCDebug(ohoswatchdog,"WatchdogInner QOhosWatchdog:: ReportEvent. isSixSecondEvent_ = %d", isSixSecondEvent_->load());
+    bool temp = isSixSecondEvent_->load();
+    if (temp)
+        QOhHiAppEvent::instance()->writeDataTagImple("ReportEvent", true, true);
+
+    OH_HiCollie_Report(&temp);
+    isSixSecondEvent_->store(temp);
+    qCDebug(ohoswatchdog,"QOhosWatchdog:: ReportEvent end. isSixSecondEvent_ = %d", isSixSecondEvent_->load());
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qohoswatchdog.h b/src/corelib/kernel/qohoswatchdog.h
new file mode 100644
index 00000000000..a9170874e6f
--- /dev/null
+++ b/src/corelib/kernel/qohoswatchdog.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOHOSWATCHDOG_H
+#define QOHOSWATCHDOG_H
+
+#include <string>
+#include <mutex>
+#include <condition_variable>
+#include <atomic>
+#include <hicollie/hicollie.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtOhosWatchdog
+{
+class QOhosWatchdog
+{
+public:
+    QOhosWatchdog();
+    ~QOhosWatchdog();
+
+    /**
+     *
+     * @brief Init the Watchdog.
+     *
+     * @param mainHandler The handler of main thread.
+     */
+    void Init();
+
+    /**
+     *
+     * @brief Stop the mainthread function of watchdog.
+     *
+     */
+    void Stop();
+
+    /**
+     *
+     * @brief Set the state of main thread.
+     *
+     * @param appMainThreadState The state of main thread.
+     */
+    void SetAppMainThreadState(const bool appMainThreadState);
+
+        /**
+     *
+     * @brief Allow report the main thread timeout event.
+     *
+     */
+    void AllowReportEvent();
+
+    /**
+     *
+     * @brief Check and reset the main thread state.
+     *
+     */
+    bool IsReportEvent();
+    void Timer();
+
+private:
+    void ReportEvent();
+    std::mutex cvMutex_;
+    int64_t lastWatchTime_ = 0;
+    std::condition_variable cvWatchdog_;
+    std::shared_ptr<std::atomic<bool>> appMainThreadIsAlive_ = std::make_shared<std::atomic<bool>>(false);
+    std::shared_ptr<std::atomic<bool>> stopWatchdog_ = std::make_shared<std::atomic<bool>>(false);
+    std::shared_ptr<std::atomic<bool>> needReport_ = std::make_shared<std::atomic<bool>>(true);
+    std::shared_ptr<std::atomic<bool>> isSixSecondEvent_ = std::make_shared<std::atomic<bool>>(false);
+    std::shared_ptr<std::atomic<int64_t>> backgroundReportCount_ = std::make_shared<std::atomic<int64_t>>(0);
+};
+}
+
+QT_END_NAMESPACE
+
+#endif /* QOHOSWATCHDOG_H */
diff --git a/src/corelib/kernel/qohutility.cpp b/src/corelib/kernel/qohutility.cpp
new file mode 100644
index 00000000000..5ee76e24eaa
--- /dev/null
+++ b/src/corelib/kernel/qohutility.cpp
@@ -0,0 +1,168 @@
+#include "qohutility.h"
+#include <deviceinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+static inline bool equal(const char *s1, const char *s2)
+{
+    return strcmp(s1, s2) == 0;
+}
+namespace QtOh {
+
+Utility::DeviceType Utility::type()
+{
+    const char *t = OH_GetDeviceType();
+    if (equal(t, "2in1")) {
+        return PC;
+    } else if (equal(t, "phone") || equal(t, "default")) {
+        return Phone;
+    } else if (equal(t, "wearable")) {
+        return Wearable;
+    } else if (equal(t, "liteWearable")) {
+        return LiteWearable;
+    } else if (equal(t, "tablet")) {
+        return Tablet;
+    } else if (equal(t, "tv")) {
+        return Tv;
+    } else if (equal(t, "car")) {
+        return Car;
+    } else if (equal(t, "smartVision")) {
+        return SmartVision;
+    }
+    return Unknown;
+}
+
+#define DEVICE_INFO(func) QString::fromUtf8(func)
+
+QString Utility::manufacture()
+{
+    return DEVICE_INFO(OH_GetManufacture());
+}
+
+QString Utility::brand()
+{
+    return DEVICE_INFO(OH_GetBrand());
+}
+
+QString Utility::marketName()
+{
+    return DEVICE_INFO(OH_GetMarketName());
+}
+
+QString Utility::productSeries()
+{
+    return DEVICE_INFO(OH_GetProductSeries());
+}
+
+QString Utility::productModel()
+{
+    return DEVICE_INFO(OH_GetProductModel());
+}
+
+QString Utility::softwareModel()
+{
+    return DEVICE_INFO(OH_GetSoftwareModel());
+}
+
+QString Utility::hardwareModel()
+{
+    return DEVICE_INFO(OH_GetHardwareModel());
+}
+
+QString Utility::bootloaderVersion()
+{
+    return DEVICE_INFO(OH_GetBootloaderVersion());
+}
+
+QString Utility::abiList()
+{
+    return DEVICE_INFO(OH_GetAbiList());
+}
+
+QString Utility::securityPatchTag()
+{
+    return DEVICE_INFO(OH_GetSecurityPatchTag());
+}
+
+QString Utility::displayVersion()
+{
+    return DEVICE_INFO(OH_GetDisplayVersion());
+}
+
+QString Utility::incrementalVersion()
+{
+    return DEVICE_INFO(OH_GetIncrementalVersion());
+}
+
+QString Utility::osReleaseType()
+{
+    return DEVICE_INFO(OH_GetOsReleaseType());
+}
+
+QString Utility::oSFullName()
+{
+    return DEVICE_INFO(OH_GetOSFullName());
+}
+
+int Utility::sdkApiVersion()
+{
+    return OH_GetSdkApiVersion();
+}
+
+int Utility::firstApiVersion()
+{
+    return OH_GetFirstApiVersion();
+}
+
+QString Utility::versionId()
+{
+    return DEVICE_INFO(OH_GetVersionId());
+}
+
+QString Utility::buildType()
+{
+    return DEVICE_INFO(OH_GetBuildType());
+}
+
+QString Utility::buildUser()
+{
+    return DEVICE_INFO(OH_GetBuildUser());
+}
+
+QString Utility::buildHost()
+{
+    return DEVICE_INFO(OH_GetBuildHost());
+}
+
+QString Utility::buildTime()
+{
+    return DEVICE_INFO(OH_GetBuildTime());
+}
+
+QString Utility::buildRootHash()
+{
+    return DEVICE_INFO(OH_GetBuildRootHash());
+}
+
+QString Utility::distributionOSName()
+{
+    return DEVICE_INFO(OH_GetDistributionOSName());
+}
+
+QString Utility::distributionOSVersion()
+{
+    return DEVICE_INFO(OH_GetDistributionOSVersion());
+}
+
+QString Utility::distributionOSReleaseType()
+{
+    return DEVICE_INFO(OH_GetDistributionOSReleaseType());
+}
+
+int Utility::distributionOSApiVersion()
+{
+    return OH_GetDistributionOSApiVersion();
+}
+
+}
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qohutility.h b/src/corelib/kernel/qohutility.h
new file mode 100644
index 00000000000..496a2fb308c
--- /dev/null
+++ b/src/corelib/kernel/qohutility.h
@@ -0,0 +1,59 @@
+#ifndef QOHUTILITY_H
+#define QOHUTILITY_H
+
+#include <qstring.h>
+#include <QtCore/qflags.h>
+
+QT_BEGIN_NAMESPACE
+namespace QtOh {
+
+class Q_CORE_EXPORT Utility
+{
+public:
+    enum DeviceType {
+        Unknown = 0x00,
+        PC = 0x01,
+        Phone = 0x02,
+        Wearable = 0x04,
+        LiteWearable = 0x08,
+        Tablet = 0x10,
+        Tv = 0x20,
+        Car = 0x40,
+        SmartVision = 0x80
+    };
+    Q_DECLARE_FLAGS(DeviceTypes, DeviceType)
+
+    static DeviceType type();
+    static QString manufacture();
+    static QString brand();
+    static QString marketName();
+    static QString productSeries();
+    static QString productModel();
+    static QString softwareModel();
+    static QString hardwareModel();
+    static QString bootloaderVersion();
+    static QString abiList();
+    static QString securityPatchTag();
+    static QString displayVersion();
+    static QString incrementalVersion();
+    static QString osReleaseType();
+    static QString oSFullName();
+    static int sdkApiVersion();
+    static int firstApiVersion();
+    static QString versionId();
+    static QString buildType();
+    static QString buildUser();
+    static QString buildHost();
+    static QString buildTime();
+    static QString buildRootHash();
+    static QString distributionOSName();
+    static QString distributionOSVersion();
+    static QString distributionOSReleaseType();
+    static int distributionOSApiVersion();
+};
+}
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QtOh::Utility::DeviceTypes)
+
+QT_END_NAMESPACE
+#endif // QOHUTILITY_H
diff --git a/src/corelib/kernel/qopenharmony.cpp b/src/corelib/kernel/qopenharmony.cpp
new file mode 100644
index 00000000000..aa3fe8fc61d
--- /dev/null
+++ b/src/corelib/kernel/qopenharmony.cpp
@@ -0,0 +1,180 @@
+#include <QHash>
+#include <filemanagement/file_uri/oh_file_uri.h>
+
+#include "qjsmodule.h"
+#include "qohutility.h"
+#include "qopenharmony.h"
+#include "qopenharmony_p.h"
+#include "qopenharmonydefines.h"
+
+static QString g_bundleName;
+static QString g_moduleName;
+static QString g_abilityName;
+
+static napi_env g_ui_env = nullptr;
+static std::thread::id g_ui_thread_id;
+
+void QtOh::setUIEnv(napi_env env)
+{
+    g_ui_env = env;
+    g_ui_thread_id = std::this_thread::get_id();
+}
+
+napi_env QtOh::uiEnv()
+{
+    return g_ui_env;
+}
+
+void QtOh::setBundleName(const QString &name)
+{
+    g_bundleName = name;
+}
+
+QString QtOh::bundleName()
+{
+    return g_bundleName;
+}
+
+void QtOh::setModuleName(const QString &name)
+{
+    g_moduleName = name;
+}
+
+QString QtOh::moduleName()
+{
+    return g_moduleName;
+}
+
+void QtOh::setAbilityName(const QString &name)
+{
+    g_abilityName = name;
+}
+
+QString QtOh::abilityName()
+{
+    return g_abilityName;
+}
+
+void QtOh::runOnJsUIThreadNoWait(const std::function<void ()> &f)
+{
+    uv_loop_s *loop = nullptr;
+    napi_get_uv_event_loop(uiEnv(), &loop);
+    if (loop == nullptr) {
+        return;
+    }
+    uv_work_t *work = new uv_work_t;
+    if (work == nullptr) {
+        return;
+    }
+
+    struct TaskContext
+    {
+        std::function<void()> function;
+    };
+
+    TaskContext *p = new TaskContext { f };
+    work->data = p;
+    uv_work_cb uvWork = [](uv_work_t *work) {};
+    uv_after_work_cb uvAfterWork = [](uv_work_t *work, int _status){
+        TaskContext *p = (TaskContext *)(work->data);
+        p->function();
+        delete p;
+        delete work;
+    };
+    uv_queue_work(loop, work, uvWork, uvAfterWork);
+}
+
+void QtOh::runOnJsUIThreadAndWait(const std::function<void ()> &f)
+{
+    if (std::this_thread::get_id() == g_ui_thread_id) {
+        f();
+        return;
+    }
+    uv_loop_s *loop = nullptr;
+    napi_get_uv_event_loop(uiEnv(), &loop);
+    if (loop == nullptr) {
+        return;
+    }
+    uv_work_t *work = new uv_work_t;
+    if (work == nullptr) {
+        return;
+    }
+
+    struct TaskContext
+    {
+        std::function<void()> function;
+        std::promise<void> promise;
+    };
+
+    TaskContext *p = new TaskContext { f };
+    work->data = p;
+    uv_work_cb uvWork = [](uv_work_t *work) {};
+    uv_after_work_cb uvAfterWork = [](uv_work_t *work, int _status){
+        TaskContext *p = (TaskContext *)(work->data);
+        p->function();
+        p->promise.set_value();
+    };
+    uv_queue_work(loop, work, uvWork, uvAfterWork);
+    auto future = p->promise.get_future();
+    future.wait();
+
+    delete p;
+    p = nullptr;
+
+    delete work;
+    work = nullptr;
+}
+
+std::thread::id QtOh::uiThreadId()
+{
+    return g_ui_thread_id;
+}
+
+static QHash<QString, QString> g_dirs;
+
+QString QtOh::dir(const QString &dirId)
+{
+    return g_dirs.value(dirId);
+}
+
+void QtOh::setDir(const QString &dirId, const QString &dir)
+{
+    g_dirs.insert(dirId, dir);
+}
+
+int QtOh::apiVersion()
+{
+    return QtOh::Utility::sdkApiVersion();
+}
+
+struct FreeDeleter {
+    void operator()(char* ptr) const {
+        std::free(ptr);
+    }
+};
+
+QString QtOh::pathFromUri(const QString &uri)
+{
+    char *data = nullptr;
+    const QByteArray utf8 = uri.toUtf8();
+    const char *cpath = utf8.constData();
+    FileManagement_ErrCode errCode = OH_FileUri_GetPathFromUri(cpath, strlen(cpath), &data);
+    if (ERR_OK != errCode || nullptr == data) {
+        return QString();
+    }
+    std::unique_ptr<char, FreeDeleter> guard(data);
+    return QString::fromUtf8(data);
+}
+
+QString QtOh::uriFromPath(const QString &path)
+{
+    char *data = nullptr;
+    const QByteArray utf8 = path.toUtf8();
+    const char *cpath = utf8.constData();
+    FileManagement_ErrCode errCode = OH_FileUri_GetUriFromPath(cpath, strlen(cpath), &data);
+    if (ERR_OK != errCode || nullptr == data) {
+        return QString();
+    }
+    std::unique_ptr<char, FreeDeleter> guard(data);
+    return QString::fromUtf8(data);
+}
diff --git a/src/corelib/kernel/qopenharmony.h b/src/corelib/kernel/qopenharmony.h
new file mode 100644
index 00000000000..94a69f7d2a7
--- /dev/null
+++ b/src/corelib/kernel/qopenharmony.h
@@ -0,0 +1,51 @@
+#ifndef QOPENHARMONY_H
+#define QOPENHARMONY_H
+
+#include <uv.h>
+#include <mutex>
+#include <future>
+#include <functional>
+#include <QtCore/qglobal.h>
+#include <napi/native_api.h>
+
+#include <qopenharmonydefines.h>
+/* NOTE must be placed after native_api.h */
+#include <QtNapi/napi.h>
+QT_BEGIN_NAMESPACE
+namespace QtOh {
+
+Q_CORE_EXPORT int apiVersion();
+
+Q_CORE_EXPORT void setBundleName(const QString &name);
+
+Q_CORE_EXPORT void setModuleName(const QString &name);
+
+Q_CORE_EXPORT void setAbilityName(const QString &name);
+
+Q_CORE_EXPORT QString bundleName();
+
+Q_CORE_EXPORT QString moduleName();
+
+Q_CORE_EXPORT QString abilityName();
+
+Q_CORE_EXPORT QString dir(const QString &dirId);
+
+Q_CORE_EXPORT void setDir(const QString &dirId, const QString &dir);
+
+Q_CORE_EXPORT void setUIEnv(napi_env env);
+
+Q_CORE_EXPORT napi_env uiEnv();
+
+Q_CORE_EXPORT std::thread::id uiThreadId();
+
+Q_CORE_EXPORT void runOnJsUIThreadNoWait(const std::function<void()> &f);
+
+Q_CORE_EXPORT void runOnJsUIThreadAndWait(const std::function<void()> &f);
+
+Q_CORE_EXPORT QString pathFromUri(const QString &uri);
+
+Q_CORE_EXPORT QString uriFromPath(const QString &path);
+}
+QT_END_NAMESPACE
+
+#endif // QOPENHARMONY_H
diff --git a/src/corelib/kernel/qopenharmony_p.h b/src/corelib/kernel/qopenharmony_p.h
new file mode 100644
index 00000000000..9591f24c4c8
--- /dev/null
+++ b/src/corelib/kernel/qopenharmony_p.h
@@ -0,0 +1,107 @@
+#ifndef QOPENHARMONY_P_H
+#define QOPENHARMONY_P_H
+
+#include <QtCore/qopenharmony.h>
+
+QT_BEGIN_NAMESPACE
+namespace QtOh {
+
+template <typename Function, typename... Args>
+auto runOnJsUIThreadWithResult(Function&& function, Args&&... args)
+    -> decltype(std::invoke(std::forward<Function>(function), std::forward<Args>(args)...))
+{
+    using ReturnType = decltype(std::invoke(std::forward<Function>(function), std::forward<Args>(args)...));
+
+    if (std::this_thread::get_id() == uiThreadId()) {
+        return std::invoke(std::forward<Function>(function), std::forward<Args>(args)...);
+    }
+
+    uv_loop_s *loop = nullptr;
+    napi_get_uv_event_loop(uiEnv(), &loop);
+    if (loop == nullptr) {
+        return ReturnType{};
+    }
+    auto promise = std::make_shared<std::promise<ReturnType>>();
+    auto future = promise->get_future();
+    uv_work_t *work = new uv_work_t;
+
+    struct TaskContext {
+        std::function<ReturnType()> task;
+        std::shared_ptr<std::promise<ReturnType>> promise;
+    };
+
+    TaskContext *p = new TaskContext{ [function = std::forward<Function>(function), ...args = std::forward<Args>(args)]() mutable {
+        return std::invoke(std::forward<Function>(function), std::forward<Args>(args)...);
+    }, promise};
+
+    work->data = p;
+    uv_queue_work(loop, work,
+                  [](uv_work_t* work) { Q_UNUSED(work) },
+    [](uv_work_t* work, int status) {
+        Q_UNUSED(status)
+        auto* ctx = static_cast<TaskContext*>(work->data);
+        ctx->promise->set_value(ctx->task());
+        delete ctx;
+        delete work;
+    }
+    );
+    return future.get();
+}
+
+// 不要在Js线程中调用
+template <typename ReturnType, typename Function, typename... Args>
+auto runOnJsUIThreadWithPromise(Function&& function, Args&&... args)
+    -> ReturnType
+{
+    if (std::this_thread::get_id() == uiThreadId()) {
+        LOGW("Could not call runOnJsUIThreadWithPromise in js thread");
+        if constexpr (std::is_void_v<ReturnType>) {
+            return;
+        } else {
+            return ReturnType{};
+        }
+    }
+    auto promise = std::make_shared<std::promise<ReturnType>>();
+    auto future = promise->get_future();
+
+    uv_loop_t* loop = nullptr;
+    napi_get_uv_event_loop(uiEnv(), &loop);
+    if (!loop) {
+        if constexpr (std::is_void_v<ReturnType>) {
+            promise->set_value();
+        } else {
+            promise->set_value(ReturnType{});
+        }
+        return future.get();
+    }
+
+    struct TaskContext {
+        std::function<void(std::shared_ptr<std::promise<ReturnType>> promise)> task;
+        std::shared_ptr<std::promise<ReturnType>> promise;
+    };
+
+    TaskContext *p = new TaskContext{
+        [function = std::forward<Function>(function), ...args = std::forward<Args>(args)](auto promise) mutable {
+            std::invoke(std::forward<Function>(function), promise, std::forward<Args>(args)...);
+    }, promise};
+
+    uv_work_t* work = new uv_work_t;
+    work->data = p;
+
+    uv_queue_work(loop, work,
+                  [](uv_work_t* work) { Q_UNUSED(work) },
+    [](uv_work_t* work, int status) {
+        Q_UNUSED(status)
+        auto* ctx = static_cast<TaskContext*>(work->data);
+        ctx->task(ctx->promise);
+        delete ctx;
+        delete work;
+    }
+    );
+
+    return future.get();
+}
+}
+QT_END_NAMESPACE
+
+#endif // QOPENHARMONY_P_H
diff --git a/src/corelib/kernel/qopenharmonydefines.h b/src/corelib/kernel/qopenharmonydefines.h
new file mode 100644
index 00000000000..58611ca5bee
--- /dev/null
+++ b/src/corelib/kernel/qopenharmonydefines.h
@@ -0,0 +1,107 @@
+#ifndef QOPENHARMONYDEFINES_H
+#define QOPENHARMONYDEFINES_H
+#include <hilog/log.h>
+
+#define QPA_LOG_DOMAIN 0xff11
+#define QPA_LOG_TAG "QPAForOpenHarmony"
+#define LOGI(...) ((void)OH_LOG_Print(LOG_APP, LOG_INFO, QPA_LOG_DOMAIN, QPA_LOG_TAG, __VA_ARGS__))
+#define LOGD(...) ((void)OH_LOG_Print(LOG_APP, LOG_DEBUG, QPA_LOG_DOMAIN, QPA_LOG_TAG, __VA_ARGS__))
+#define LOGW(...) ((void)OH_LOG_Print(LOG_APP, LOG_WARN, QPA_LOG_DOMAIN, QPA_LOG_TAG, __VA_ARGS__))
+#define LOGE(...) ((void)OH_LOG_Print(LOG_APP, LOG_ERROR, QPA_LOG_DOMAIN, QPA_LOG_TAG, __VA_ARGS__))
+
+#define NAPI_RETVAL_NOTHING
+
+#define GET_AND_THROW_LAST_ERROR(env, status, function)                                                     \
+    do {                                                                                                    \
+        const napi_extended_error_info* errorInfo = nullptr;                                                \
+        napi_get_last_error_info((env), &errorInfo);                                                        \
+        bool isPending = false;                                                                             \
+        napi_is_exception_pending((env), &isPending);                                                       \
+        if (!isPending && errorInfo != nullptr) {                                                           \
+            const char* errorMessage =                                                                      \
+                errorInfo->error_message != nullptr ? errorInfo->error_message : function;                  \
+                LOGE("call method %{public}s failed, the error code is %{public}d", errorMessage, status);  \
+        }                                                                                                   \
+    } while (0)
+
+#define NAPI_ASSERT_BASE(env, assertion, message, retVal)                                    \
+    do {                                                                                     \
+        if (!(assertion)) {                                                                  \
+            napi_throw_error((env), nullptr, "assertion (" #assertion ") failed: " message); \
+            return retVal;                                                                   \
+        }                                                                                    \
+    } while (0)
+
+#define NAPI_ASSERT(env, assertion, message) NAPI_ASSERT_BASE(env, assertion, message, nullptr)
+
+#define NAPI_ASSERT_RETURN_VOID(env, assertion, message) NAPI_ASSERT_BASE(env, assertion, message, NAPI_RETVAL_NOTHING)
+
+#define NAPI_CALL_BASE(env, theCall, retVal)                   \
+    do {                                                       \
+        napi_status status = (theCall);                        \
+        if (status != napi_ok) {                               \
+            GET_AND_THROW_LAST_ERROR((env), status, #theCall); \
+            return retVal;                                     \
+        }                                                      \
+    } while (0)
+
+#define NAPI_CALL_BASE_NO_THROW(env, theCall, retVal) \
+    do {                                     \
+        if ((theCall) != napi_ok) {          \
+            return retVal;                   \
+        }                                    \
+    } while (0)
+
+#define NAPI_CALL(env, theCall) NAPI_CALL_BASE(env, theCall, nullptr)
+
+#define NAPI_CALL_RETURN_VOID(env, theCall) NAPI_CALL_BASE(env, theCall, NAPI_RETVAL_NOTHING)
+
+#define NAPI_CALL_RETURN_VOID_NO_THROW(env, theCall) NAPI_CALL_BASE_NO_THROW(env, theCall, NAPI_RETVAL_NOTHING)
+
+#define DECLARE_NAPI_PROPERTY(name, val)                                       \
+    {                                                                          \
+        (name), nullptr, nullptr, nullptr, nullptr, val, napi_default, nullptr \
+    }
+
+#define DECLARE_NAPI_STATIC_PROPERTY(name, val)                               \
+    {                                                                         \
+        (name), nullptr, nullptr, nullptr, nullptr, val, napi_static, nullptr \
+    }
+
+#define DECLARE_NAPI_FUNCTION(name, func)                                         \
+    {                                                                             \
+        (name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, nullptr \
+    }
+
+#define DECLARE_NAPI_FUNCTION_WITH_DATA(name, func, data)                         \
+    {                                                                             \
+        (name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, data    \
+    }
+
+#define DECLARE_NAPI_STATIC_FUNCTION(name, func)                                 \
+    {                                                                            \
+        (name), nullptr, (func), nullptr, nullptr, nullptr, napi_static, nullptr \
+    }
+
+#define DECLARE_NAPI_GETTER(name, getter)                                           \
+    {                                                                               \
+        (name), nullptr, nullptr, (getter), nullptr, nullptr, napi_default, nullptr \
+    }
+
+#define DECLARE_NAPI_SETTER(name, setter)                                           \
+    {                                                                               \
+        (name), nullptr, nullptr, nullptr, (setter), nullptr, napi_default, nullptr \
+    }
+
+#define DECLARE_NAPI_GETTER_SETTER(name, getter, setter)                             \
+    {                                                                                \
+        (name), nullptr, nullptr, (getter), (setter), nullptr, napi_default, nullptr \
+    }
+
+#define DECLARE_NAPI_FUNCTION(name, func)                                         \
+    {                                                                             \
+        (name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, nullptr \
+    }
+
+
+#endif // QOPENHARMONYDEFINES_H
diff --git a/src/corelib/kernel/qpermissions_openharmony.cpp b/src/corelib/kernel/qpermissions_openharmony.cpp
new file mode 100644
index 00000000000..bb81666fc01
--- /dev/null
+++ b/src/corelib/kernel/qpermissions_openharmony.cpp
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qpermissions.h"
+#include "qpermissions_p.h"
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qfuture.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+namespace QPermissions::Private
+{
+    Qt::PermissionStatus checkPermission(const QPermission &permission)
+    {
+        // Todo
+        return Qt::PermissionStatus::Undetermined;
+    }
+
+    void requestPermission(const QPermission &permission,
+                           const QPermissions::Private::PermissionCallback &callback)
+    {
+        // Todo
+    }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h
index 6d7973faf87..1b4ad092167 100644
--- a/src/corelib/kernel/qsharedmemory_p.h
+++ b/src/corelib/kernel/qsharedmemory_p.h
@@ -122,6 +122,12 @@ public:
     }
 #endif // QT_CONFIG(systemsemaphore)
 
+#ifdef Q_OS_OPENHARMONY
+    struct SharedSegmentMetaData {
+        unsigned int linkCounter;
+    };
+#endif
+
 private:
 #ifdef Q_OS_WIN
     Qt::HANDLE hand = nullptr;
@@ -130,6 +136,10 @@ private:
 #else
     key_t unix_key = 0;
 #endif
+
+#ifdef Q_OS_OPENHARMONY
+    SharedSegmentMetaData *metaDataPtr { nullptr };
+#endif
 };
 
 QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsharedmemory_posix.cpp b/src/corelib/kernel/qsharedmemory_posix.cpp
index fccad56ae38..a5e6906c29c 100644
--- a/src/corelib/kernel/qsharedmemory_posix.cpp
+++ b/src/corelib/kernel/qsharedmemory_posix.cpp
@@ -25,6 +25,59 @@
 
 QT_BEGIN_NAMESPACE
 
+#ifdef Q_OS_OPENHARMONY
+namespace {
+
+QByteArray getMetaDataKey(QString key)
+{
+    return QFile::encodeName(
+            QSharedMemoryPrivate::makePlatformSafeKey(key + QStringLiteral("_qt_metadata")));
+}
+
+QSharedMemoryPrivate::SharedSegmentMetaData *getMetaDataPtr(QString key)
+{
+    using SharedSegmentMetaData = QSharedMemoryPrivate::SharedSegmentMetaData;
+
+    int fd;
+    QT_EINTR_LOOP(fd, ::shm_open(getMetaDataKey(key).constData(), O_RDWR | O_CREAT | O_CLOEXEC, 0600));
+    if (fd == -1) {
+        return nullptr;
+    }
+
+    int ftruncateRes;
+    QT_EINTR_LOOP(ftruncateRes, QT_FTRUNCATE(fd, sizeof(SharedSegmentMetaData)));
+    if (ftruncateRes == -1) {
+        qt_safe_close(fd);
+        return nullptr;
+    }
+
+    void *memory = QT_MMAP(0, sizeof(SharedSegmentMetaData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+    if (memory == MAP_FAILED || memory == nullptr) {
+        qt_safe_close(fd);
+        return nullptr;
+    }
+
+    qt_safe_close(fd);
+
+    return reinterpret_cast<SharedSegmentMetaData *>(memory);
+}
+
+bool unlinkSharedMemory(QString key)
+{
+    const QByteArray shmKey = QFile::encodeName(QSharedMemoryPrivate::makePlatformSafeKey(key));
+    return ::shm_unlink(shmKey.constData()) == 0 || errno == ENOENT;
+}
+
+bool unlinkSharedMemoryMetaData(QString key)
+{
+    const QByteArray shmMetaDataKey = getMetaDataKey(key);
+    return ::shm_unlink(shmMetaDataKey.constData()) == 0 || errno == ENOENT;
+}
+
+}
+#endif
+
+
 using namespace Qt::StringLiterals;
 
 int QSharedMemoryPrivate::handle()
@@ -142,6 +195,19 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
         return false;
     }
 
+#ifdef Q_OS_OPENHARMONY
+    metaDataPtr = getMetaDataPtr(this->key);
+    if (metaDataPtr == nullptr) {
+        setErrorString(QLatin1String("QSharedMemory::attach (getMetaDataPtr)"));
+        cleanHandle();
+        memory = 0;
+        size = 0;
+        return false;
+    }
+
+    ++(metaDataPtr->linkCounter);
+#endif
+
 #ifdef F_ADD_SEALS
     // Make sure the shared memory region will not shrink
     // otherwise someone could cause SIGBUS on us.
@@ -188,6 +254,25 @@ bool QSharedMemoryPrivate::detach()
     // On non-QNX systems (tested Linux and Haiku), the st_nlink field is always 1,
     // so we'll simply leak the shared memory files.
     cleanHandle();
+
+#ifdef Q_OS_OPENHARMONY
+    const auto linkCounter = --(metaDataPtr->linkCounter);
+    if (linkCounter == 0) {
+        if (!unlinkSharedMemory(this->key)) {
+            setErrorString(QLatin1String("QSharedMemory::detach (shm unlink)"));
+        }
+
+        if (!unlinkSharedMemoryMetaData(this->key)) {
+            setErrorString(QLatin1String("QSharedMemory::detach (shm metadata unlink)"));
+        }
+    }
+
+    if (::munmap(metaDataPtr, sizeof(*metaDataPtr)) == -1) {
+        setErrorString(QLatin1String("QSharedMemory::detach (metadata munmap)"));
+        return false;
+    }
+#endif
+
 #endif
 
     return true;
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 52f6f4409b9..8c021ddbb82 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -154,7 +154,7 @@ inline void QFactoryLoaderPrivate::updateSinglePath(const QString &path)
     QDirIterator plugins(path,
 #if defined(Q_OS_WIN)
                 QStringList(QStringLiteral("*.dll")),
-#elif defined(Q_OS_ANDROID)
+#elif defined(Q_OS_ANDROID) || defined(Q_OS_OPENHARMONY)
                 QStringList("libplugins_%1_*.so"_L1.arg(suffix)),
 #endif
                 QDir::Files);
@@ -241,7 +241,7 @@ void QFactoryLoader::update()
 
     const QStringList paths = QCoreApplication::libraryPaths();
     for (const QString &pluginDir : paths) {
-#ifdef Q_OS_ANDROID
+#if defined(Q_OS_ANDROID) || defined(Q_OS_OPENHARMONY)
         QString path = pluginDir;
 #else
         QString path = pluginDir + d->suffix;
@@ -299,7 +299,7 @@ QFactoryLoader::QFactoryLoader(const char *iid,
 #if QT_CONFIG(library)
     d->cs = cs;
     d->suffix = suffix;
-# ifdef Q_OS_ANDROID
+#if defined(Q_OS_ANDROID) || defined(Q_OS_OPENHARMONY)
     if (!d->suffix.isEmpty() && d->suffix.at(0) == u'/')
         d->suffix.remove(0, 1);
 # endif
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
index c6341199c9c..7c10721aeae 100644
--- a/src/corelib/plugin/qpluginloader.cpp
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -249,7 +249,7 @@ static QString locatePlugin(const QString& fileName)
     for (const QString &path : std::as_const(paths)) {
         for (const QString &prefix : std::as_const(prefixes)) {
             for (const QString &suffix : std::as_const(suffixes)) {
-#ifdef Q_OS_ANDROID
+#if defined(Q_OS_ANDROID) || defined(Q_OS_OPENHARMONY)
                 {
                     QString pluginPath = basePath + prefix + baseName + suffix;
                     const QString fn = path + "/lib"_L1 + pluginPath.replace(u'/', u'_');
diff --git a/src/corelib/text/qlocale_harmony.cpp b/src/corelib/text/qlocale_harmony.cpp
new file mode 100644
index 00000000000..7d48d3efb85
--- /dev/null
+++ b/src/corelib/text/qlocale_harmony.cpp
@@ -0,0 +1,273 @@
+#include "qvariant.h"
+#include "qlocale_p.h"
+#include "qdatetime.h"
+#include "qstringlist.h"
+#include "qreadwritelock.h"
+#include "qstringbuilder.h"
+#include "qcoreapplication.h"
+
+#include "qjsmodule.h"
+#include "qopenharmonydefines.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SYSTEMLOCALE
+struct QSystemLocaleData
+{
+    QSystemLocaleData()
+        : lc_numeric(QLocale::C)
+          , lc_time(QLocale::C)
+          , lc_monetary(QLocale::C)
+          , lc_messages(QLocale::C)
+          , m_ohSystemi18n(nullptr)
+          , m_inited{ false }
+    {
+        readEnvironment();
+    }
+
+    void readEnvironment();
+
+    QReadWriteLock lock;
+
+    QLocale lc_numeric;
+    QLocale lc_time;
+    QLocale lc_monetary;
+    QLocale lc_messages;
+    QByteArray lc_messages_var;
+    QByteArray lc_measurement_var;
+    QByteArray lc_collate_var;
+    QStringList uiLanguages;
+    QAtomicInteger<bool> m_inited;
+    QScopedPointer<QJsObject> m_ohSystemi18n;
+};
+
+void QSystemLocaleData::readEnvironment()
+{
+    QWriteLocker locker(&lock);
+    QtOh::runOnJsUIThreadAndWait([this]{
+        if (m_ohSystemi18n.isNull()) {
+            QJsModule module("@ohos.i18n");
+            Napi::Value value = module.get("System");
+            m_ohSystemi18n.reset(new QJsObject(value.As<Napi::Object>()));
+        }
+
+        Napi::Value value = m_ohSystemi18n->call("getSystemLocale");
+        QString tmpAll("C");
+        if (!value.IsNull()) {
+            std::string str = value.ToString();
+            tmpAll = QString::fromStdString(str);
+        }
+
+        QString tmpLanguage("C");
+        value = m_ohSystemi18n->call("getSystemLanguage");
+        if (!value.IsNull()) {
+            std::string str = value.ToString();
+            tmpLanguage = QString::fromStdString(str);
+        }
+
+        QByteArray all = tmpAll.toLocal8Bit();
+        QByteArray language = tmpLanguage.toLocal8Bit();
+
+        QByteArray numeric  = all.isEmpty() ? language : all;
+        QByteArray time     = all.isEmpty() ? language : all;
+        QByteArray monetary = all.isEmpty() ? language : all;
+        lc_messages_var     = all.isEmpty() ? language : all;
+        lc_measurement_var  = all.isEmpty() ? language : all;
+        lc_collate_var      = all.isEmpty() ? language : all;
+        QByteArray lang = language;
+        if (lang.isEmpty())
+            lang = QByteArray("C");
+        if (numeric.isEmpty())
+            numeric = lang;
+        if (time.isEmpty())
+            time = lang;
+        if (monetary.isEmpty())
+            monetary = lang;
+        if (lc_messages_var.isEmpty())
+            lc_messages_var = lang;
+        if (lc_measurement_var.isEmpty())
+            lc_measurement_var = lang;
+        if (lc_collate_var.isEmpty())
+            lc_collate_var = lang;
+        lc_numeric = QLocale(QString::fromLatin1(numeric));
+        lc_time = QLocale(QString::fromLatin1(time));
+        lc_monetary = QLocale(QString::fromLatin1(monetary));
+        lc_messages = QLocale(QString::fromLatin1(lc_messages_var));
+    });
+    m_inited.storeRelease(true);
+}
+
+Q_GLOBAL_STATIC(QSystemLocaleData, qSystemLocaleData)
+#endif
+
+#ifndef QT_NO_SYSTEMLOCALE
+
+QLocale QSystemLocale::fallbackLocale() const
+{
+    QLocale locale(QLocale::C);
+    QtOh::runOnJsUIThreadAndWait([&locale]{
+        Napi::Value value = qSystemLocaleData()->m_ohSystemi18n->call("getSystemLocale");
+        QString lang = QString::fromStdString(std::string(value.As<Napi::String>()));
+        if (lang.isEmpty()) {
+            value = qSystemLocaleData()->m_ohSystemi18n->call("getSystemLanguage");
+            lang = QString::fromStdString(std::string(value.As<Napi::String>()));
+        }
+
+        if (lang.isEmpty()) {
+            value = qSystemLocaleData()->m_ohSystemi18n->call("getSystemRegion");
+            lang = QString::fromStdString(std::string(value.As<Napi::String>()));
+        }
+        // if the locale is the "C" locale, then we can return the language we found here:
+        if (lang.isEmpty() || lang == QLatin1String("C") || lang == QLatin1String("POSIX"))
+            locale = QLocale(lang);
+
+        value = qSystemLocaleData()->m_ohSystemi18n->call("getAppPreferredLanguage");
+        QString prefer = QString::fromStdString(std::string(value.As<Napi::String>()));
+        if (!prefer.isEmpty())
+            locale = QLocale(prefer);
+    });
+
+    return locale;
+}
+
+QVariant QSystemLocale::query(QueryType type, QVariant &&in) const
+{
+    QSystemLocaleData *d = qSystemLocaleData();
+
+    if (type == LocaleChanged) {
+        d->readEnvironment();
+        return QVariant();
+    }
+
+    if (!d->m_inited.loadAcquire())
+        d->readEnvironment();
+
+    QReadLocker locker(&d->lock);
+
+    const QLocale &lc_numeric = d->lc_numeric;
+    const QLocale &lc_time = d->lc_time;
+    const QLocale &lc_monetary = d->lc_monetary;
+    const QLocale &lc_messages = d->lc_messages;
+
+    switch (type) {
+    case DecimalPoint:
+        return lc_numeric.decimalPoint();
+    case GroupSeparator:
+        return lc_numeric.groupSeparator();
+    case ZeroDigit:
+        return lc_numeric.zeroDigit();
+    case NegativeSign:
+        return lc_numeric.negativeSign();
+    case DateFormatLong:
+        return lc_time.dateFormat(QLocale::LongFormat);
+    case DateFormatShort:
+        return lc_time.dateFormat(QLocale::ShortFormat);
+    case TimeFormatLong:
+        return lc_time.timeFormat(QLocale::LongFormat);
+    case TimeFormatShort:
+        return lc_time.timeFormat(QLocale::ShortFormat);
+    case DayNameLong:
+        return lc_time.dayName(in.toInt(), QLocale::LongFormat);
+    case DayNameShort:
+        return lc_time.dayName(in.toInt(), QLocale::ShortFormat);
+    case MonthNameLong:
+        return lc_time.monthName(in.toInt(), QLocale::LongFormat);
+    case MonthNameShort:
+        return lc_time.monthName(in.toInt(), QLocale::ShortFormat);
+    case StandaloneMonthNameLong:
+        return lc_time.standaloneMonthName(in.toInt(), QLocale::LongFormat);
+    case StandaloneMonthNameShort:
+        return lc_time.standaloneMonthName(in.toInt(), QLocale::ShortFormat);
+    case DateToStringLong:
+        return lc_time.toString(in.toDate(), QLocale::LongFormat);
+    case DateToStringShort:
+        return lc_time.toString(in.toDate(), QLocale::ShortFormat);
+    case TimeToStringLong:
+        return lc_time.toString(in.toTime(), QLocale::LongFormat);
+    case TimeToStringShort:
+        return lc_time.toString(in.toTime(), QLocale::ShortFormat);
+    case DateTimeFormatLong:
+        return lc_time.dateTimeFormat(QLocale::LongFormat);
+    case DateTimeFormatShort:
+        return lc_time.dateTimeFormat(QLocale::ShortFormat);
+    case DateTimeToStringLong:
+        return lc_time.toString(in.toDateTime(), QLocale::LongFormat);
+    case DateTimeToStringShort:
+        return lc_time.toString(in.toDateTime(), QLocale::ShortFormat);
+    case PositiveSign:
+        return lc_numeric.positiveSign();
+    case AMText:
+        return lc_time.amText();
+    case PMText:
+        return lc_time.pmText();
+    case FirstDayOfWeek:
+        return lc_time.firstDayOfWeek();
+    case CurrencySymbol:
+        return lc_monetary.currencySymbol(QLocale::CurrencySymbolFormat(in.toUInt()));
+    case CurrencyToString: {
+        switch (in.userType()) {
+        case QMetaType::Int:
+            return lc_monetary.toCurrencyString(in.toInt());
+        case QMetaType::UInt:
+            return lc_monetary.toCurrencyString(in.toUInt());
+        case QMetaType::Double:
+            return lc_monetary.toCurrencyString(in.toDouble());
+        case QMetaType::LongLong:
+            return lc_monetary.toCurrencyString(in.toLongLong());
+        case QMetaType::ULongLong:
+            return lc_monetary.toCurrencyString(in.toULongLong());
+        default:
+            break;
+        }
+        return QString();
+    }
+    case MeasurementSystem: {
+        const QString meas_locale = QString::fromLatin1(d->lc_measurement_var);
+        if (meas_locale.compare(QLatin1String("Metric"), Qt::CaseInsensitive) == 0)
+            return QLocale::MetricSystem;
+        if (meas_locale.compare(QLatin1String("Other"), Qt::CaseInsensitive) == 0)
+            return QLocale::MetricSystem;
+        return QVariant((int)QLocale(meas_locale).measurementSystem());
+    }
+    case Collation:
+        return QString::fromLatin1(d->lc_collate_var);
+    case UILanguages: {
+        if (!d->uiLanguages.isEmpty())
+            return d->uiLanguages;
+        QtOh::runOnJsUIThreadAndWait([d]{
+            Napi::Value value = qSystemLocaleData()->m_ohSystemi18n->call("getSystemLanguages");
+            Napi::Array lst = value.As<Napi::Array>();
+            if (lst.IsNull())
+                return;
+
+            for (uint32_t i = 0; i < lst.Length(); ++i) {
+                Napi::Value value = lst[i];
+                const QString &name = QString::fromStdString(std::string(value.As<Napi::String>()));
+                QStringView lang, script, cntry;
+                if (qt_splitLocaleName(name, &lang, &script, &cntry)) {
+                    if (!cntry.length())
+                        d->uiLanguages.append(lang.toString());
+                    else
+                        d->uiLanguages.append(lang.toString() % QLatin1Char('-') % cntry);
+                }
+            }
+            d->uiLanguages.removeDuplicates();
+        });
+        return d->uiLanguages.isEmpty() ? QVariant() : QVariant(d->uiLanguages);
+    }
+    case StringToStandardQuotation:
+        return lc_messages.quoteString(qvariant_cast<QStringView>(in));
+    case StringToAlternateQuotation:
+        return lc_messages.quoteString(qvariant_cast<QStringView>(in), QLocale::AlternateQuotation);
+    case ListToSeparatedString:
+        return lc_messages.createSeparatedList(in.toStringList());
+    case LocaleChanged:
+        Q_ASSERT(false);
+    default:
+        break;
+    }
+    return QVariant();
+}
+#endif // QT_NO_SYSTEMLOCALE
+
+QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 76f71c6dacd..da70fda4a83 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -272,7 +272,7 @@ void terminate_on_exception(T &&t)
 
 void *QThreadPrivate::start(void *arg)
 {
-#ifdef PTHREAD_CANCEL_DISABLE
+#if defined(PTHREAD_CANCEL_DISABLE) && !defined(Q_OS_OPENHARMONY)
     pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, nullptr);
 #endif
     pthread_cleanup_push(QThreadPrivate::finish, arg);
@@ -314,7 +314,7 @@ void *QThreadPrivate::start(void *arg)
 #endif
 
         emit thr->started(QThread::QPrivateSignal());
-#ifdef PTHREAD_CANCEL_DISABLE
+#if defined(PTHREAD_CANCEL_DISABLE) && !defined(Q_OS_OPENHARMONY)
         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, nullptr);
         pthread_testcancel();
 #endif
@@ -745,7 +745,7 @@ void QThread::start(Priority priority)
 
 void QThread::terminate()
 {
-#if !defined(Q_OS_ANDROID)
+#if !defined(Q_OS_ANDROID) && !defined(Q_OS_OPENHARMONY)
     Q_D(QThread);
     QMutexLocker locker(&d->mutex);
 
@@ -788,7 +788,7 @@ void QThread::setTerminationEnabled(bool enabled)
                "Current thread was not started with QThread.");
 
     Q_UNUSED(thr);
-#if defined(Q_OS_ANDROID)
+#if defined(Q_OS_ANDROID) || defined(Q_OS_OPENHARMONY)
     Q_UNUSED(enabled);
 #else
     pthread_setcancelstate(enabled ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE, nullptr);
diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp
index 0544dc10df9..bdfc507bb9e 100644
--- a/src/corelib/time/qtimezone.cpp
+++ b/src/corelib/time/qtimezone.cpp
@@ -33,6 +33,8 @@ static QTimeZonePrivate *newBackendTimeZone()
     return new QMacTimeZonePrivate();
 #elif defined(Q_OS_ANDROID)
     return new QAndroidTimeZonePrivate();
+#elif defined(Q_OS_OPENHARMONY)
+    return new QOhTimeZonePrivate();
 #elif defined(Q_OS_UNIX)
     return new QTzTimeZonePrivate();
 #elif QT_CONFIG(icu)
@@ -60,6 +62,8 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId)
     return new QMacTimeZonePrivate(ianaId);
 #elif defined(Q_OS_ANDROID)
     return new QAndroidTimeZonePrivate(ianaId);
+#elif defined(Q_OS_OPENHARMONY)
+    return new QOhTimeZonePrivate(ianaId);
 #elif defined(Q_OS_UNIX)
     return new QTzTimeZonePrivate(ianaId);
 #elif QT_CONFIG(icu)
diff --git a/src/corelib/time/qtimezoneprivate_openharmony.cpp b/src/corelib/time/qtimezoneprivate_openharmony.cpp
new file mode 100644
index 00000000000..3382b22fa80
--- /dev/null
+++ b/src/corelib/time/qtimezoneprivate_openharmony.cpp
@@ -0,0 +1,210 @@
+#include "qtimezone.h"
+#include "qdatetime.h"
+#include "qtimezoneprivate_p.h"
+#include <private/qopenharmony_p.h>
+#include <private/qjspromise_p.h>
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QOhTimeZonePrivate::QOhTimeZonePrivate(const QString &jsModuleName, const QTimeZonePrivate &parent)
+    : QTimeZonePrivate(parent), ohI18nModule(jsModuleName), ohTimeZone(nullptr)
+{
+}
+
+// Create the system default time zone
+QOhTimeZonePrivate::QOhTimeZonePrivate()
+    : QOhTimeZonePrivate(QString("@ohos.i18n"))
+{
+    m_id = QtOh::runOnJsUIThreadWithPromise<QByteArray>([this](auto p) {
+        QJsModule jsSystemDateTime("@ohos.systemDateTime");
+        QJsPromise promise(jsSystemDateTime.call("getTimezone").As<Napi::Promise>());
+        promise.onThen([this, p](const Napi::CallbackInfo &info){
+                   p->set_value(QByteArray::fromStdString(info[0].ToString()));
+               }).onCatch([this, p](const Napi::CallbackInfo &info) {
+                    p->set_value(QByteArray());
+                });
+    });
+}
+
+// Create a named time zone
+QOhTimeZonePrivate::QOhTimeZonePrivate(const QByteArray &ianaId)
+    : QOhTimeZonePrivate(QString("@ohos.i18n"))
+{
+    init(ianaId);
+}
+
+QOhTimeZonePrivate::QOhTimeZonePrivate(const QOhTimeZonePrivate &other)
+    : QOhTimeZonePrivate(QString("@ohos.i18n"), other)
+{
+    ohTimeZone.reset(new QJsObject(other.ohTimeZone.data()->object()));
+    m_id = other.id();
+}
+
+QOhTimeZonePrivate::~QOhTimeZonePrivate()
+{
+}
+
+void QOhTimeZonePrivate::init(const QByteArray &ianaId)
+{
+    QtOh::runOnJsUIThreadAndWait([=, this] {
+        const QString iana = QString::fromUtf8(ianaId);
+        Napi::Object timeZone =
+                ohI18nModule.call("getTimeZone", { Napi::String::New(QtOh::uiEnv(), iana.toStdString()) }).As<Napi::Object>();
+
+        if (timeZone.Has("getID")) {
+            QString timezoneId = QString::fromStdString(QJsObject(timeZone).call("getID").As<Napi::String>());
+            if (timezoneId != QStringLiteral("Etc/Unknown")) {
+                m_id = ianaId;
+                ohTimeZone.reset(new QJsObject(timeZone));
+            }
+        }
+    });
+}
+
+QOhTimeZonePrivate *QOhTimeZonePrivate::clone() const
+{
+    return new QOhTimeZonePrivate(*this);
+}
+
+
+QString QOhTimeZonePrivate::displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
+                                             const QLocale &locale) const
+{
+    Q_UNUSED(nameType);
+    Q_UNUSED(locale);
+
+    if(ohTimeZone.isNull())
+        return QString();
+
+    return QtOh::runOnJsUIThreadWithResult([=, this] {
+        bool daylightTime = (timeType == QTimeZone::DaylightTime);
+        return QString::fromStdString(ohTimeZone->call("getDisplayName",
+                                                      { Napi::Boolean::New(QtOh::uiEnv(), daylightTime) }).As<Napi::String>());
+    });
+}
+
+QString QOhTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
+{
+    if (isDaylightTime(atMSecsSinceEpoch))
+        return displayName(QTimeZone::DaylightTime, QTimeZone::ShortName, QLocale());
+    else
+        return displayName(QTimeZone::StandardTime, QTimeZone::ShortName, QLocale());
+}
+
+int QOhTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
+{
+    if (!ohTimeZone.isNull()) {
+        return QtOh::runOnJsUIThreadWithResult([=, this] {
+            return ohTimeZone->call("getOffset",
+                                  { Napi::Number::New(QtOh::uiEnv(), atMSecsSinceEpoch) })
+                           .As<Napi::Number>().Int32Value() / 1000;
+        });
+    } else {
+        return 0;
+    }
+}
+
+int QOhTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
+{
+    Q_UNUSED(atMSecsSinceEpoch);
+
+    if (!ohTimeZone.isNull()) {
+        return QtOh::runOnJsUIThreadWithResult([=, this] {
+            return ohTimeZone->call("getRawOffset").As<Napi::Number>().Int32Value() / 1000;
+        });
+    } else {
+        return 0;
+    }
+}
+
+int QOhTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const
+{
+    return (offsetFromUtc(atMSecsSinceEpoch) - standardTimeOffset(atMSecsSinceEpoch));
+}
+
+bool QOhTimeZonePrivate::hasDaylightTime() const
+{
+    // OpenHarmony没有接口直接判断,通过XXXX.1.1与XXXX.7.1的偏移是否相同来判断
+    if (!ohTimeZone.isNull()) {
+        int currentYear = QDateTime::currentDateTime().date().year();
+        QDate jan1(currentYear, 1, 1);
+        QDateTime jan1DateTime = QDateTime(jan1, QTime(0, 0, 0), Qt::UTC);
+        QDate jul1(currentYear, 7, 1);
+        QDateTime jul1DateTime = QDateTime(jul1, QTime(0, 0, 0), Qt::UTC);
+        qint64 jan1TimeStamp = jan1DateTime.toMSecsSinceEpoch();
+        qint64 jul1TimeStamp = jul1DateTime.toMSecsSinceEpoch();
+        return offsetFromUtc(jan1TimeStamp) != offsetFromUtc(jul1TimeStamp);
+    } else {
+        return false;
+    }
+}
+
+bool QOhTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
+{
+    if (!ohTimeZone.isNull()) {
+        return standardTimeOffset(atMSecsSinceEpoch) != offsetFromUtc(atMSecsSinceEpoch);
+    } else {
+        return false;
+    }
+}
+
+QTimeZonePrivate::Data QOhTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
+{
+    if (!ohTimeZone.isNull()) {
+        Data data;
+        data.atMSecsSinceEpoch = forMSecsSinceEpoch;
+        data.standardTimeOffset = standardTimeOffset(forMSecsSinceEpoch);
+        data.offsetFromUtc = offsetFromUtc(forMSecsSinceEpoch);
+        data.daylightTimeOffset = data.offsetFromUtc - data.standardTimeOffset;
+        data.abbreviation = abbreviation(forMSecsSinceEpoch);
+        return data;
+    } else {
+        return invalidData();
+    }
+}
+
+bool QOhTimeZonePrivate::hasTransitions() const
+{
+    //TODO:api20有接口可以实现
+    return false;
+}
+
+QTimeZonePrivate::Data QOhTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
+{
+    // transitions not available on OpenHarmony, so return an invalid data object
+    Q_UNUSED(afterMSecsSinceEpoch);
+    return invalidData();
+}
+
+QTimeZonePrivate::Data QOhTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
+{
+    // transitions not available on OpenHarmony, so return an invalid data object
+    Q_UNUSED(beforeMSecsSinceEpoch);
+    return invalidData();
+}
+
+QByteArray QOhTimeZonePrivate::systemTimeZoneId() const
+{
+    return m_id;
+}
+
+QList<QByteArray> QOhTimeZonePrivate::availableTimeZoneIds() const
+{
+    QList<QByteArray> availableTimeZoneIdList;
+
+    if (!ohTimeZone.isNull()) {
+        QtOh::runOnJsUIThreadAndWait([&] {
+            Napi::Array availableIDs = ohTimeZone->call("getAvailableIDs").As<Napi::Array>();
+            for (uint32_t i = 0; i < availableIDs.Length(); i++) {
+                availableTimeZoneIdList.append(
+                        QByteArray::fromStdString(availableIDs.Get(i).ToString()));
+            }
+        });
+    }
+
+    return availableTimeZoneIdList;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
index dac3471da01..3d49b3b3154 100644
--- a/src/corelib/time/qtimezoneprivate_p.h
+++ b/src/corelib/time/qtimezoneprivate_p.h
@@ -242,7 +242,7 @@ private:
 };
 #endif
 
-#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID)
+#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_OPENHARMONY)
 struct QTzTransitionTime
 {
     qint64 atMSecsSinceEpoch;
@@ -475,6 +475,54 @@ private:
 };
 #endif // Q_OS_ANDROID
 
+#if defined(Q_OS_OPENHARMONY)
+#include "qjsmodule.h"
+#include <QScopedPointer>
+
+class QOhTimeZonePrivate final : public QTimeZonePrivate
+{
+public:
+    // Create default time zone
+    QOhTimeZonePrivate();
+    // Create named time zone
+    QOhTimeZonePrivate(const QByteArray &ianaId);
+    QOhTimeZonePrivate(const QOhTimeZonePrivate &other);
+    // Delegate constructor
+    QOhTimeZonePrivate(const QString &jsModuleName, const QTimeZonePrivate &parent = QTimeZonePrivate());
+    ~QOhTimeZonePrivate();
+
+    QOhTimeZonePrivate *clone() const override;
+
+    QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
+                        const QLocale &locale) const override;
+    QString abbreviation(qint64 atMSecsSinceEpoch) const override;
+
+    int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
+    int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
+    int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
+
+    bool hasDaylightTime() const override;
+    bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
+
+    Data data(qint64 forMSecsSinceEpoch) const override;
+
+    bool hasTransitions() const override;
+    Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
+    Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
+
+    QByteArray systemTimeZoneId() const override;
+
+    QList<QByteArray> availableTimeZoneIds() const override;
+
+private:
+    void init(const QByteArray &zoneId);
+
+    QJsModule ohI18nModule;
+    QScopedPointer<QJsObject> ohTimeZone;
+};
+#endif // Q_OS_OPENHARMONY
+
+
 QT_END_NAMESPACE
 
 #endif // QTIMEZONEPRIVATE_P_H
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 8a8f66f263a..8302a3b4716 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -25,6 +25,8 @@ if (QT_FEATURE_gui)
         set(_default_platform "haiku")
     elseif(WASM)
         set(_default_platform "wasm")
+    elseif(OHOS)
+        set(_default_platform "openharmony")
     else()
         set(_default_platform "xcb")
     endif()
@@ -689,6 +691,22 @@ qt_internal_extend_target(Gui CONDITION UNIX AND NOT APPLE
         text/unix/qgenericunixfontdatabase_p.h
 )
 
+qt_internal_extend_target(Gui CONDITION UNIX AND OHOS
+    SOURCES
+        text/openharmony/qohfontdatabase_p.h
+        text/openharmony/qohfontdatabase.cpp
+        kernel/qplatformaccessctrl.h
+        kernel/qplatformaccessctrl.cpp
+        kernel/qplatformabilityctrl.h
+        kernel/qplatformabilityctrl.cpp
+        kernel/qohosabilityctrl.h
+        kernel/qohosabilityctrl.cpp
+        platform/openharmony/qohnativeinterface.cpp
+    LIBRARIES
+        native_drawing
+        hitrace_ndk.z
+)
+
 qt_internal_extend_target(Gui CONDITION QT_FEATURE_fontconfig AND QT_FEATURE_freetype AND UNIX AND NOT APPLE
     SOURCES
         text/unix/qfontconfigdatabase.cpp text/unix/qfontconfigdatabase_p.h
diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake
index a8a6e7775c0..87aa472e5e2 100644
--- a/src/gui/configure.cmake
+++ b/src/gui/configure.cmake
@@ -422,6 +422,7 @@ qt_config_compile_test(opengles3
     LABEL "OpenGL ES 3.0"
     LIBRARIES
         ${test_libs}
+        GLESv3
 # special case begin
     COMPILE_OPTIONS ${extra_compiler_options}
 # special case end
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index 6a36862a044..976921f9faf 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -141,6 +141,32 @@ QClipboard::QClipboard(QObject *parent)
 QClipboard::~QClipboard()
 {
 }
+#if defined(Q_OS_OPENHARMONY) && OHOS_SDK_VERSION >= 15
+void QClipboard::reportProgress()
+{
+    if (progressMode() == QClipboard::ProgressMode::Default)
+        return;
+
+    QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
+    clipboard->reportProgress();
+}
+
+void QClipboard::setProgressMode(ProgressMode mode)
+{
+    if (progressMode() == mode)
+        return;
+
+    QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
+    clipboard->setProgressMode(mode);
+    emit progressModeChanged(mode);
+}
+
+QClipboard::ProgressMode QClipboard::progressMode() const
+{
+    QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
+    return clipboard->progressMode();
+}
+#endif
 
 /*!
     \fn void QClipboard::changed(QClipboard::Mode mode)
diff --git a/src/gui/kernel/qclipboard.h b/src/gui/kernel/qclipboard.h
index 42b8bad0265..0bb09cffff4 100644
--- a/src/gui/kernel/qclipboard.h
+++ b/src/gui/kernel/qclipboard.h
@@ -25,6 +25,12 @@ private:
 
 public:
     enum Mode { Clipboard, Selection, FindBuffer, LastMode = FindBuffer };
+#if defined(Q_OS_OPENHARMONY) && OHOS_SDK_VERSION >= 15
+    enum ProgressMode { None, Default };
+    void reportProgress();
+    QClipboard::ProgressMode progressMode() const;
+    void setProgressMode(QClipboard::ProgressMode mode);
+#endif
 
     void clear(Mode mode = Clipboard);
 
@@ -52,6 +58,10 @@ Q_SIGNALS:
     void selectionChanged();
     void findBufferChanged();
     void dataChanged();
+#if defined(Q_OS_OPENHARMONY) && OHOS_SDK_VERSION >= 15
+    void progressValueChanged(int value);
+    void progressModeChanged(QClipboard::ProgressMode mode);
+#endif
 
 protected:
     friend class QApplication;
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 6e0867530d0..39b5dccdfcf 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -1867,6 +1867,22 @@ QCloseEvent::QCloseEvent()
 
 Q_IMPL_EVENT_COMMON(QCloseEvent)
 
+#ifdef Q_OS_OPENHARMONY
+#if OHOS_SDK_VERSION >= 15
+QCloseEvent::QCloseEvent(CloseReason reason)
+    : QEvent(Close)
+    , m_reason(reason)
+{
+
+}
+
+QCloseEvent::CloseReason QCloseEvent::closeReason() const
+{
+    return m_reason;
+}
+#endif
+#endif
+
 /*!
    \class QIconDragEvent
    \brief The QIconDragEvent class indicates that a main icon drag has begun.
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index a3fd09d9a4c..d4fd742618e 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -562,6 +562,23 @@ class Q_GUI_EXPORT QCloseEvent : public QEvent
     Q_DECL_EVENT_COMMON(QCloseEvent)
 public:
     QCloseEvent();
+
+#ifdef Q_OS_OPENHARMONY
+#if OHOS_SDK_VERSION >= 15
+    enum CloseReason {
+        UnKnown,
+        WindowClose,
+        AbilityClose,
+        InternalClose
+    };
+
+    QCloseEvent(CloseReason reason);
+    CloseReason closeReason() const;
+
+private:
+    CloseReason m_reason;
+#endif
+#endif
 };
 
 
@@ -593,7 +610,11 @@ class Q_GUI_EXPORT QContextMenuEvent : public QInputEvent
 {
     Q_DECL_EVENT_COMMON(QContextMenuEvent)
 public:
-    enum Reason { Mouse, Keyboard, Other };
+    enum Reason { Mouse, Keyboard, Other
+#ifdef Q_OS_OPENHARMONY
+                  , TouchScreen
+#endif
+    };
 
     QContextMenuEvent(Reason reason, const QPoint &pos, const QPoint &globalPos,
                       Qt::KeyboardModifiers modifiers = Qt::NoModifier);
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index b1e33fe5313..2a054310915 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -2210,6 +2210,13 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
         qWarning("QGuiApplicationPrivate::processMouseEvent: Got NaN in mouse position");
         return;
     }
+	
+#ifdef Q_OS_OPENHARMONY
+    if (e->buttonType == QEvent::MouseButtonPress) {
+        HiTracer tracer("QGuiApplicationPrivate::processMouseEvent DOWN");
+        qInfo("QGuiApplicationPrivate::processMouseEvent DOWN");
+    }
+#endif
 
     type = e->buttonType;
     button = e->button;
@@ -2735,11 +2742,24 @@ void QGuiApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::Cl
         e->eventAccepted = false;
         return;
     }
-
+#ifdef Q_OS_OPENHARMONY
+#if OHOS_SDK_VERSION >= 15
+    QCloseEvent event(e->reason);
+#else
     QCloseEvent event;
+#endif
+#else
+    QCloseEvent event;
+#endif
     QGuiApplication::sendSpontaneousEvent(e->window.data(), &event);
 
     e->eventAccepted = event.isAccepted();
+#ifdef Q_OS_OPENHARMONY
+#if OHOS_SDK_VERSION >= 15
+    if (e->resolve)
+        e->resolve(e->eventAccepted);
+#endif
+#endif
 }
 
 void QGuiApplicationPrivate::processFileOpenEvent(QWindowSystemInterfacePrivate::FileOpenEvent *e)
@@ -2910,7 +2930,11 @@ void QGuiApplicationPrivate::processContextMenuEvent(QWindowSystemInterfacePriva
     if (!e->window || e->mouseTriggered || e->window->d_func()->blockedByModalWindow)
         return;
 
+#ifdef Q_OS_OPENHARMONY
+    QContextMenuEvent ev(QContextMenuEvent::TouchScreen, e->pos, e->globalPos, e->modifiers);
+#else
     QContextMenuEvent ev(QContextMenuEvent::Keyboard, e->pos, e->globalPos, e->modifiers);
+#endif
     QGuiApplication::sendSpontaneousEvent(e->window.data(), &ev);
 }
 #endif
@@ -3732,6 +3756,13 @@ void QGuiApplicationPrivate::processApplicationTermination(QWindowSystemInterfac
     QEvent event(QEvent::Quit);
     QGuiApplication::sendSpontaneousEvent(QGuiApplication::instance(), &event);
     windowSystemEvent->eventAccepted = event.isAccepted();
+#ifdef Q_OS_OPENHARMONY
+#if OHOS_SDK_VERSION >= 15
+    if (windowSystemEvent->resolve) {
+        windowSystemEvent->resolve(event.isAccepted());
+    }
+#endif
+#endif
 }
 
 /*!
diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h
index 14bce88c62d..e54ed54fd28 100644
--- a/src/gui/kernel/qguiapplication.h
+++ b/src/gui/kernel/qguiapplication.h
@@ -161,6 +161,9 @@ Q_SIGNALS:
     QT_DEPRECATED_VERSION_X_6_0("Handle QEvent::ApplicationPaletteChange instead") void paletteChanged(const QPalette &pal);
     QT_DEPRECATED_VERSION_X_6_0("Handle QEvent::ApplicationFontChange instead")  void fontChanged(const QFont &font);
 #endif
+#ifdef Q_OS_OPENHARMONY
+    void newNativeWindowCreated(const QString &want);
+#endif
 protected:
     bool event(QEvent *) override;
     bool compressEvent(QEvent *, QObject *receiver, QPostEventList *) override;
diff --git a/src/gui/kernel/qohosabilityctrl.cpp b/src/gui/kernel/qohosabilityctrl.cpp
new file mode 100644
index 00000000000..6d49646fe02
--- /dev/null
+++ b/src/gui/kernel/qohosabilityctrl.cpp
@@ -0,0 +1,30 @@
+#include "qohosabilityctrl.h"
+#include <qpa/qplatformintegration.h>
+#include "qguiapplication_p.h"
+#include "qplatformabilityctrl.h"
+
+void QtOhPrivate::startAbility(const QVariantMap &want, const QVariantMap &startOptions,
+                               const std::function<void(Napi::Value)> &resultHandler)
+{
+    QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
+    if (QPlatformAbilityCtrl *ctrl = pi->abilityCtrl()) {
+        ctrl->startAbility(want, startOptions, resultHandler);
+    }
+}
+
+void QtOhPrivate::startAbilityForResult(const QVariantMap &want, const QVariantMap &startOptions,
+                                        const std::function<void (Napi::Value,Napi::Value)> &resultHandler)
+{
+    QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
+    if (QPlatformAbilityCtrl *ctrl = pi->abilityCtrl()) {
+        ctrl->startAbilityForResult(want, startOptions, resultHandler);
+    }
+}
+
+void QtOhPrivate::terminateSelfWithResult(const QVariantMap &abilityResult)
+{
+    QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
+    if (QPlatformAbilityCtrl *ctrl = pi->abilityCtrl()) {
+        ctrl->terminateSelfWithResult(abilityResult);
+    }
+}
diff --git a/src/gui/kernel/qohosabilityctrl.h b/src/gui/kernel/qohosabilityctrl.h
new file mode 100644
index 00000000000..f438f142b54
--- /dev/null
+++ b/src/gui/kernel/qohosabilityctrl.h
@@ -0,0 +1,23 @@
+#ifndef QOHOSABILITYCTRL_H
+#define QOHOSABILITYCTRL_H
+
+#include <QtGui/qtguiglobal.h>
+#include <QVariantMap>
+
+QT_BEGIN_NAMESPACE
+namespace Napi {
+class Value;
+}
+namespace QtOhPrivate {
+
+Q_GUI_EXPORT void startAbility(const QVariantMap &want, const QVariantMap &startOptions,
+                               const std::function<void(Napi::Value)> &resultHandler);
+Q_GUI_EXPORT void startAbilityForResult(const QVariantMap &want, const QVariantMap &startOptions,
+                                        const std::function<void(Napi::Value, Napi::Value)> &resultHandler);
+Q_GUI_EXPORT void terminateSelfWithResult(const QVariantMap &abilityResult);
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QOHOSABILITYCTRL_H
diff --git a/src/gui/kernel/qplatformabilityctrl.cpp b/src/gui/kernel/qplatformabilityctrl.cpp
new file mode 100644
index 00000000000..0edc1a376b7
--- /dev/null
+++ b/src/gui/kernel/qplatformabilityctrl.cpp
@@ -0,0 +1,5 @@
+#include "qplatformabilityctrl.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformabilityctrl.h b/src/gui/kernel/qplatformabilityctrl.h
new file mode 100644
index 00000000000..58b334c0ed6
--- /dev/null
+++ b/src/gui/kernel/qplatformabilityctrl.h
@@ -0,0 +1,28 @@
+#ifndef QPLATFORMABILITYCTRL_H
+#define QPLATFORMABILITYCTRL_H
+
+#include <QtGui/qtguiglobal.h>
+#include <QVariantMap>
+namespace Napi {
+class Value;
+}
+
+QT_BEGIN_NAMESPACE
+
+
+class Q_GUI_EXPORT QPlatformAbilityCtrl
+{
+public:
+    virtual void startAbility(const QVariantMap &want, const QVariantMap &startOptions,
+                              const std::function<void (Napi::Value)> &resultHandler) = 0;
+
+    virtual void startAbilityForResult(const QVariantMap &want, const QVariantMap &startOptions,
+                                       const std::function<void(Napi::Value, Napi::Value)> &resultHandler) = 0;
+
+    virtual void terminateSelfWithResult(const QVariantMap &abilityResult) = 0;
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QPLATFORMABILITYCTRL_H
diff --git a/src/gui/kernel/qplatformaccessctrl.cpp b/src/gui/kernel/qplatformaccessctrl.cpp
new file mode 100644
index 00000000000..a019b0a6ce1
--- /dev/null
+++ b/src/gui/kernel/qplatformaccessctrl.cpp
@@ -0,0 +1,122 @@
+#include <QDebug>
+#include <QThread>
+#include <QJsObject>
+#include <QSemaphore>
+#include <QCoreApplication>
+
+#include "qplatformaccessctrl.h"
+
+static bool waitForSemaphore(int timeoutMs, QSharedPointer<QSemaphore> sem)
+{
+    while (timeoutMs > 0) {
+        if (sem->tryAcquire(1, 10))
+            return true;
+        timeoutMs -= 10;
+        QCoreApplication::processEvents();
+    }
+    return false;
+}
+
+int QPlatformAccessCtrl::accessTokenId()
+{
+    int tokenId = -1;
+    QJsObject *bundleMgr = bundleManagerAcquire();
+    if (nullptr == bundleMgr) {
+        qWarning() << Q_FUNC_INFO << "bundle manager acquire faild.";
+        return tokenId;
+    }
+
+    QtOh::runOnJsUIThreadAndWait([&tokenId, bundleMgr]{
+        /* NOTE 0x00000001 参考BundleFlag
+         * https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V13/js-apis-bundlemanager-V13#bundleflag
+         */
+        Napi::Value result = bundleMgr->call("getBundleInfoForSelfSync", { Napi::Number::New(bundleMgr->env(), 0x00000001) });
+        Napi::Object bundleInfo = result.ToObject();
+        Napi::Value value = bundleInfo.Get("appInfo").As<Napi::Object>().Get("accessTokenId");
+        if (value.IsNull())
+            return;
+
+        tokenId = value.As<Napi::Number>();
+    });
+
+    return tokenId;
+}
+
+QPlatformAccessCtrl::~QPlatformAccessCtrl()
+{
+
+}
+
+int QPlatformAccessCtrl::checkPermission(const QString &permission)
+{
+    int tokenId = accessTokenId();
+    if (-1 == tokenId) {
+        qWarning() << Q_FUNC_INFO << "get accessTokenId failed.";
+        return -1;
+    }
+
+    QJsObject *atManager = atManagerAcquire();
+    if (nullptr == atManager) {
+        qWarning() << Q_FUNC_INFO << "abilityAccessCtrl acquire failed.";
+        return -1;
+    }
+
+    int retValue = -1;
+    QtOh::runOnJsUIThreadAndWait([&retValue, permission, tokenId, atManager]{
+        std::string stdPermission(permission.toStdString());
+        Napi::Value result = atManager->call("checkAccessTokenSync",
+                                             { Napi::Number::New(atManager->env(), tokenId),
+                                               Napi::String::New(atManager->env(), stdPermission) });
+        if (result.IsNull())
+            return;
+
+        retValue = result.As<Napi::Number>();
+    });
+
+    return retValue;
+}
+
+QtOhPrivate::PermissionRequestResult QPlatformAccessCtrl::requestPermissionsSync(const QStringList &permissions, int timeoutMs)
+{
+    QSharedPointer<QtOhPrivate::PermissionRequestResult> res(new QtOhPrivate::PermissionRequestResult());
+    QSharedPointer<QSemaphore> sem(new QSemaphore());
+    requestPermissions(permissions, [sem, res](const QtOhPrivate::PermissionRequestResult &result) {
+        *res = result;
+        sem->release();
+    });
+
+    if (waitForSemaphore(timeoutMs, sem))
+        return std::move(*res);
+    else
+        return QtOhPrivate::PermissionRequestResult();
+}
+
+QtOhPrivate::PermissionRequestResult QPlatformAccessCtrl::requestPermissionsOnSettingSync(const QStringList &permissions, int timeoutMs)
+{
+    QSharedPointer<QtOhPrivate::PermissionRequestResult> res(new QtOhPrivate::PermissionRequestResult());
+    QSharedPointer<QSemaphore> sem(new QSemaphore());
+    requestPermissionsOnSetting(permissions, [sem, res](const QtOhPrivate::PermissionRequestResult &result) {
+        *res = result;
+        sem->release();
+    });
+
+    if (waitForSemaphore(timeoutMs, sem))
+        return std::move(*res);
+    else
+        return QtOhPrivate::PermissionRequestResult();
+}
+
+bool QPlatformAccessCtrl::requestEnableNotificationSync(int timeoutMs)
+{
+    bool res = false;
+    QSharedPointer<QSemaphore> sem(new QSemaphore());
+    requestEnableNotification([sem, &res](bool result) {
+        res = result;
+        sem->release();
+    });
+
+    if (waitForSemaphore(timeoutMs, sem))
+        return res;
+    else
+        return false;
+}
diff --git a/src/gui/kernel/qplatformaccessctrl.h b/src/gui/kernel/qplatformaccessctrl.h
new file mode 100644
index 00000000000..842f90c4407
--- /dev/null
+++ b/src/gui/kernel/qplatformaccessctrl.h
@@ -0,0 +1,63 @@
+#ifndef QPLATFORMACCESSCTRL_H
+#define QPLATFORMACCESSCTRL_H
+
+#include <functional>
+#include <QSharedPointer>
+#include <QtGui/qtguiglobal.h>
+
+class QJsObject;
+QT_BEGIN_NAMESPACE
+
+namespace QtOhPrivate {
+enum class Q_GUI_EXPORT PermissionsResult {
+    Denied = -1,
+    Granted = 0,
+    InValidRequest = 2
+};
+
+struct Q_GUI_EXPORT PermissionRequestResult{
+    QStringList permissions;
+    QList<PermissionsResult> authResults;
+    QList<bool> dialogShownResults;
+
+    PermissionRequestResult() = default;
+    PermissionRequestResult(const QStringList& perms,
+                            const QList<PermissionsResult>& auth,
+                            const QList<bool>& dialogShown)
+        : permissions(perms), authResults(auth), dialogShownResults(dialogShown) {}
+};
+
+
+using PermissionsResultFunc = std::function<void(const PermissionRequestResult &)>;
+using enableNotificationFunc = std::function<void(bool)>;
+}
+
+class Q_GUI_EXPORT QPlatformAccessCtrl
+{
+public:
+    explicit QPlatformAccessCtrl() = default;
+    virtual ~QPlatformAccessCtrl();
+
+    virtual int checkPermission(const QString &permission);
+
+    QtOhPrivate::PermissionRequestResult requestPermissionsSync(const QStringList &permissions, int timeoutMs = INT_MAX);
+    QtOhPrivate::PermissionRequestResult requestPermissionsOnSettingSync(const QStringList &permissions, int timeoutMs = INT_MAX);
+    virtual void requestPermissions(const QStringList &permissions, const QtOhPrivate::PermissionsResultFunc &callbackFunc) = 0;
+    virtual void requestPermissionsOnSetting(const QStringList &permissions, const QtOhPrivate::PermissionsResultFunc &callbackFunc) = 0;
+
+    virtual void requestEnableNotification(const QtOhPrivate::enableNotificationFunc &callbackFunc) = 0;
+    virtual bool requestEnableNotificationSync(int timeoutMs = INT_MAX);
+    virtual bool isNotificationEnabled() = 0;
+    virtual void openNotificationSettings() = 0;
+protected:
+    int accessTokenId();
+    virtual QJsObject *atManagerAcquire() = 0;
+    virtual QJsObject *bundleManagerAcquire() = 0;
+    virtual QJsObject *notificationManagerAcquire() = 0;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QtOhPrivate::PermissionRequestResult)
+
+#endif // QPLATFORMACCESSCTRL_H
diff --git a/src/gui/kernel/qplatformclipboard.cpp b/src/gui/kernel/qplatformclipboard.cpp
index 7321b5065dc..91d6ef01437 100644
--- a/src/gui/kernel/qplatformclipboard.cpp
+++ b/src/gui/kernel/qplatformclipboard.cpp
@@ -88,7 +88,26 @@ void QPlatformClipboard::emitChanged(QClipboard::Mode mode)
     if (!QGuiApplicationPrivate::is_app_closing) // QTBUG-39317, prevent emission when closing down.
         QGuiApplication::clipboard()->emitChanged(mode);
 }
+#ifdef Q_OS_OPENHARMONY
+#if OHOS_SDK_VERSION >= 15
+void QPlatformClipboard::reportProgress()
+{
+#warning TODO Handle
+}
+
+QClipboard::ProgressMode QPlatformClipboard::progressMode() const
+{
+#warning TODO Handle
+    return QClipboard::ProgressMode::None;
+}
 
+void QPlatformClipboard::setProgressMode(QClipboard::ProgressMode mode)
+{
+#warning TODO Handle
+    Q_UNUSED(mode);
+}
+#endif
+#endif
 QT_END_NAMESPACE
 
 #endif //QT_NO_CLIPBOARD
diff --git a/src/gui/kernel/qplatformclipboard.h b/src/gui/kernel/qplatformclipboard.h
index 51b7c51abd3..8e92f8a9749 100644
--- a/src/gui/kernel/qplatformclipboard.h
+++ b/src/gui/kernel/qplatformclipboard.h
@@ -35,6 +35,13 @@ public:
     virtual bool supportsMode(QClipboard::Mode mode) const;
     virtual bool ownsMode(QClipboard::Mode mode) const;
     void emitChanged(QClipboard::Mode mode);
+#ifdef Q_OS_OPENHARMONY
+#if OHOS_SDK_VERSION >= 15
+    virtual void reportProgress();
+    virtual QClipboard::ProgressMode progressMode() const;
+    virtual void setProgressMode(QClipboard::ProgressMode mode);
+#endif
+#endif
 };
 
 QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h
index c2aeaeaaa67..17b81263c4c 100644
--- a/src/gui/kernel/qplatformdialoghelper.h
+++ b/src/gui/kernel/qplatformdialoghelper.h
@@ -375,6 +375,10 @@ public:
     virtual QString selectedMimeTypeFilter() const;
     virtual QString selectedNameFilter() const = 0;
 
+#ifdef Q_OS_OPENHARMONY
+    virtual QList<QUrl> selectedUris() const { return QList<QUrl>(); };
+#endif
+
     virtual bool isSupportedUrl(const QUrl &url) const;
 
     const QSharedPointer<QFileDialogOptions> &options() const;
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index c95742b34dd..80aed84b952 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -361,6 +361,18 @@ QPlatformAccessibility *QPlatformIntegration::accessibility() const
 
 #endif
 
+#ifdef Q_OS_OPENHARMONY
+QPlatformAccessCtrl *QPlatformIntegration::accessCtrl() const
+{
+    return nullptr;
+}
+
+QPlatformAbilityCtrl *QPlatformIntegration::abilityCtrl() const
+{
+    return nullptr;
+}
+#endif
+
 QVariant QPlatformIntegration::styleHint(StyleHint hint) const
 {
     switch (hint) {
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index 3d433957678..42412014716 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -68,7 +68,10 @@ template <typename R, typename I, typename... Args, R(I::*func)(Args...) const>
 struct QInterfaceProxy<func> : public QInterfaceProxyImp<R, I, func, Args...> {};
 
 } // QNativeInterface::Private
-
+#ifdef Q_OS_OPENHARMONY
+class QPlatformAccessCtrl;
+class QPlatformAbilityCtrl;
+#endif
 class Q_GUI_EXPORT QPlatformIntegration
 {
 public:
@@ -133,6 +136,11 @@ public:
     virtual QPlatformAccessibility *accessibility() const;
 #endif
 
+#ifdef Q_OS_OPENHARMONY
+    virtual QPlatformAccessCtrl *accessCtrl() const;
+    virtual QPlatformAbilityCtrl *abilityCtrl() const;    
+#endif
+
     // Access native handles. The window handle is already available from Wid;
     virtual QPlatformNativeInterface *nativeInterface() const;
 
diff --git a/src/gui/kernel/qplatformservices.cpp b/src/gui/kernel/qplatformservices.cpp
index 1c8062389d5..6321cc032d7 100644
--- a/src/gui/kernel/qplatformservices.cpp
+++ b/src/gui/kernel/qplatformservices.cpp
@@ -49,6 +49,14 @@ bool QPlatformServices::openDocument(const QUrl &url)
     return false;
 }
 
+#ifdef Q_OS_OPENHARMONY
+bool QPlatformServices::openUri(const QUrl &url, bool isDir){
+    qWarning("This plugin does not support QPlatformServices::openUri() for '%s'.",
+             qPrintable(url.toString()));
+    return false;
+}
+#endif
+
 /*!
  * \brief QPlatformServices::desktopEnvironment returns the active desktop environment.
  *
diff --git a/src/gui/kernel/qplatformservices.h b/src/gui/kernel/qplatformservices.h
index 063247af084..4215406f9a7 100644
--- a/src/gui/kernel/qplatformservices.h
+++ b/src/gui/kernel/qplatformservices.h
@@ -46,6 +46,10 @@ public:
     virtual bool openUrl(const QUrl &url);
     virtual bool openDocument(const QUrl &url);
 
+#ifdef Q_OS_OPENHARMONY
+    virtual bool openUri(const QUrl &url, bool isDir);
+#endif
+
     virtual QByteArray desktopEnvironment() const;
 
     virtual bool hasCapability(Capability capability) const;
diff --git a/src/gui/kernel/qplatformsystemtrayicon.cpp b/src/gui/kernel/qplatformsystemtrayicon.cpp
index 0b21fe39f7c..49c687c5561 100644
--- a/src/gui/kernel/qplatformsystemtrayicon.cpp
+++ b/src/gui/kernel/qplatformsystemtrayicon.cpp
@@ -143,6 +143,11 @@ QPlatformMenu *QPlatformSystemTrayIcon::createMenu() const
     return QGuiApplicationPrivate::platformTheme()->createPlatformMenu();
 }
 
+#ifdef Q_OS_OPENHARMONY
+void QPlatformSystemTrayIcon::updateIcon(const QIcon &iconLight, const QIcon &iconDark) {
+}
+#endif
+
 QT_END_NAMESPACE
 
 #include "moc_qplatformsystemtrayicon.cpp"
diff --git a/src/gui/kernel/qplatformsystemtrayicon.h b/src/gui/kernel/qplatformsystemtrayicon.h
index c2c80f9334b..e752993f09b 100644
--- a/src/gui/kernel/qplatformsystemtrayicon.h
+++ b/src/gui/kernel/qplatformsystemtrayicon.h
@@ -40,6 +40,9 @@ public:
 
     virtual void init() = 0;
     virtual void cleanup() = 0;
+#ifdef Q_OS_OPENHARMONY
+    virtual void updateIcon(const QIcon &iconLight, const QIcon &iconDark);
+#endif
     virtual void updateIcon(const QIcon &icon) = 0;
     virtual void updateToolTip(const QString &tooltip) = 0;
     virtual void updateMenu(QPlatformMenu *menu) = 0;
diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp
index aa879138f5f..29348318388 100644
--- a/src/gui/kernel/qplatformtheme.cpp
+++ b/src/gui/kernel/qplatformtheme.cpp
@@ -847,6 +847,17 @@ QString QPlatformTheme::removeMnemonics(const QString &original)
     returnText.truncate(finalDest);
     return returnText;
 }
+#ifdef Q_OS_OPENHARMONY
+bool QPlatformTheme::darkThemeEnabled() const
+{
+    return false;
+}
+
+void QPlatformTheme::setThemeColorMode(int colorMode)
+{
+    Q_UNUSED(colorMode);
+}
+#endif
 
 unsigned QPlatformThemePrivate::currentKeyPlatforms()
 {
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index dcc0c8e0224..24d9587db6e 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -319,7 +319,10 @@ public:
     static QString defaultStandardButtonText(int button);
     static QString removeMnemonics(const QString &original);
     QString name() const;
-
+#ifdef Q_OS_OPENHARMONY
+    virtual bool darkThemeEnabled() const;
+    virtual void setThemeColorMode(int colorMode);
+#endif
 protected:
     explicit QPlatformTheme(QPlatformThemePrivate *priv);
     QScopedPointer<QPlatformThemePrivate> d_ptr;
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index d1bbbe5c398..f42905a2cac 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -71,6 +71,18 @@ QPlatformScreen *QPlatformWindow::screen() const
     return scr ? scr->handle() : nullptr;
 }
 
+#ifdef Q_OS_OPENHARMONY
+/*!
+ * \brief obtain the size of xcomponent provided by the harmonyos window
+ * by default, return the size of the window.
+ * \return retur QSize
+ */
+QSize QPlatformWindow::xcomponentSize() const
+{
+    return windowGeometry().size();
+}
+#endif
+
 /*!
     Returns the actual surface format of the window.
 */
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index b6e96a457ef..75e04cb5449 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -48,7 +48,9 @@ public:
     QPlatformWindow *parent() const;
 
     QPlatformScreen *screen() const override;
-
+#ifdef Q_OS_OPENHARMONY
+    virtual QSize xcomponentSize() const;
+#endif
     virtual QSurfaceFormat format() const override;
 
     virtual void setGeometry(const QRect &rect);
diff --git a/src/gui/kernel/qplatformwindow_p.h b/src/gui/kernel/qplatformwindow_p.h
index 65b8b4a2c53..fad6204c1d0 100644
--- a/src/gui/kernel/qplatformwindow_p.h
+++ b/src/gui/kernel/qplatformwindow_p.h
@@ -122,6 +122,34 @@ protected:
 };
 #endif
 
+#if defined(Q_OS_OPENHARMONY)
+struct Q_GUI_EXPORT QOpenHarmonyWindow
+{
+    QT_DECLARE_NATIVE_INTERFACE(QOpenHarmonyWindow, 1, QWindow)
+
+    enum class NativeNodeRenderFit {
+        FIT_CENTER = 0,				/* 保持动画终态的内容大小,并且内容始终与组件保持中心对齐 */
+        FIT_TOP = 1,				/* 保持动画终态的内容大小,并且内容始终与组件保持顶部中心对齐 */
+        FIT_BOTTOM = 2,				/* 保持动画终态的内容大小,并且内容始终与组件保持底部中心对齐 */
+        FIT_LEFT = 3,				/* 保持动画终态的内容大小,并且内容始终与组件保持左侧对齐 */
+        FIT_RIGHT = 4,				/* 保持动画终态的内容大小,并且内容始终与组件保持右侧对齐 */
+        FIT_TOP_LEFT = 5,			/* 保持动画终态的内容大小,并且内容始终与组件保持左上角对齐 */
+        FIT_TOP_RIGHT = 6,			/* 保持动画终态的内容大小,并且内容始终与组件保持右上角对齐 */
+        FIT_BOTTOM_LEFT = 7,			/* 保持动画终态的内容大小,并且内容始终与组件保持左下角对齐 */
+        FIT_BOTTOM_RIGHT = 8,			/* 保持动画终态的内容大小,并且内容始终与组件保持右下角对齐 */
+        FIT_RESIZE_FILL = 9,			/* 不考虑动画终态内容的宽高比,并且内容始终缩放到组件的大小 */
+        FIT_RESIZE_CONTAIN = 10,		/* 保持动画终态内容的宽高比进行缩小或放大,使内容完整显示在组件内,且与组件保持中心对齐 */
+        FIT_RESIZE_CONTAIN_TOP_LEFT = 11,	/* 保持动画终态内容的宽高比进行缩小或放大,使内容完整显示在组件内。当组件宽方向有剩余时,内容与组件保持左侧对齐,当组件高方向有剩余时,内容与组件保持顶部对齐 */
+        FIT_RESIZE_CONTAIN_BOTTOM_RIGHT = 12,	/* 保持动画终态内容的宽高比进行缩小或放大,使内容完整显示在组件内。当组件宽方向有剩余时,内容与组件保持右侧对齐,当组件高方向有剩余时,内容与组件保持底部对齐 */
+        FIT_RESIZE_COVER = 13,			/* 保持动画终态内容的宽高比进行缩小或放大,使内容两边都大于或等于组件两边,且与组件保持中心对齐,显示内容的中间部分 */
+        FIT_RESIZE_COVER_TOP_LEFT = 14,	 	/* 保持动画终态内容的宽高比进行缩小或放大,使内容的两边都恰好大于或等于组件两边。当内容宽方向有剩余时,内容与组件保持左侧对齐,显示内容的左侧部分。当内容高方向有剩余时,内容与组件保持顶部对齐,显示内容的顶侧部分 */
+        FIT_RESIZE_COVER_BOTTOM_RIGHT = 15      /* 保持动画终态内容的宽高比进行缩小或放大,使内容的两边都恰好大于或等于组件两边。当内容宽方向有剩余时,内容与组件保持右侧对齐,显示内容的右侧部分。当内容高方向有剩余时,内容与组件保持底部对齐,显示内容的底侧部分 */
+    };
+    inline static constexpr const char* NativeNodeFitIdentifier = "nativenoderenderfit";
+    virtual void setNativeNodeRenderFit(QOpenHarmonyWindow::NativeNodeRenderFit fit) = 0;
+};
+#endif
+
 } // QNativeInterface::Private
 
 QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index a0efdb447dc..aa189ed3fce 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1899,6 +1899,9 @@ void QWindow::setFramePosition(const QPoint &point)
 */
 void QWindow::setPosition(const QPoint &pt)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWindow::setPosition");
+#endif
     setGeometry(QRect(pt, size()));
 }
 
@@ -1952,6 +1955,9 @@ void QWindow::resize(int w, int h)
 */
 void QWindow::resize(const QSize &newSize)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWindow::resize (%dx%d)", newSize.width(), newSize.height());
+#endif
     Q_D(QWindow);
     d->positionPolicy = QWindowPrivate::WindowFrameExclusive;
     if (d->platformWindow) {
@@ -2999,8 +3005,10 @@ void QWindowPrivate::setCursor(const QCursor *newCursor)
         cursor = *newCursor;
         hasCursor = true;
     } else {
+#ifndef Q_OS_OPENHARMONY
         if (!hasCursor)
             return;
+#endif
         cursor = QCursor(Qt::ArrowCursor);
         hasCursor = false;
     }
@@ -3057,6 +3065,10 @@ void *QWindow::resolveInterface(const char *name, int revision) const
     QT_NATIVE_INTERFACE_RETURN_IF(QWaylandWindow, platformWindow);
 #endif
 
+#if defined(Q_OS_OPENHARMONY)
+    QT_NATIVE_INTERFACE_RETURN_IF(QOpenHarmonyWindow, platformWindow);
+#endif
+
     return nullptr;
 }
 
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 48dc5fe7f4e..fc3fd4de61f 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -276,6 +276,14 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleApplicationTermination)
         QWindowSystemInterfacePrivate::ApplicationTermination);
 }
 
+#if defined(Q_OS_OPENHARMONY) && OHOS_SDK_VERSION >= 15
+QT_DEFINE_QPA_EVENT_HANDLER(bool, handleApplicationTermination, std::function<void(bool)> resolve)
+{
+    return handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowSystemEvent, Delivery>(
+            QWindowSystemInterfacePrivate::ApplicationTermination, resolve);
+}
+#endif
+
 QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow *window, const QRect &newGeometry)
     : WindowSystemEvent(GeometryChange)
     , window(window)
@@ -345,6 +353,14 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleCloseEvent, QWindow *window)
     return handleWindowSystemEvent<QWindowSystemInterfacePrivate::CloseEvent, Delivery>(window);
 }
 
+#if defined(Q_OS_OPENHARMONY) && OHOS_SDK_VERSION >= 15
+QT_DEFINE_QPA_EVENT_HANDLER(bool, handleCloseEvent, QWindow *window, QCloseEvent::CloseReason reason, std::function<void(bool)> resolve)
+{
+    Q_ASSERT(window);
+    return handleWindowSystemEvent<QWindowSystemInterfacePrivate::CloseEvent, Delivery>(window, reason, resolve);
+}
+#endif
+
 /*!
 
 \a w == 0 means that the event is in global coords only, \a local will be ignored in this case
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index f7857e16fa0..2d0ddda42e2 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -176,6 +176,10 @@ public:
 
     template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
     static bool handleCloseEvent(QWindow *window);
+#if defined(Q_OS_OPENHARMONY) && OHOS_SDK_VERSION >= 15
+    template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
+    static bool handleCloseEvent(QWindow *window, QCloseEvent::CloseReason reason, std::function<void(bool)> resolve);
+#endif
 
     template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
     static void handleEnterEvent(QWindow *window, const QPointF &local = QPointF(), const QPointF& global = QPointF());
@@ -198,6 +202,10 @@ public:
 
     template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
     static bool handleApplicationTermination();
+#if defined(Q_OS_OPENHARMONY) && OHOS_SDK_VERSION >= 15
+    template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
+    static bool handleApplicationTermination(std::function<void(bool)> resolve);
+#endif
 
 #if QT_CONFIG(draganddrop)
     static QPlatformDragQtResponse handleDrag(QWindow *window, const QMimeData *dropData,
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
index 5aa4d17a1b7..f76b3bb4482 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -88,6 +88,15 @@ public:
         EventType type;
         int flags;
         bool eventAccepted;
+#ifdef Q_OS_OPENHARMONY
+#if OHOS_SDK_VERSION >= 15
+        using Resolve = std::function<void(bool)>;
+        explicit WindowSystemEvent(EventType t, Resolve r)
+            : type(t), flags(0), eventAccepted(true), resolve(r) { }
+
+        Resolve resolve { nullptr };
+#endif
+#endif
     };
 
     class CloseEvent : public WindowSystemEvent {
@@ -96,6 +105,14 @@ public:
             : WindowSystemEvent(Close), window(w)
             { }
         QPointer<QWindow> window;
+#ifdef Q_OS_OPENHARMONY
+#if OHOS_SDK_VERSION >= 15        
+        explicit CloseEvent(QWindow *w, QCloseEvent::CloseReason cr, Resolve r)
+            : WindowSystemEvent(Close, r), window(w), reason(cr)
+        { }
+        QCloseEvent::CloseReason reason = QCloseEvent::InternalClose;
+#endif
+#endif
     };
 
     class GeometryChangeEvent : public WindowSystemEvent {
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 586c19885ec..4c293e7f9e8 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -115,6 +115,9 @@ QWindow* QBackingStore::window() const
 
 void QBackingStore::beginPaint(const QRegion &region)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QBackingStore::beginPaint");
+#endif
     const qreal dpr = d_ptr->backingStoreDevicePixelRatio();
 
     if (d_ptr->highDpiBackingstore &&
@@ -154,6 +157,9 @@ void QBackingStore::beginPaint(const QRegion &region)
 */
 QPaintDevice *QBackingStore::paintDevice()
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QBackingStore::paintDevice");
+#endif
     QPaintDevice *device = handle()->paintDevice();
 
     if (QHighDpiScaling::isActive() && device->devType() == QInternal::Image)
@@ -172,6 +178,9 @@ QPaintDevice *QBackingStore::paintDevice()
 */
 void QBackingStore::endPaint()
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QBackingStore::endPaint");
+#endif
     if (paintDevice()->paintingActive())
         qWarning("QBackingStore::endPaint() called with active painter; did you forget to destroy it or call QPainter::end() on it?");
 
@@ -194,6 +203,9 @@ void QBackingStore::endPaint()
 */
 void QBackingStore::flush(const QRegion &region, QWindow *window, const QPoint &offset)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QBackingStore::flush");
+#endif
     QWindow *topLevelWindow = this->window();
 
     if (!window)
@@ -229,6 +241,9 @@ void QBackingStore::flush(const QRegion &region, QWindow *window, const QPoint &
 */
 void QBackingStore::resize(const QSize &size)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QBackingStore::resize");
+#endif
     d_ptr->size = size;
     const qreal factor = d_ptr->deviceIndependentToNativeFactor();
     handle()->resize(QHighDpi::scale(size, factor), QHighDpi::scale(d_ptr->staticContents, factor));
diff --git a/src/gui/painting/qcompositionfunctions.cpp b/src/gui/painting/qcompositionfunctions.cpp
index 46e1a812fcb..a8ee55db28b 100644
--- a/src/gui/painting/qcompositionfunctions.cpp
+++ b/src/gui/painting/qcompositionfunctions.cpp
@@ -487,7 +487,16 @@ inline static void comp_func_Clear_template(typename Ops::Type *dest, int length
     }
 }
 
-void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
+#ifndef OPENHARMONY_ALWAYS_INLINE
+    #ifdef Q_OS_OPENHARMONY
+        #define OPENHARMONY_ALWAYS_INLINE __attribute__((always_inline))
+    #else
+        #define OPENHARMONY_ALWAYS_INLINE
+    #endif
+#endif
+
+
+OPENHARMONY_ALWAYS_INLINE void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
 {
     comp_func_Clear_template<Argb32Operations>(dest, length, const_alpha);
 }
@@ -557,7 +566,7 @@ inline static void comp_func_Source_template(typename Ops::Type *Q_DECL_RESTRICT
     }
 }
 
-void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha)
+OPENHARMONY_ALWAYS_INLINE void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha)
 {
     comp_func_solid_Source_template<Argb32Operations>(dest, length, color, const_alpha);
 }
@@ -667,7 +676,7 @@ inline static void comp_func_SourceOver_template(typename Ops::Type *Q_DECL_REST
     }
 }
 
-void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha)
+OPENHARMONY_ALWAYS_INLINE void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha)
 {
     comp_func_solid_SourceOver_template<Argb32Operations>(dest, length, color, const_alpha);
 }
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index 1fceb83710b..b483f0135da 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -12,7 +12,16 @@
 
 QT_BEGIN_NAMESPACE
 
-void qt_memfill32(quint32 *dest, quint32 value, qsizetype count)
+#ifndef OPENHARMONY_ALWAYS_INLINE
+    #ifdef Q_OS_OPENHARMONY
+        #define OPENHARMONY_ALWAYS_INLINE __attribute__((always_inline))
+    #else
+        #define OPENHARMONY_ALWAYS_INLINE
+    #endif
+#endif
+
+
+OPENHARMONY_ALWAYS_INLINE void qt_memfill32(quint32 *dest, quint32 value, qsizetype count)
 {
     const int epilogueSize = count % 16;
 #if defined(Q_CC_GHS) || defined(Q_CC_MSVC)
@@ -764,7 +773,7 @@ void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer, int x, int
 }
 #endif
 
-void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, uint color, uint const_alpha)
+OPENHARMONY_ALWAYS_INLINE void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, uint color, uint const_alpha)
 {
     if ((const_alpha & qAlpha(color)) == 255) {
         qt_memfill32(destPixels, color, length);
@@ -1286,7 +1295,7 @@ void QT_FASTCALL convertRGBA8888ToARGB32PM_neon(uint *buffer, int count, const Q
     convertARGBToARGB32PM_neon<true>(buffer, buffer, count);
 }
 
-const uint *QT_FASTCALL fetchARGB32ToARGB32PM_neon(uint *buffer, const uchar *src, int index, int count,
+OPENHARMONY_ALWAYS_INLINE const uint *QT_FASTCALL fetchARGB32ToARGB32PM_neon(uint *buffer, const uchar *src, int index, int count,
                                                    const QList<QRgb> *, QDitherInfo *)
 {
     convertARGBToARGB32PM_neon<false>(buffer, reinterpret_cast<const uint *>(src) + index, count);
@@ -1335,7 +1344,7 @@ void QT_FASTCALL storeRGB32FromARGB32PM_neon(uchar *dest, const uint *src, int i
     convertARGBFromARGB32PM_neon<false,true>(d, src, count);
 }
 
-void QT_FASTCALL storeARGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+OPENHARMONY_ALWAYS_INLINE void QT_FASTCALL storeARGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
                                               const QList<QRgb> *, QDitherInfo *)
 {
     uint *d = reinterpret_cast<uint *>(dest) + index;
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index b9568ae64e0..81782ef8655 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1362,6 +1362,9 @@ void QRasterPaintEngine::fillPath(const QPainterPath &path, QSpanData *fillData)
 static void fillRect_normalized(const QRect &r, QSpanData *data,
                                 QRasterPaintEnginePrivate *pe)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("fillRect_normalized");
+#endif
     int x1, x2, y1, y2;
 
     bool rectClipped = true;
@@ -2095,6 +2098,9 @@ static inline const QRect toAlignedRect_positive(const QRectF &rect)
 */
 void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QRasterPaintEngine::drawImage");
+#endif
 #ifdef QT_DEBUG_DRAW
     qDebug() << " - QRasterPaintEngine::drawImage(), p=" <<  p << " image=" << img.size() << "depth=" << img.depth();
 #endif
diff --git a/src/gui/platform/openharmony/qohnativeinterface.cpp b/src/gui/platform/openharmony/qohnativeinterface.cpp
new file mode 100644
index 00000000000..f5826e16f1e
--- /dev/null
+++ b/src/gui/platform/openharmony/qohnativeinterface.cpp
@@ -0,0 +1,10 @@
+#include <qpa/qplatformwindow_p.h>
+#include <QtCore/private/qnativeinterface_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QNativeInterface::Private;
+
+QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QOpenHarmonyWindow);
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/openharmony/openharmony.pri b/src/gui/text/openharmony/openharmony.pri
new file mode 100644
index 00000000000..d2e6f760f33
--- /dev/null
+++ b/src/gui/text/openharmony/openharmony.pri
@@ -0,0 +1,7 @@
+HEADERS += \
+    $$PWD/qohfontdatabase_p.h
+
+SOURCES += \
+    $$PWD/qohfontdatabase.cpp
+
+LIBS += -lnative_drawing
diff --git a/src/gui/text/openharmony/qohfontdatabase.cpp b/src/gui/text/openharmony/qohfontdatabase.cpp
new file mode 100644
index 00000000000..8ca0cc5d288
--- /dev/null
+++ b/src/gui/text/openharmony/qohfontdatabase.cpp
@@ -0,0 +1,313 @@
+#include "qohfontdatabase_p.h"
+#include <native_drawing/drawing_text_font_descriptor.h>
+#include <native_drawing/drawing_text_typography.h>
+#include <private/qfontengine_ft_p.h>
+#include <ft2build.h>
+#include <QtCore/QFile>
+#include FT_TRUETYPE_TABLES_H
+#include FT_ERRORS_H
+
+class QOhFontDatabasePrivate
+{
+    Q_DECLARE_PUBLIC(QOhFontDatabase)
+public:
+    QOhFontDatabasePrivate()
+    {
+        auto fontconfig = OH_Drawing_GetSystemFontConfigInfo(nullptr);
+        if (fontconfig) {
+            m_defaultFontFamily = QString::fromUtf8(fontconfig->fontGenericInfoSet->familyName);
+            m_fallbackFontFamily = QString::fromUtf8(fontconfig->fallbackGroupSet->fallbackInfoSet->familyName);
+            OH_Drawing_DestroySystemFontConfigInfo(fontconfig);
+        }
+    }
+
+    void initFontDatabaseByType(OH_Drawing_SystemFontType type);
+
+    ~QOhFontDatabasePrivate()
+    {
+
+    }
+    QFont defaultFont() const
+    {
+        return m_defaultFontFamily.isEmpty() ? QFont()
+        : QFont(m_defaultFontFamily, 12, QFont::Normal);
+    }
+
+private:
+    QOhFontDatabase *q_ptr;
+    mutable QHash<QPlatformTheme::Font, QFont> m_themeFonts;
+    QHash<OH_Drawing_SystemFontType, QStringList> m_systemFontFamilies;
+    QString m_defaultFontFamily;
+    QString m_fallbackFontFamily;
+};
+
+QOhFontDatabase::QOhFontDatabase()
+    : QGenericUnixFontDatabase(),
+      m_d(new QOhFontDatabasePrivate())
+{
+    m_d->q_ptr = this;
+}
+
+QOhFontDatabase::~QOhFontDatabase()
+{
+
+}
+
+QString QOhFontDatabase::fontDir() const
+{
+    QString dir = QGenericUnixFontDatabase::fontDir();
+    auto fontconfig = OH_Drawing_GetSystemFontConfigInfo(nullptr);
+    if (fontconfig) {
+        if (fontconfig->fontDirSize > 0) {
+            dir = QString::fromUtf8(fontconfig->fontDirSet[0]);
+        }
+        OH_Drawing_DestroySystemFontConfigInfo(fontconfig);
+    }
+    return dir;
+}
+
+void QOhFontDatabasePrivate::initFontDatabaseByType(OH_Drawing_SystemFontType type)
+{
+    std::unique_ptr<::OH_Drawing_Array, decltype(&::OH_Drawing_DestroySystemFontFullNames)> drawingArray(::OH_Drawing_GetSystemFontFullNamesByType(type),
+                                                                                                         ::OH_Drawing_DestroySystemFontFullNames);
+
+    qsizetype size = ::OH_Drawing_GetDrawingArraySize(drawingArray.get());
+    for (qsizetype i = 0; i < size; i++) {
+        auto drawingString = ::OH_Drawing_GetSystemFontFullNameByIndex(drawingArray.get(), i);
+        std::unique_ptr<::OH_Drawing_FontDescriptor, decltype(&::OH_Drawing_DestroyFontDescriptor)> descriptor(::OH_Drawing_GetFontDescriptorByFullName(drawingString, (::OH_Drawing_SystemFontType)type),
+                                                                                                               ::OH_Drawing_DestroyFontDescriptor);
+        if (descriptor)
+        {
+            m_systemFontFamilies[type] << QOhFontDatabase::addFontFile(QByteArray(), descriptor->path);
+        }
+    }
+}
+
+bool isTTCFile(const QByteArray &fontData, const QByteArray &filePath) {
+    QByteArray header;
+    
+    if (!fontData.isEmpty()) {
+        if (fontData.size() >= 4) {
+            header = fontData.left(4);
+        }
+    } else {
+        QFile file(QString::fromUtf8(filePath));
+        if (file.open(QIODevice::ReadOnly) && file.size() >= 4) {
+            header = file.read(4);
+            file.close();
+        }
+    }
+    
+    if (header == QByteArray("ttcf", 4)) {
+        return true;
+    }
+    return false;
+}
+
+extern FT_Library qt_getFreetype();
+QStringList QOhFontDatabase::addFontFile(const QByteArray &fontData, const QByteArray &file)
+{
+    FT_Library library = qt_getFreetype();
+    int index = 0;
+    int numFaces = 0;
+    QStringList families;
+
+    bool isTTC = isTTCFile(fontData, file);
+    do {
+        FT_Face face;
+        FT_Error error;
+        int faceIndex = index;
+        if (!isTTC && index > 0)
+            faceIndex = index << 16;
+        if (!fontData.isEmpty()) {
+            error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), faceIndex, &face);
+        } else {
+            error = FT_New_Face(library, file.constData(), faceIndex, &face);
+        }
+
+        if (error != FT_Err_Ok) {
+            qDebug() << "FT_New_Face failed with index" << index << "(faceIndex:" << faceIndex << "):" << Qt::hex << error;
+            break;
+        }
+        
+        if (faceIndex == 0) {
+            if (isTTC) {
+                numFaces = face->num_faces;
+            } else {
+                numFaces = (face->style_flags >> 16) & 0xFFFF;
+                numFaces += 1;
+            }
+        }
+
+        QFont::Weight weight = QFont::Normal;
+        QFont::Style style = QFont::StyleNormal;
+
+        if (face->style_flags & FT_STYLE_FLAG_ITALIC)
+            style = QFont::StyleItalic;
+        if (face->style_flags & FT_STYLE_FLAG_BOLD)
+            weight = QFont::Bold;
+
+        bool fixedPitch = (face->face_flags & FT_FACE_FLAG_FIXED_WIDTH);
+        QSupportedWritingSystems writingSystems;
+
+        // detect symbol fonts
+        for (int i = 0; i < face->num_charmaps; ++i) {
+            FT_CharMap cm = face->charmaps[i];
+            if (cm->encoding == FT_ENCODING_ADOBE_CUSTOM || cm->encoding == FT_ENCODING_MS_SYMBOL) {
+                writingSystems.setSupported(QFontDatabase::Symbol);
+                break;
+            }
+        }
+
+        QFont::Stretch stretch = QFont::Unstretched;
+        TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
+        if (os2) {
+            quint32 unicodeRange[4] = {
+                quint32(os2->ulUnicodeRange1),
+                quint32(os2->ulUnicodeRange2),
+                quint32(os2->ulUnicodeRange3),
+                quint32(os2->ulUnicodeRange4)
+            };
+            quint32 codePageRange[2] = {
+                quint32(os2->ulCodePageRange1),
+                quint32(os2->ulCodePageRange2)
+            };
+
+            writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+
+            if (os2->usWeightClass) {
+                weight = static_cast<QFont::Weight>(os2->usWeightClass);
+            } else if (os2->panose[2]) {
+                int w = os2->panose[2];
+                if (w <= 1)
+                    weight = QFont::Thin;
+                else if (w <= 2)
+                    weight = QFont::ExtraLight;
+                else if (w <= 3)
+                    weight = QFont::Light;
+                else if (w <= 5)
+                    weight = QFont::Normal;
+                else if (w <= 6)
+                    weight = QFont::Medium;
+                else if (w <= 7)
+                    weight = QFont::DemiBold;
+                else if (w <= 8)
+                    weight = QFont::Bold;
+                else if (w <= 9)
+                    weight = QFont::ExtraBold;
+                else if (w <= 10)
+                    weight = QFont::Black;
+            }
+
+            switch (os2->usWidthClass) {
+            case 1:
+                stretch = QFont::UltraCondensed;
+                break;
+            case 2:
+                stretch = QFont::ExtraCondensed;
+                break;
+            case 3:
+                stretch = QFont::Condensed;
+                break;
+            case 4:
+                stretch = QFont::SemiCondensed;
+                break;
+            case 5:
+                stretch = QFont::Unstretched;
+                break;
+            case 6:
+                stretch = QFont::SemiExpanded;
+                break;
+            case 7:
+                stretch = QFont::Expanded;
+                break;
+            case 8:
+                stretch = QFont::ExtraExpanded;
+                break;
+            case 9:
+                stretch = QFont::UltraExpanded;
+                break;
+            }
+        }
+
+        QString family = QString::fromUtf8(face->family_name);
+        QString styleName = QString::fromUtf8(face->style_name);
+
+        FontFile *fontFile = new FontFile;
+        fontFile->fileName = QFile::decodeName(file);
+        fontFile->indexValue = faceIndex;
+        registerFont(family, styleName, QString(), weight, style, stretch,
+                     true, true, 0, fixedPitch, writingSystems, fontFile);
+
+
+        families.append(family);
+
+        FT_Done_Face(face);
+        ++index;
+    } while (index < numFaces);
+
+    return families;
+}
+
+void QOhFontDatabase::populateFontDatabase()
+{
+    Q_D(QOhFontDatabase);
+    d->initFontDatabaseByType(OH_Drawing_SystemFontType::GENERIC);
+    d->initFontDatabaseByType(OH_Drawing_SystemFontType::STYLISH);
+    d->initFontDatabaseByType(OH_Drawing_SystemFontType::INSTALLED);
+}
+
+QStringList QOhFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
+{
+    QStringList result;
+    /*
+     * 从系统中获取通用字体
+     * 当前为 HarmonyOS Sans 字体
+     * 仅支持英文
+     * @since 14
+     */
+    Q_D(const QOhFontDatabase);
+    if (d->m_defaultFontFamily.isEmpty() && d->m_fallbackFontFamily.isEmpty()
+        && d->m_systemFontFamilies[OH_Drawing_SystemFontType::GENERIC].isEmpty())
+        return QGenericUnixFontDatabase::fallbacksForFamily(family, style, styleHint, script);
+    result << d->m_defaultFontFamily;
+    /*
+     * 从系统中获取备选字体
+     * 只有 HMOS Color Emoji 字体
+     * 仅支持英文
+     * @since 14
+     */
+    result << d->m_fallbackFontFamily;
+    /*
+     * 用系统字体作为备选字体,
+     * 风格字体与默认字体的风格可能存在较大差异,
+     * 不考虑风格字体作为备选字体
+     */
+    result << d->m_systemFontFamilies[OH_Drawing_SystemFontType::GENERIC];
+    return result;
+}
+
+QFont QOhFontDatabase::defaultFont() const
+{
+    Q_D(const QOhFontDatabase);
+    return d->defaultFont();
+}
+
+QFont QOhFontDatabase::themeFont(QPlatformTheme::Font) const
+{
+    /* Todo 根据类型创建字体 */
+    Q_D(const QOhFontDatabase);
+    return d->defaultFont();
+}
+
+const QHash<QPlatformTheme::Font, QFont> &QOhFontDatabase::themeFonts() const
+{
+    Q_D(const QOhFontDatabase);
+    if (d->m_themeFonts.isEmpty()) {
+        for (long f = QPlatformTheme::SystemFont; f < QPlatformTheme::NFonts; f++) {
+            QPlatformTheme::Font ft = static_cast<QPlatformTheme::Font>(f);
+            d->m_themeFonts.insert(ft, themeFont(ft));
+        }
+    }
+    return d->m_themeFonts;
+}
diff --git a/src/gui/text/openharmony/qohfontdatabase_p.h b/src/gui/text/openharmony/qohfontdatabase_p.h
new file mode 100644
index 00000000000..1322dba169a
--- /dev/null
+++ b/src/gui/text/openharmony/qohfontdatabase_p.h
@@ -0,0 +1,27 @@
+#ifndef QOHFONTDATABASE_P_H
+#define QOHFONTDATABASE_P_H
+#include <private/qgenericunixfontdatabase_p.h>
+#include <qpa/qplatformtheme.h>
+#include <QScopedPointer>
+#include <QStringList>
+class QOhFontDatabasePrivate;
+class Q_GUI_EXPORT QOhFontDatabase: public QGenericUnixFontDatabase
+{
+    Q_DECLARE_PRIVATE_D(m_d, QOhFontDatabase)
+public:
+    QOhFontDatabase();
+    ~QOhFontDatabase();
+    void populateFontDatabase() override;
+    QString fontDir() const override;
+    QFont defaultFont() const override;
+    QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const override;
+
+    // For OpenHarmony platform themes
+    QFont themeFont(QPlatformTheme::Font) const;
+    const QHash<QPlatformTheme::Font, QFont> &themeFonts() const;
+    static QStringList addFontFile(const QByteArray &fontData, const QByteArray &file);
+private:
+    QScopedPointer<QOhFontDatabasePrivate> m_d;
+};
+
+#endif // QOHFONTDATABASE_P_H
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index f7e405f0b5d..8a0264a0621 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -1820,7 +1820,16 @@ QString QFontMetricsF::elidedText(const QString &text, Qt::TextElideMode mode, q
         _text = _text.mid(posA);
     }
     QStackTextEngine engine(_text, QFont(d.data()));
-    return engine.elidedText(mode, QFixed::fromReal(width), flags);
+/*The default font of HarmonyOS allows for adjusting the spacing of ellipses*/
+#ifdef Q_OS_OPENHARMONY
+        QString str = engine.elidedText(mode, QFixed::fromReal(width), flags);
+        while (str.length() > 1 && boundingRect(str).width() > width) {
+            str.remove(str.length() - 2, 1);
+        }
+        return str;
+#else
+        return engine.elidedText(mode, QFixed::fromReal(width), flags);
+#endif
 }
 
 /*!
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index ae452885fc7..c1324549ee7 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -205,6 +205,32 @@ bool QDesktopServices::openUrl(const QUrl &url)
     return platformServices->openUrl(url);
 }
 
+#ifdef Q_OS_OPENHARMONY
+bool QDesktopServices::openUri(const QUrl &url, bool isDir)
+{
+    if (!url.isValid())
+        return false;
+
+    QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
+    if (Q_UNLIKELY(!platformIntegration)) {
+        QCoreApplication *application = QCoreApplication::instance();
+        if (Q_UNLIKELY(!application))
+            qWarning("QDesktopServices::openUrl: Please instantiate the QGuiApplication object "
+                     "first");
+        else if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(application)))
+            qWarning("QDesktopServices::openUrl: Application is not a GUI application");
+        return false;
+    }
+
+    QPlatformServices *platformServices = platformIntegration->services();
+    if (!platformServices) {
+        qWarning("The platform plugin does not support services.");
+        return false;
+    }
+    return platformServices->openUri(url, isDir);
+}
+#endif
+
 /*!
     Sets the handler for the given \a scheme to be the handler \a method provided by
     the \a receiver object.
diff --git a/src/gui/util/qdesktopservices.h b/src/gui/util/qdesktopservices.h
index 476b84691e6..32e031fc364 100644
--- a/src/gui/util/qdesktopservices.h
+++ b/src/gui/util/qdesktopservices.h
@@ -19,6 +19,9 @@ class Q_GUI_EXPORT QDesktopServices
 {
 public:
     static bool openUrl(const QUrl &url);
+#ifdef Q_OS_OPENHARMONY
+    static bool openUri(const QUrl &url, bool isDir = false);
+#endif
     static void setUrlHandler(const QString &scheme, QObject *receiver, const char *method);
     static void unsetUrlHandler(const QString &scheme);
 };
diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt
index 3283260c66a..c416e30652d 100644
--- a/src/network/CMakeLists.txt
+++ b/src/network/CMakeLists.txt
@@ -200,6 +200,11 @@ qt_internal_extend_target(Network CONDITION ANDROID AND QT_FEATURE_dnslookup
         kernel/qdnslookup_android.cpp
 )
 
+qt_internal_extend_target(Network CONDITION OHOS AND QT_FEATURE_dnslookup
+    SOURCES
+        kernel/qdnslookup_openharmony.cpp
+)
+
 qt_internal_extend_target(Network CONDITION WIN32
     SOURCES
         kernel/qhostinfo_win.cpp
@@ -305,7 +310,7 @@ qt_internal_extend_target(Network CONDITION QT_FEATURE_localserver
         socket/qlocalsocket.cpp socket/qlocalsocket.h socket/qlocalsocket_p.h
 )
 
-qt_internal_extend_target(Network CONDITION INTEGRITY AND QT_FEATURE_localserver
+qt_internal_extend_target(Network CONDITION INTEGRITY AND OHOS AND QT_FEATURE_localserver
     SOURCES
         socket/qlocalserver_tcp.cpp
         socket/qlocalsocket_tcp.cpp
@@ -354,7 +359,7 @@ qt_internal_extend_target(Network CONDITION QT_FEATURE_ocsp AND QT_FEATURE_opens
         ssl/qocsp_p.h
 )
 
-qt_internal_extend_target(Network CONDITION QT_FEATURE_dnslookup AND UNIX AND NOT ANDROID
+qt_internal_extend_target(Network CONDITION QT_FEATURE_dnslookup AND UNIX AND NOT ANDROID AND NOT OHOS
     SOURCES
         kernel/qdnslookup_unix.cpp
 )
diff --git a/src/network/access/qnetworkaccessfilebackend.cpp b/src/network/access/qnetworkaccessfilebackend.cpp
index 2100c188a58..150989195d5 100644
--- a/src/network/access/qnetworkaccessfilebackend.cpp
+++ b/src/network/access/qnetworkaccessfilebackend.cpp
@@ -20,6 +20,9 @@ QStringList QNetworkAccessFileBackendFactory::supportedSchemes() const
             << QStringLiteral("qrc");
 #if defined(Q_OS_ANDROID)
     schemes << QStringLiteral("assets");
+#endif
+#if defined(Q_OS_OPENHARMONY)
+    schemes << QStringLiteral("rawfile");
 #endif
     return schemes;
 }
@@ -43,6 +46,9 @@ QNetworkAccessFileBackendFactory::create(QNetworkAccessManager::Operation op,
     if (url.scheme().compare("qrc"_L1, Qt::CaseInsensitive) == 0
 #if defined(Q_OS_ANDROID)
             || url.scheme().compare("assets"_L1, Qt::CaseInsensitive) == 0
+#endif
+#if defined(Q_OS_OPENHARMONY)
+            || url.scheme().compare("rawfile"_L1, Qt::CaseInsensitive) == 0
 #endif
             || url.isLocalFile()) {
         return new QNetworkAccessFileBackend;
@@ -103,6 +109,11 @@ void QNetworkAccessFileBackend::open()
             if (url.scheme() == "assets"_L1)
                 fileName = "assets:"_L1 + url.path();
             else
+#endif
+#if defined(Q_OS_OPENHARMONY)
+            if (url.scheme() == "rawfile"_L1)
+                fileName = "rawfile"_L1 + url.path();
+            else
 #endif
                 fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery);
         }
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index b83f2561d38..b903c187130 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -1152,6 +1152,9 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
         if (isLocalFile
 #ifdef Q_OS_ANDROID
             || scheme == "assets"_L1
+#endif
+#ifdef Q_OS_OPENHARMONY
+            || scheme == "rawfile"_L1
 #endif
             || scheme == "qrc"_L1) {
             return new QNetworkReplyFileImpl(this, req, op);
diff --git a/src/network/access/qnetworkreplyfileimpl.cpp b/src/network/access/qnetworkreplyfileimpl.cpp
index 7d2ba390691..c0a0153823e 100644
--- a/src/network/access/qnetworkreplyfileimpl.cpp
+++ b/src/network/access/qnetworkreplyfileimpl.cpp
@@ -78,6 +78,11 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, con
             if (scheme == "assets"_L1)
                 fileName = "assets:"_L1 + url.path();
             else
+#endif
+#if defined(Q_OS_OPENHARMONY)
+			if (scheme == "rawfile"_L1)
+            	fileName = "rawfile:"_L1 + url.path();
+            else
 #endif
                 fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery);
         }
diff --git a/src/network/kernel/qdnslookup_openharmony.cpp b/src/network/kernel/qdnslookup_openharmony.cpp
new file mode 100644
index 00000000000..7bd9ed578d6
--- /dev/null
+++ b/src/network/kernel/qdnslookup_openharmony.cpp
@@ -0,0 +1,46 @@
+#include "qdnslookup_p.h"
+
+#include "qjsmodule.h"
+#include <private/qopenharmony_p.h>
+#include <private/qjspromise_p.h>
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName,
+                               const QHostAddress &nameserver, QDnsLookupReply *reply)
+{
+    Q_UNUSED(requestType);
+    Q_UNUSED(nameserver);
+
+    QtOh::runOnJsUIThreadWithPromise<bool>([requestName, &reply](auto p) {
+        QJsModule jsNetMoudle("@ohos.net.connection");
+        QJsPromise promise(jsNetMoudle.call(
+                "getAddressesByName", { Napi::String::New(QtOh::uiEnv(), requestName.data()) }).As<Napi::Promise>());
+        promise.onThen([p, requestName, &reply](const Napi::CallbackInfo &info) {
+                   Napi::Object netAddress = info[0].As<Napi::Object>();
+                   QString address = QString::fromStdString(netAddress.Get("address").ToString());
+                   int family = netAddress.Get("family").ToNumber().Int32Value();
+                   int port = netAddress.Get("port").ToNumber().Int32Value();
+                   qWarning() << "getAddressesByName success:" << address << family << port << requestName.data();
+                   QDnsHostAddressRecord record;
+                   record.d->value = QHostAddress(address);
+                   reply->hostAddressRecords.append(record);
+                   p->set_value(true);
+               })
+                .onCatch([p, requestName, &reply](const Napi::CallbackInfo &info) {
+                    Napi::Object error = info[0].As<Napi::Object>();
+                    Napi::Number code = error.Get("code").ToNumber();
+                    Napi::String message = error.Get("message").ToString();
+                    qWarning() << "getAddressesByName fail:" << code.Int32Value()
+                               << QString::fromStdString(message) <<  requestName.data();
+                    reply->error = QDnsLookup::ServerFailureError;
+                    reply->errorString = tr("Server failure");
+                    p->set_value(false);
+                    return;
+                });
+    });
+}
+
+QT_END_NAMESPACE
diff --git a/src/openharmony/CMakeLists.txt b/src/openharmony/CMakeLists.txt
new file mode 100644
index 00000000000..87a5aa7ce56
--- /dev/null
+++ b/src/openharmony/CMakeLists.txt
@@ -0,0 +1,17 @@
+#####################################################################
+## OpenHarmony Template Files:
+#####################################################################
+
+
+set(openharmony_template_dirs
+    abilitystage
+    entryability
+    pages
+)
+
+foreach(dir IN LISTS openharmony_template_dirs)
+    qt_copy_or_install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/
+        DESTINATION openharmony/qtbase/${dir}/
+        FILES_MATCHING PATTERN "*.ts" PATTERN "*.ets"
+    )
+endforeach()
\ No newline at end of file
diff --git a/src/openharmony/abilitystage/MyAbilityStage.ets b/src/openharmony/abilitystage/MyAbilityStage.ets
new file mode 100644
index 00000000000..38ba6746063
--- /dev/null
+++ b/src/openharmony/abilitystage/MyAbilityStage.ets
@@ -0,0 +1,8 @@
+import { AbilityStage } from '@kit.AbilityKit';
+import qpa from 'libplugins_platforms_qopenharmony.so'
+
+export default class MyAbilityStage extends AbilityStage {
+  onCreate(): void {
+    qpa.attachAbilityStage(this);
+  }
+}
\ No newline at end of file
diff --git a/src/openharmony/entryability/EntryAbility.ets b/src/openharmony/entryability/EntryAbility.ets
new file mode 100644
index 00000000000..5b37164bb7b
--- /dev/null
+++ b/src/openharmony/entryability/EntryAbility.ets
@@ -0,0 +1,64 @@
+import AbilityConstant from '@ohos.app.ability.AbilityConstant';
+import UIAbility from '@ohos.app.ability.UIAbility';
+import Window from '@ohos.window'
+import Want from '@ohos.app.ability.Want';
+import qpa from 'libplugins_platforms_qopenharmony.so'
+import hilog from '@ohos.hilog';
+
+
+export default class EntryAbility extends UIAbility {
+  tag = "QtForOpenHarmony";
+  domain = 0xFF00;
+  private launchApplication = "libentry.so"
+  private launchParams = ""
+
+  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
+    super.onCreate(want, launchParam)
+  }
+
+  newLocalStorage() {
+    return new LocalStorage()
+  }
+
+  onDestroy() {
+    hilog.info(this.domain, this.tag, '%{public}s', 'Ability onDestroy');
+  }
+
+  onWindowStageCreate(windowStage: Window.WindowStage) {
+    // Main window is created, set main page for this ability
+    hilog.info(this.domain, this.tag, '%{public}s', 'Ability onWindowStageCreate');
+    this.launchParamSet();
+    qpa.startQtApplication(this);
+  }
+
+  async launchParamSet(){
+    let params:string[] = [];
+
+    //NOTE:应用启动参数在此处使用params.push添加
+    this.launchParams = params.join(' ');
+  }
+
+  onWindowStageDestroy() {
+    // Main window is destroyed, release UI related resources
+    hilog.info(this.domain, this.tag, '%{public}s', 'Ability onWindowStageDestroy');
+  }
+
+  onForeground() {
+    // Ability has brought to foreground
+    hilog.info(this.domain, this.tag, '%{public}s', 'Ability onForeground');
+  }
+
+  onBackground() {
+    // Ability has back to background
+    hilog.info(this.domain, this.tag, '%{public}s', 'Ability onBackground');
+  }
+
+  /**
+   * note:启动模式为singleton/specified才生效
+   * @param want
+   * @param launchParam
+   */
+  onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+    qpa.handleOnNewWant(want, launchParam);
+  }
+};
diff --git a/src/openharmony/entryability/EntryEmbeddedAbility.ets b/src/openharmony/entryability/EntryEmbeddedAbility.ets
new file mode 100644
index 00000000000..1c2f05c9de4
--- /dev/null
+++ b/src/openharmony/entryability/EntryEmbeddedAbility.ets
@@ -0,0 +1,51 @@
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { UIExtensionContentSession, Want } from '@kit.AbilityKit';
+import EmbeddedUIExtensionAbility from '@ohos.app.ability.EmbeddedUIExtensionAbility';
+import AbilityConstant from '@ohos.app.ability.AbilityConstant';
+import qpa from 'libplugins_platforms_qopenharmony.so'
+
+export default class EntryEmbeddedAbility extends EmbeddedUIExtensionAbility {
+  tag = "QtForOpenHarmony";
+  domain = 0x0000;
+  private name: string = "qt_entry_window"
+  private launchParams = ""
+  private launchApplication = "libentry.so"
+  private launchWant: Want  = {}
+  onCreate(launchParam: AbilityConstant.LaunchParam) {
+    hilog.info(this.domain, this.tag, '%{public}s', 'Ability onCreate');
+  }
+
+  onForeground() {
+    hilog.info(this.domain, this.tag, '%{public}s', 'Ability onForeground');
+  }
+
+  onBackground() {
+    hilog.info(this.domain, this.tag, '%{public}s', 'Ability onBackground');
+  }
+
+  onDestroy() {
+    hilog.info(this.domain, this.tag, '%{public}s', 'Ability onDestroy');
+  }
+
+  onSessionCreate(want: Want, session: UIExtensionContentSession) {
+    hilog.info(this.domain, this.tag, '%{public}s', 'Ability onSessionCreate');
+    this.launchWant = want;
+    this.launchParamSet();
+    qpa.startQtApplication(this, session);
+  }
+
+  newLocalStorage() {
+    return new LocalStorage();
+  }
+
+  async launchParamSet(){
+    let params:string[] = [];
+
+    //NOTE:应用启动参数在此处添加
+    this.launchParams = params.join(' ');
+  }
+  onSessionDestroy(session: UIExtensionContentSession) {
+    hilog.info(this.domain, this.tag, '%{public}s', 'Ability onSessionDestroy');
+  }
+};
+
diff --git a/src/openharmony/pages/Index.ets b/src/openharmony/pages/Index.ets
new file mode 100644
index 00000000000..d7163c54bc5
--- /dev/null
+++ b/src/openharmony/pages/Index.ets
@@ -0,0 +1,18 @@
+let storage = LocalStorage.getShared()
+
+@Entry(storage)
+@Component
+struct Index {
+  @LocalStorageProp("idName") windowId: string = "";
+
+  build() {
+    Stack({ alignContent: Alignment.TopStart }) {
+      XComponent({
+        id: this.windowId,
+        type: XComponentType.NODE,
+        libraryname: 'plugins_platforms_qopenharmony'
+      }).width('100%')
+        .height('100%')
+    }
+  }
+}
diff --git a/src/plugins/platforms/CMakeLists.txt b/src/plugins/platforms/CMakeLists.txt
index bcf29dedd10..885855a61c8 100644
--- a/src/plugins/platforms/CMakeLists.txt
+++ b/src/plugins/platforms/CMakeLists.txt
@@ -1,6 +1,9 @@
 # Copyright (C) 2022 The Qt Company Ltd.
 # SPDX-License-Identifier: BSD-3-Clause
 
+if(OHOS)
+    add_subdirectory(openharmony)
+endif()
 if(ANDROID)
     add_subdirectory(android)
 endif()
diff --git a/src/plugins/platforms/openharmony/CMakeLists.txt b/src/plugins/platforms/openharmony/CMakeLists.txt
new file mode 100644
index 00000000000..9ec4e4848e6
--- /dev/null
+++ b/src/plugins/platforms/openharmony/CMakeLists.txt
@@ -0,0 +1,224 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## QOhIntegrationPlugin Plugin:
+#####################################################################
+
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+set(JSCLASS_SOURCES
+    jsclass/qjsability.h
+    jsclass/qjsabilitystage.h
+    jsclass/qjsaccessmanager.h
+    jsclass/qjsdisplay.h
+    jsclass/qjsscreen.h
+    jsclass/qjsdeviceinfo.h
+    jsclass/qjsuiability.h
+    jsclass/qjsbasecontext.h
+    jsclass/qjscontext.h
+    jsclass/qjsapplicationcontext.h
+    jsclass/qjsuiabilitycontext.h
+    jsclass/qjsuiextensionability.h
+    jsclass/qjsuiextensioncontext.h
+    jsclass/qjsuiextensioncontextsession.h
+    jsclass/qjswant.h
+    jsclass/qjswindowproxy.h
+    jsclass/qjswindowstage.h
+    jsclass/qjscursor.h
+    jsclass/qjssettings.h
+    jsclass/qjsabilityinfo.h
+    jsclass/qjsabilityfactory.h
+    jsclass/qjsability.cpp
+    jsclass/qjsabilitystage.cpp
+    jsclass/qjsaccessmanager.cpp
+    jsclass/qjsdisplay.cpp
+    jsclass/qjsscreen.cpp
+    jsclass/qjsdeviceinfo.cpp
+    jsclass/qjsuiability.cpp
+    jsclass/qjsbasecontext.cpp
+    jsclass/qjscontext.cpp
+    jsclass/qjsapplicationcontext.cpp
+    jsclass/qjsuiabilitycontext.cpp
+    jsclass/qjsuiextensionability.cpp
+    jsclass/qjsuiextensioncontext.cpp
+    jsclass/qjsuiextensioncontextsession.cpp
+    jsclass/qjswant.cpp
+    jsclass/qjswindowproxy.cpp
+    jsclass/qjswindowstage.cpp
+    jsclass/qjscursor.cpp
+    jsclass/qjssettings.cpp
+    jsclass/qjsabilityinfo.cpp
+    jsclass/qjsabilityfactory.cpp
+)
+
+set(INPUTMETHOD_SOURCES
+    inputmethod/qohcontroller.h
+    inputmethod/qohtexteditorproxy.h
+    inputmethod/qohinputmethodproxy.h
+    inputmethod/qohinputmethod.h
+    inputmethod/qohattachoptions.h
+    inputmethod/qohcursorinfo.h
+    inputmethod/qohtextconfig.h
+    inputmethod/qohtextavoidinfo.h
+    inputmethod/qohcontroller.cpp
+    inputmethod/qohtexteditorproxy.cpp
+    inputmethod/qohinputmethodproxy.cpp
+    inputmethod/qohinputmethod.cpp
+    inputmethod/qohattachoptions.cpp
+    inputmethod/qohcursorinfo.cpp
+    inputmethod/qohtextconfig.cpp
+    inputmethod/qohtextavoidinfo.cpp
+)
+
+qt_internal_add_plugin(QOhIntegrationPlugin
+    OUTPUT_NAME qopenharmony
+    PLUGIN_TYPE platforms
+    DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES openharmony
+    SOURCES
+        qohplatformintegration.h
+        qohplatformwindow.h
+        qohplatformopenglwindow.h
+        qohplatformforeignwindow.h
+        qohplatformscreen.h
+        qohplatformbackingstore.h
+        qohxcomponent.h
+        qohnativewindowmanager.h
+        qohplatformopenglcontext.h
+        qoheventdispatcher.h
+        qohplatformoffscreensurface.h
+        qohmain.h
+        qohplatforminputcontext.h
+        qohplatformtheme.h
+        qohplatformdialoghelpers.h
+        qohfileenginehandler.h
+        qohnativewindow.h
+        qohjsonlistener.h
+        qohwindownode.h
+        qohwindownodeeventhandler.h
+        qohplatformservices.h
+        qohplatformcursor.h
+        qohplatformabilityctrl.h
+        qohplatformnativeinterface.h
+        qohevent.h
+        qohextensionwindow.h
+        qohnormalwindow.h
+        qohauxiliary.h
+        qohplatformmenu.h
+        qohobjectholder.h
+        qohnativenodeapi.h
+        qoharkui.h
+        qohwindowcontext.h
+        qohkeys.h
+        qohdesktopwindow.h
+        qohplatformplugin.cpp
+        qohplatformwindow.cpp
+        qohplatformintegration.cpp
+        qohplatformopenglwindow.cpp
+        qohplatformforeignwindow.cpp
+        qohplatformscreen.cpp
+        qohplatformbackingstore.cpp
+        qohplatformopenglcontext.cpp
+        qohplatformoffscreensurface.cpp
+        qohmain.cpp
+        qohxcomponent.cpp
+        qohnativewindowmanager.cpp
+        qoheventdispatcher.cpp
+        qohplatforminputcontext.cpp
+        qohplatformtheme.cpp
+        qohplatformdialoghelpers.cpp
+        qohfileenginehandler.cpp
+        qohnativewindow.cpp
+        qohjsonlistener.cpp
+        qohwindownode.cpp
+        qohwindownodeeventhandler.cpp
+        qohplatformservices.cpp
+        qohplatformcursor.cpp
+        qohplatformabilityctrl.cpp
+        qohplatformnativeinterface.cpp
+        qohextensionwindow.cpp
+        qohnormalwindow.cpp
+        qohauxiliary.cpp
+        qohplatformmenu.cpp
+        qohnativenodeapi.cpp
+        qoharkui.cpp
+        qohwindowcontext.cpp
+        qohkeys.cpp
+        qohdesktopwindow.cpp
+        arkui/qohdragevent.h
+        arkui/qohdragevent.cpp
+        ${INPUTMETHOD_SOURCES}
+        ${JSCLASS_SOURCES}
+    NO_UNITY_BUILD_SOURCES
+    INCLUDE_DIRECTORIES
+        jsclass
+        inputmethod
+        arkui
+    DEFINES
+        OHOS_PLATFORM
+    LIBRARIES
+        EGL::EGL
+        Qt::Core
+        Qt::CorePrivate
+        Qt::Gui
+        Qt::GuiPrivate
+        ace_napi.z ohfileuri ace_ndk.z rawfile.z native_window
+        udmf pixelmap pasteboard ohinput native_display_manager qos hitrace_ndk.z
+        native_drawing native_window_manager ohinputmethod native_vsync image_source
+        ohresmgr ohinputmethod
+)
+
+qt_internal_extend_target(QOhIntegrationPlugin CONDITION QT_FEATURE_vulkan
+    SOURCES
+        qohplatformvulkaninstance.h
+        qohplatformvulkaninstance.cpp
+)
+
+qt_internal_extend_target(QOhIntegrationPlugin CONDITION QT_FEATURE_systemtrayicon
+    SOURCES
+        qohsystemtrayicon.cpp qohsystemtrayicon.h
+)
+
+qt_internal_extend_target(QOhIntegrationPlugin CONDITION QT_FEATURE_clipboard
+    SOURCES
+        qohplatformclipboard.cpp qohplatformclipboard.h
+)
+
+qt_internal_extend_target(QOhIntegrationPlugin CONDITION QT_FEATURE_clipboard AND QT_FEATURE_draganddrop
+    SOURCES
+        qohdrag.cpp qohdrag.h
+)
+
+if(${OHOS_SDK_VERSION} GREATER 13)
+    qt_internal_extend_target(QOhIntegrationPlugin CONDITION QT_FEATURE_accessibility
+        SOURCES
+            accessibility/qohaccessibility.h
+            accessibility/qohplatformaccessibility.h
+            accessibility/qohaccessibilityprovider.h
+            accessibility/qohaccessiblenode.h
+            accessibility/qohaccessibility.cpp
+            accessibility/qohplatformaccessibility.cpp
+            accessibility/qohaccessibilityprovider.cpp
+            accessibility/qohaccessiblenode.cpp
+        INCLUDE_DIRECTORIES
+            accessibility
+    )
+    qt_internal_extend_target(QOhIntegrationPlugin
+        SOURCES
+            qohdisplay.h
+            qohdisplaymanager.h
+            qohdisplaylistener.h
+            qohdisplay.cpp
+            qohdisplaymanager.cpp
+            qohdisplaylistener.cpp
+    )
+endif()
+
+if(${OHOS_SDK_VERSION} GREATER 14)
+    qt_internal_extend_target(QOhIntegrationPlugin
+        SOURCES
+            qohnativevsync.h
+            qohnativevsync.cpp
+    )
+endif()
+
diff --git a/src/plugins/platforms/openharmony/accessibility/accessibility.pri b/src/plugins/platforms/openharmony/accessibility/accessibility.pri
new file mode 100644
index 00000000000..7758a1d97ce
--- /dev/null
+++ b/src/plugins/platforms/openharmony/accessibility/accessibility.pri
@@ -0,0 +1,13 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+    $$PWD/qohaccessibility.h \
+    $$PWD/qohplatformaccessibility.h \
+    $$PWD/qohaccessibilityprovider.h \
+    $$PWD/qohaccessiblenode.h
+
+SOURCES += \
+    $$PWD/qohaccessibility.cpp \
+    $$PWD/qohplatformaccessibility.cpp \
+    $$PWD/qohaccessibilityprovider.cpp \
+    $$PWD/qohaccessiblenode.cpp
diff --git a/src/plugins/platforms/openharmony/accessibility/qohaccessibility.cpp b/src/plugins/platforms/openharmony/accessibility/qohaccessibility.cpp
new file mode 100644
index 00000000000..80ce8cabb7d
--- /dev/null
+++ b/src/plugins/platforms/openharmony/accessibility/qohaccessibility.cpp
@@ -0,0 +1,299 @@
+#include "qohaccessibility.h"
+#include "qohaccessiblenode.h"
+#include "qohplatformwindow.h"
+#include "qohwindowcontext.h"
+#include "qohauxiliary.h"
+#include "qohaccessibilityprovider.h"
+#include <QtGui/qwindow.h>
+#include <QtGui/qguiapplication.h>
+#include <qpa/qplatformintegration.h>
+#include <QtCore/qopenharmonydefines.h>
+#include <qpa/qplatformaccessibility.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <private/qaccessiblebridgeutils_p.h>
+#include <mutex>
+#include <string>
+#if QT_CONFIG(accessibility)
+
+QT_BEGIN_NAMESPACE
+namespace QtOhAccessibility {
+
+// arkUi框架设计的特殊值,根节点必须设置parentId为这个值
+const int parentOfRoot = -2100000;
+void fillAccessibilityElement(ArkUI_AccessibilityElementInfo *element, QOhAccessibleNode *node)
+{
+    QtOh::runOnQtMainThreadAndWait([node]{
+       node->update();
+    });
+    OH_ArkUI_AccessibilityElementInfoSetElementId(element, node->id());
+    OH_ArkUI_AccessibilityElementInfoSetParentId(element, node->parent() == nullptr ? parentOfRoot : node->parent()->id());
+    OH_ArkUI_AccessibilityElementInfoSetComponentType(element, node->type().toUtf8().constData());
+    OH_ArkUI_AccessibilityElementInfoSetContents(element, node->contents().isEmpty() ? node->name().toUtf8().constData() : node->contents().toUtf8().constData());
+    OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(element, node->contents().toUtf8().constData());
+    OH_ArkUI_AccessibilityElementInfoSetHintText(element, node->hint().toUtf8().constData());
+    OH_ArkUI_AccessibilityElementInfoSetAccessibilityDescription(element, node->description().toUtf8().constData());
+    auto actions = node->actions();
+    OH_ArkUI_AccessibilityElementInfoSetOperationActions(element, actions.size(), actions.data());
+    QAccessible::State s = node->state();
+    OH_ArkUI_AccessibilityElementInfoSetVisible(element, node->isVisible());
+    OH_ArkUI_AccessibilityElementInfoSetEnabled(element, s.disabled != 1);
+    OH_ArkUI_AccessibilityElementInfoSetFocusable(element, node->focusable == 1);
+    OH_ArkUI_AccessibilityElementInfoSetFocused(element, s.focused == 1);
+    OH_ArkUI_AccessibilityElementInfoSetCheckable(element, s.checkable == 1);
+    OH_ArkUI_AccessibilityElementInfoSetChecked(element, s.checked == 1);
+    OH_ArkUI_AccessibilityElementInfoSetSelected(element, s.selected == 1);
+    OH_ArkUI_AccessibilityElementInfoSetIsPassword(element, s.passwordEdit == 1);
+    OH_ArkUI_AccessibilityElementInfoSetEditable(element, s.editable == 1);
+    OH_ArkUI_AccessibilityElementInfoSetClickable(element, node->clickable);
+    OH_ArkUI_AccessibilityElementInfoSetScrollable(element, node->scrollable);
+    QColor clr = node->backgroundColor();
+    QString name = clr.name();
+    QByteArray nameArray = name.toUtf8();
+    OH_ArkUI_AccessibilityElementInfoSetBackgroundColor(element, nameArray.constData());
+    auto valueInfo = node->valueInfo();
+    if (valueInfo.has_value()) {
+        ArkUI_AccessibleRangeInfo info = valueInfo.value();
+        OH_ArkUI_AccessibilityElementInfoSetRangeInfo(element, &info);
+    }
+    auto gridInfo = node->gridInfo();
+    if (gridInfo.has_value()) {
+        ArkUI_AccessibleGridInfo info = gridInfo.value();
+        OH_ArkUI_AccessibilityElementInfoSetGridInfo(element, &info);
+    }
+    auto gridItemInfo = node->gridItemInfo();
+    for (size_t i = 0; i < gridItemInfo.size(); ++i) {
+        auto item = gridItemInfo[i];
+        OH_ArkUI_AccessibilityElementInfoSetGridItemInfo(element, &item);
+    }
+    auto selections = node->selections();
+    if (!selections.empty()) {
+        auto first = selections.front();
+        OH_ArkUI_AccessibilityElementInfoSetSelectedTextStart(element, first.first);
+        OH_ArkUI_AccessibilityElementInfoSetSelectedTextEnd(element, first.second);
+    }
+
+    ArkUI_AccessibleRect rect = node->geometry();
+    OH_ArkUI_AccessibilityElementInfoSetScreenRect(element, &rect);
+}
+
+void fillChildrenAccessibilityElement(ArkUI_AccessibilityElementInfo *parentNode, ArkUI_AccessibilityElementInfoList *elementList, QOhAccessibleNode *node, bool recursive)
+{
+    if (!node->isVisible()) {
+        return;
+    }
+    auto c = node->children();
+    int64_t count = c.count();
+    if (count < 1)
+        return;
+    std::vector<int64_t> ids;
+    for (int64_t i = 0; i < count; ++i) {
+        ids.push_back(c.at(i)->id());
+    }
+    OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(parentNode, ids.size(), &ids[0]);
+
+    std::vector<std::pair<ArkUI_AccessibilityElementInfo *, QOhAccessibleNode *>> children(count);
+    for (int i = 0; i < count; ++i) {
+        auto childNode = c.at(i);
+        auto child = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList);
+        fillAccessibilityElement(child, childNode);
+        children[i] = {child, childNode};
+    }
+    if (!recursive)
+        return;
+    for (auto &child : children) {
+        fillChildrenAccessibilityElement(child.first, elementList, child.second, recursive);
+    }
+}
+
+static QWindow *windowForId(const char* instanceId)
+{
+    QWindow *window = nullptr;
+    if (instanceId == nullptr) {
+        window = QGuiApplication::focusWindow();
+        if (window == nullptr) {
+            window = QGuiApplication::topLevelWindows().empty() ? nullptr : QGuiApplication::topLevelWindows().last();
+        }
+    } else {
+        QOhPlatformWindow *pw = QOhWindowContext::get(instanceId);
+        if (pw != nullptr)
+            window = pw->window();
+    }
+    return window;
+}
+
+static void createOhNodeForWindow(QWindow *w,  ArkUI_AccessibilityElementInfoList *elementList)
+{
+    auto node = QOhAccessibleNode::node(w);
+    if (node == nullptr) {
+        node = QtOh::runOnQtMainThreadWithResult([w]{
+            QOhAccessibleNode *node = new QOhAccessibleNode(w);
+            return node;
+        });
+    }
+    
+    if (node != nullptr) {
+        auto element = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList);
+        fillAccessibilityElement(element, node);
+        fillChildrenAccessibilityElement(element, elementList, node, true);
+    }
+}
+
+
+int32_t findAccessibilityNodeInfosById(const char* instanceId, int64_t elementId, ArkUI_AccessibilitySearchMode mode,
+                                                                 int32_t requestId,
+                                                                 ArkUI_AccessibilityElementInfoList *elementList)
+{
+    // Ignoring all requests while starting up / shutting down
+    if (QCoreApplication::startingUp() || QCoreApplication::closingDown())
+        return OH_NATIVEXCOMPONENT_RESULT_SUCCESS;
+
+    auto accessibilityProvider = QGuiApplicationPrivate::platformIntegration()->accessibility();
+    if (accessibilityProvider == nullptr)
+        return OH_NATIVEXCOMPONENT_RESULT_FAILED;
+    accessibilityProvider->setActive(true);
+
+    LOGI("QOhAccessibilityProvider::findAccessibilityNodeInfosById start, instanceId: %{public}s elementId: %{public}ld, requestId: %{public}d, mode: %{public}d",
+         instanceId, elementId, requestId, static_cast<int32_t>(mode));
+
+    if (elementList == nullptr) {
+        LOGI("QOhAccessibilityProvider::findAccessibilityNodeInfosById elementList is null");
+        return OH_NATIVEXCOMPONENT_RESULT_FAILED;
+    }
+
+    if (elementId == -1 && mode == ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN) {
+        if (instanceId == nullptr)
+            return OH_NATIVEXCOMPONENT_RESULT_FAILED;
+        QWindow *window = windowForId(instanceId);
+        if (window == nullptr || window->accessibleRoot() == nullptr)
+            return OH_NATIVEXCOMPONENT_RESULT_FAILED;
+        createOhNodeForWindow(window, elementList);
+    } else {
+        // Screen Reader will query Elements with mode==ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT
+        if (mode == ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) {
+            QOhAccessibleNode *node = QOhAccessibleNode::find(elementId);
+            if (node != nullptr) {
+                auto element = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList);
+                fillAccessibilityElement(element, node);
+                fillChildrenAccessibilityElement(element, elementList, node, true);
+            }
+        }
+    }
+
+    LOGI("QOhAccessibilityProvider::findAccessibilityNodeInfosById end");
+    return OH_NATIVEXCOMPONENT_RESULT_SUCCESS;
+}
+
+int32_t findAccessibilityNodeInfosByText(const char* instanceId, int64_t elementId, const char *text, int32_t requestId,
+                                                                   ArkUI_AccessibilityElementInfoList *elementList)
+{
+    return OH_NATIVEXCOMPONENT_RESULT_SUCCESS;
+}
+
+int32_t findFocusedAccessibilityNode(const char* instanceId, int64_t elementId, ArkUI_AccessibilityFocusType focusType,
+                                                               int32_t requestId,
+                                                               ArkUI_AccessibilityElementInfo *elementInfo)
+
+{
+    LOGI("QOhAccessibilityProvider::findFocusedAccessibilityNode elementId: %{public}ld, requestId: %{public}d, focusType: %{public}d",
+         elementId, requestId, static_cast<int32_t>(focusType));
+
+    return OH_NATIVEXCOMPONENT_RESULT_SUCCESS;
+}
+
+int32_t findNextFocusAccessibilityNode(const char* instanceId, int64_t elementId,
+                                                                 ArkUI_AccessibilityFocusMoveDirection direction,
+                                                                 int32_t requestId,
+                                                                 ArkUI_AccessibilityElementInfo *elementInfo)
+{
+
+    LOGI("QOhAccessibilityProvider::findNextFocusAccessibilityNode elementId: %{public}ld, requestId: %{public}d, direction: %{public}d",
+         elementId, requestId, static_cast<int32_t>(direction));
+
+    return OH_NATIVEXCOMPONENT_RESULT_SUCCESS;
+}
+
+int32_t executeAccessibilityAction(const char* instanceId, int64_t elementId, ArkUI_Accessibility_ActionType action,
+                                                             ArkUI_AccessibilityActionArguments *actionArguments,
+                                                             int32_t requestId)
+{
+
+    Q_UNUSED(instanceId)
+    // Screen Reader will trigger this callback.
+    // At least the following actions must be processed
+    // After the processing, the response event needs to be sent to the system.
+    LOGI("QOhAccessibilityProvider::executeAccessibilityAction elementId: %{public}ld, action: %{public}d", elementId, action);
+    auto node = QOhAccessibleNode::find(elementId);
+    if (node == nullptr)
+        return OH_NATIVEXCOMPONENT_RESULT_FAILED;
+
+    QAccessibleInterface *interface = node->face();
+    QAccessibleActionInterface *actionInterface = interface->actionInterface();
+    QOhAccessibilityProvider *p = QOhAccessibilityProvider::provider(interface);
+    if (!actionInterface || !p)
+        return OH_NATIVEXCOMPONENT_RESULT_FAILED;
+
+    switch (action) {
+    case ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK:
+        QtOh::runOnQtMainThread([interface, actionInterface]{
+            auto actionNames = QAccessibleBridgeUtils::effectiveActionNames(interface);
+            if (actionNames.isEmpty())
+                return;
+            QAccessibleBridgeUtils::performEffectiveAction(interface, actionNames.first());
+        });
+        p->sendAccessibilityEvent(node, ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED);
+        break;
+    case ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS:
+        QtOh::runOnQtMainThread([interface]{
+            QAccessibleBridgeUtils::performEffectiveAction(interface, QAccessibleActionInterface::setFocusAction());
+        });
+        p->sendAccessibilityEvent(node, ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED);
+        break;
+    case ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD:
+        QtOh::runOnQtMainThread([interface]{
+            auto actionNames = QAccessibleBridgeUtils::effectiveActionNames(interface);
+            if (actionNames.isEmpty())
+                return;
+            if (actionNames.contains(QAccessibleActionInterface::scrollDownAction()))
+                QAccessibleBridgeUtils::performEffectiveAction(interface, QAccessibleActionInterface::scrollDownAction());
+            if (actionNames.contains(QAccessibleActionInterface::scrollRightAction()))
+                QAccessibleBridgeUtils::performEffectiveAction(interface, QAccessibleActionInterface::scrollRightAction());
+            if (actionNames.contains(QAccessibleActionInterface::increaseAction()))
+                QAccessibleBridgeUtils::performEffectiveAction(interface, QAccessibleActionInterface::increaseAction());
+        });
+        p->sendAccessibilityEvent(node, ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED);
+        break;
+    case ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD:
+        QtOh::runOnQtMainThread([interface]{
+            auto actionNames = QAccessibleBridgeUtils::effectiveActionNames(interface);
+            if (actionNames.isEmpty())
+                return;
+            if (actionNames.contains(QAccessibleActionInterface::scrollUpAction()))
+                QAccessibleBridgeUtils::performEffectiveAction(interface, QAccessibleActionInterface::scrollUpAction());
+            if (actionNames.contains(QAccessibleActionInterface::scrollLeftAction()))
+                QAccessibleBridgeUtils::performEffectiveAction(interface, QAccessibleActionInterface::scrollLeftAction());
+            if (actionNames.contains(QAccessibleActionInterface::decreaseAction()))
+                QAccessibleBridgeUtils::performEffectiveAction(interface, QAccessibleActionInterface::decreaseAction());
+        });
+        p->sendAccessibilityEvent(node, ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED);
+        break;
+    default:
+        break;
+    }
+    return OH_NATIVEXCOMPONENT_RESULT_SUCCESS;
+}
+
+int32_t clearFocusedFocusAccessibilityNode(const char* instanceId)
+{
+    LOGI("QOhAccessibilityProvider::clearFocusedFocusAccessibilityNode");
+    return OH_NATIVEXCOMPONENT_RESULT_SUCCESS;
+}
+
+int32_t getAccessibilityNodeCursorPosition(const char* instanceId, int64_t elementId, int32_t requestId, int32_t *index)
+{
+    LOGI("QOhAccessibilityProvider::getAccessibilityNodeCursorPosition");
+    return OH_NATIVEXCOMPONENT_RESULT_SUCCESS;
+}
+}
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/openharmony/accessibility/qohaccessibility.h b/src/plugins/platforms/openharmony/accessibility/qohaccessibility.h
new file mode 100644
index 00000000000..6c853342fe6
--- /dev/null
+++ b/src/plugins/platforms/openharmony/accessibility/qohaccessibility.h
@@ -0,0 +1,41 @@
+#ifndef QOHACCESSIBILITY_H
+#define QOHACCESSIBILITY_H
+
+#include <QtGui/qtguiglobal.h>
+#include <ace/xcomponent/native_interface_xcomponent.h>
+#if QT_CONFIG(accessibility)
+
+QT_BEGIN_NAMESPACE
+class QOhAccessibleNode;
+
+namespace QtOhAccessibility {
+
+void fillAccessibilityElement(ArkUI_AccessibilityElementInfo *element, QOhAccessibleNode *node);
+
+void fillChildrenAccessibilityElement(ArkUI_AccessibilityElementInfo *parentNode, ArkUI_AccessibilityElementInfoList *elementList, QOhAccessibleNode *node, bool recursive = false);
+
+int32_t findAccessibilityNodeInfosById(const char* instanceId, int64_t elementId, ArkUI_AccessibilitySearchMode mode,
+                                       int32_t requestId,
+                                       ArkUI_AccessibilityElementInfoList *elementList);
+int32_t findAccessibilityNodeInfosByText(const char* instanceId, int64_t elementId, const char *text, int32_t requestId,
+                                         ArkUI_AccessibilityElementInfoList *elementList);
+int32_t findFocusedAccessibilityNode(const char* instanceId, int64_t elementId, ArkUI_AccessibilityFocusType focusType,
+                                     int32_t requestId,
+                                     ArkUI_AccessibilityElementInfo *elementInfo);
+int32_t findNextFocusAccessibilityNode(const char* instanceId, int64_t elementId,
+                                       ArkUI_AccessibilityFocusMoveDirection direction,
+                                       int32_t requestId,
+                                       ArkUI_AccessibilityElementInfo *elementInfo);
+int32_t executeAccessibilityAction(const char* instanceId, int64_t elementId, ArkUI_Accessibility_ActionType action,
+                                   ArkUI_AccessibilityActionArguments *actionArguments,
+                                   int32_t requestId);
+int32_t clearFocusedFocusAccessibilityNode(const char* instanceId);
+int32_t getAccessibilityNodeCursorPosition(const char* instanceId, int64_t elementId, int32_t requestId, int32_t *index);
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QOHACCESSIBILITY_H
diff --git a/src/plugins/platforms/openharmony/accessibility/qohaccessibilityprovider.cpp b/src/plugins/platforms/openharmony/accessibility/qohaccessibilityprovider.cpp
new file mode 100644
index 00000000000..97311212807
--- /dev/null
+++ b/src/plugins/platforms/openharmony/accessibility/qohaccessibilityprovider.cpp
@@ -0,0 +1,348 @@
+#include "qohaccessibilityprovider.h"
+#include "qohaccessiblenode.h"
+#include "qohaccessibility.h"
+#include "qohobjectholder.h"
+#include "qohwindowcontext.h"
+
+#include <QtGui/qwindow.h>
+#include <QtGui/qguiapplication.h>
+#include <QtCore/qopenharmonydefines.h>
+#include <qpa/qplatformnativeinterface.h>
+#include <QTimer>
+#include <private/qaccessiblecache_p.h>
+#if QT_CONFIG(accessibility)
+
+#include <QtGui/qaccessible.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+QOhAccessibilityProvider::QOhAccessibilityProvider(OH_NativeXComponent *xcompoent)
+{
+    ArkUI_AccessibilityProvider *provider = nullptr;
+    int32_t ret = OH_NativeXComponent_GetNativeAccessibilityProvider(xcompoent, &provider);
+    if (provider == nullptr) {
+        LOGW("get accessibility provider is null");
+        return;
+    }
+
+    m_accessibilityProviderCallbacks.findAccessibilityNodeInfosById = findAccessibilityNodeInfosById;
+    m_accessibilityProviderCallbacks.findAccessibilityNodeInfosByText = findAccessibilityNodeInfosByText;
+    m_accessibilityProviderCallbacks.findFocusedAccessibilityNode = findFocusedAccessibilityNode;
+    m_accessibilityProviderCallbacks.findNextFocusAccessibilityNode = findNextFocusAccessibilityNode;
+    m_accessibilityProviderCallbacks.executeAccessibilityAction = executeAccessibilityAction;
+    m_accessibilityProviderCallbacks.clearFocusedFocusAccessibilityNode = clearFocusedFocusAccessibilityNode;
+    m_accessibilityProviderCallbacks.getAccessibilityNodeCursorPosition = getAccessibilityNodeCursorPosition;
+#if OHOS_SDK_VERSION > 14
+    char id[OH_XCOMPONENT_ID_LEN_MAX + 1] = { };
+    uint64_t id_length = OH_XCOMPONENT_ID_LEN_MAX + 1;
+    ret = OH_NativeXComponent_GetXComponentId(xcompoent, id, &id_length);
+    if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+        LOGW("QOhAccessibilityProvider::QOhAccessibilityProvider get xcompoent id failed");
+        return;
+    }
+    ret = OH_ArkUI_AccessibilityProviderRegisterCallbackWithInstance(id, provider, &m_accessibilityProviderCallbacks);
+#else
+    ret = OH_ArkUI_AccessibilityProviderRegisterCallback(provider, &m_accessibilityProviderCallbacks);
+#endif
+     if (ret != 0) {
+         LOGW("OH_ArkUI_AccessibilityProviderRegisterCallback failed");
+         return;
+     }
+    m_provider = provider;
+}
+
+QOhAccessibilityProvider::~QOhAccessibilityProvider()
+{
+
+}
+
+void QOhAccessibilityProvider::registerForWindow(QWindow *window)
+{
+    if (window == nullptr || m_providers.contains(window))
+        return;
+    QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface();
+    if (!window->handle())
+        return;
+    OH_NativeXComponent *xcomponent = reinterpret_cast<OH_NativeXComponent *>(platform->nativeResourceForWindow("nativeXComponent", window));
+    if (xcomponent == nullptr)
+        return;
+    QOhAccessibilityProvider *provider = new QOhAccessibilityProvider(xcomponent);
+    m_providers.insert(window, provider);
+    provider->connect(window, &QWindow::destroyed, provider, [window]{
+        if (m_providers.contains(window)) {
+            delete m_providers.take(window);
+        }
+    });
+}
+
+void QOhAccessibilityProvider::playSound(const QString &sound)
+{
+
+}
+
+QOhAccessibilityProvider *QOhAccessibilityProvider::provider(QAccessibleEvent *event)
+{
+    QAccessibleInterface *iface = event->accessibleInterface();
+    if (!iface || !iface->isValid())
+        return nullptr;
+
+    return provider(iface);
+}
+
+QOhAccessibilityProvider *QOhAccessibilityProvider::provider(QAccessibleInterface *iface)
+{
+    QWindow *window = QOhWindowContext::windowForInterface(iface);
+
+    if (!m_providers.contains(window))
+        registerForWindow(window);
+
+    return m_providers.value(window);
+}
+
+void QOhAccessibilityProvider::processAccessibilityEvent(QAccessibleEvent *event, ArkUI_AccessibilityEventType eventType)
+{
+    QOhAccessibilityProvider *p = provider(event);
+    if (p == nullptr)
+        return;
+    QAccessibleInterface *iface = event->accessibleInterface();
+    p->sendAccessibilityEvent(iface, eventType);
+}
+
+void QOhAccessibilityProvider::notifyFocusChange(QAccessibleEvent *event)
+{
+    QOhAccessibilityProvider *p = provider(event);
+    if (p == nullptr)
+        return;
+    QAccessibleInterface *iface = event->accessibleInterface();
+    QAccessible::State s = iface->state();
+    p->sendAccessibilityEvent(iface, s.focused == 1 ? ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED :
+                                                      ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED);
+}
+
+void QOhAccessibilityProvider::notifyStateChange(QAccessibleStateChangeEvent *event)
+{
+    QOhAccessibilityProvider *p = provider(event);
+ }
+
+void QOhAccessibilityProvider::notifyValueChange(QAccessibleValueChangeEvent *event)
+{
+    QOhAccessibilityProvider *p = provider(event);
+    if (p == nullptr)
+        return;
+    QAccessibleInterface *iface = event->accessibleInterface();
+    p->sendAccessibilityEvent(iface, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_TEXT_UPDATE);
+}
+
+void QOhAccessibilityProvider::notifyNameChange(QAccessibleEvent *event)
+{
+    QOhAccessibilityProvider *p = provider(event);
+    if (p == nullptr)
+        return;
+    QAccessibleInterface *iface = event->accessibleInterface();
+    p->sendAccessibilityEvent(iface, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_TEXT_UPDATE);
+}
+
+void QOhAccessibilityProvider::notifySelectionChange(QAccessibleEvent *event)
+{
+    QOhAccessibilityProvider *p = provider(event);
+    if (p == nullptr)
+        return;
+    QAccessibleInterface *iface = event->accessibleInterface();
+    p->sendAccessibilityEvent(iface, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED);
+}
+
+void QOhAccessibilityProvider::notifyTextChange(QAccessibleEvent *event)
+{
+    QOhAccessibilityProvider *p = provider(event);
+    if (p == nullptr)
+        return;
+    QAccessibleInterface *iface = event->accessibleInterface();
+    p->sendAccessibilityEvent(iface, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_TEXT_UPDATE);
+}
+
+void QOhAccessibilityProvider::deleteTimer()
+{
+    if (m_pageChangedTimer != nullptr) {
+        if (m_pageChangedTimer->isActive())
+            m_pageChangedTimer->stop();
+        delete m_pageChangedTimer;
+    }
+}
+
+void QOhAccessibilityProvider::notifyPageChange(QAccessibleEvent *event)
+{
+//     Qt上层会发送多个hide/show事件下来
+    m_pedingInterfaces << QAccessible::uniqueId(event->accessibleInterface());
+    if (m_pageChangedTimer == nullptr) {
+        m_pageChangedTimer = new QTimer;
+        qRemovePostRoutine(deleteTimer);
+        m_pageChangedTimer->setSingleShot(true);
+        QObject::connect(m_pageChangedTimer, &QTimer::timeout, []{
+            if (m_pedingInterfaces.isEmpty())
+                return;
+            QList<QOhAccessibilityProvider *> pr;
+            for (int i = 0; i < m_pedingInterfaces.count(); ++i) {
+                auto id = m_pedingInterfaces.at(i);
+                auto iface = QAccessibleCache::instance()->interfaceForId(id);
+                if (iface == nullptr)
+                    continue;
+                auto p = provider(iface);
+                if (p != nullptr && !pr.contains(p)) {
+                    pr << p;
+                    p->sendAccessibilityEvent(iface, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE);
+                }
+            }
+            m_pedingInterfaces.clear();
+        });
+    }
+    if (m_pageChangedTimer->isActive())
+        return;
+    m_pageChangedTimer->start(5000);
+}
+
+void QOhAccessibilityProvider::sendAccessibilityEvent(QOhAccessibleNode *node, ArkUI_AccessibilityEventType eventType)
+{
+    if (m_provider == nullptr) {
+        qWarning() << "sendAccessibilityEvent: ohos provider is nullptr";
+        return;
+    }
+    QOhObjectHolder<ArkUI_AccessibilityEventInfo> eventInfo(OH_ArkUI_CreateAccessibilityEventInfo, OH_ArkUI_DestoryAccessibilityEventInfo);
+    auto nativeEventInfo = eventInfo.object();
+    if (nativeEventInfo == nullptr) {
+        qWarning() << "sendAccessibilityEvent: Unable to create accessibility eventInfo";
+        return;
+    }
+    QOhObjectHolder<ArkUI_AccessibilityElementInfo> elementInfo(OH_ArkUI_CreateAccessibilityElementInfo, OH_ArkUI_DestoryAccessibilityElementInfo);
+    auto nativeElementInfo = elementInfo.object();
+    if (nativeElementInfo == nullptr) {
+        qWarning() << "sendAccessibilityEvent: Unable to create accessibility elementInfo";
+        return;
+    }
+    QtOhAccessibility::fillAccessibilityElement(nativeElementInfo, node);
+    auto callback = [](int32_t code){
+        qDebug() << "send accessibility result: " << code;
+    };
+    OH_ArkUI_AccessibilityEventSetEventType(nativeEventInfo, eventType);
+    OH_ArkUI_AccessibilityEventSetElementInfo(nativeEventInfo, nativeElementInfo);
+    OH_ArkUI_SendAccessibilityAsyncEvent(m_provider, nativeEventInfo, callback);
+}
+
+void QOhAccessibilityProvider::sendAccessibilityEvent(QAccessibleInterface *iface, ArkUI_AccessibilityEventType eventType)
+{
+    if (!iface || !iface->isValid())
+        return;
+    auto node = QOhAccessibleNode::find(iface);
+    if (node == nullptr)
+        return;
+    sendAccessibilityEvent(node, eventType);
+}
+
+#if OHOS_SDK_VERSION > 14
+int32_t QOhAccessibilityProvider::findAccessibilityNodeInfosById(const char* instanceId, int64_t elementId, ArkUI_AccessibilitySearchMode mode,
+                                                             int32_t requestId,
+                                                             ArkUI_AccessibilityElementInfoList *elementList)
+{
+    return QtOhAccessibility::findAccessibilityNodeInfosById(instanceId, elementId, mode,requestId, elementList);
+}
+
+int32_t QOhAccessibilityProvider::findAccessibilityNodeInfosByText(const char* instanceId, int64_t elementId, const char *text, int32_t requestId,
+                                                               ArkUI_AccessibilityElementInfoList *elementList)
+{
+    return QtOhAccessibility::findAccessibilityNodeInfosByText(instanceId, elementId, text, requestId, elementList);
+}
+
+int32_t QOhAccessibilityProvider::findFocusedAccessibilityNode(const char* instanceId, int64_t elementId, ArkUI_AccessibilityFocusType focusType,
+                                                           int32_t requestId,
+                                                           ArkUI_AccessibilityElementInfo *elementInfo)
+
+{
+    return QtOhAccessibility::findFocusedAccessibilityNode(instanceId, elementId, focusType, requestId, elementInfo);
+}
+
+int32_t QOhAccessibilityProvider::findNextFocusAccessibilityNode(const char* instanceId, int64_t elementId,
+                                                             ArkUI_AccessibilityFocusMoveDirection direction,
+                                                             int32_t requestId,
+                                                             ArkUI_AccessibilityElementInfo *elementInfo)
+{
+
+    return QtOhAccessibility::findNextFocusAccessibilityNode(instanceId, elementId, direction, requestId, elementInfo);
+}
+
+int32_t QOhAccessibilityProvider::executeAccessibilityAction(const char* instanceId, int64_t elementId, ArkUI_Accessibility_ActionType action,
+                                                         ArkUI_AccessibilityActionArguments *actionArguments,
+                                                         int32_t requestId)
+{
+
+    return QtOhAccessibility::executeAccessibilityAction(instanceId, elementId, action,
+                                                                actionArguments,
+                                                                requestId);
+}
+
+int32_t QOhAccessibilityProvider::clearFocusedFocusAccessibilityNode(const char* instanceId)
+{
+    return QtOhAccessibility::clearFocusedFocusAccessibilityNode(instanceId);
+}
+
+int32_t QOhAccessibilityProvider::getAccessibilityNodeCursorPosition(const char* instanceId, int64_t elementId, int32_t requestId, int32_t *index)
+{
+    return QtOhAccessibility::getAccessibilityNodeCursorPosition(instanceId, elementId, requestId, index);
+}
+#else
+int32_t QOhAccessibilityProvider::findAccessibilityNodeInfosById(int64_t elementId, ArkUI_AccessibilitySearchMode mode,
+                                                             int32_t requestId,
+                                                             ArkUI_AccessibilityElementInfoList *elementList)
+{
+    return QtOhAccessibility::findAccessibilityNodeInfosById(nullptr, elementId, mode,requestId, elementList);
+}
+
+int32_t QOhAccessibilityProvider::findAccessibilityNodeInfosByText(int64_t elementId, const char *text, int32_t requestId,
+                                                               ArkUI_AccessibilityElementInfoList *elementList)
+{
+    return QtOhAccessibility::findAccessibilityNodeInfosByText(nullptr, elementId, text, requestId, elementList);
+}
+
+int32_t QOhAccessibilityProvider::findFocusedAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusType focusType,
+                                                           int32_t requestId,
+                                                           ArkUI_AccessibilityElementInfo *elementInfo)
+
+{
+    return QtOhAccessibility::findFocusedAccessibilityNode(nullptr, elementId, focusType, requestId, elementInfo);
+}
+
+int32_t QOhAccessibilityProvider::findNextFocusAccessibilityNode(int64_t elementId,
+                                                             ArkUI_AccessibilityFocusMoveDirection direction,
+                                                             int32_t requestId,
+                                                             ArkUI_AccessibilityElementInfo *elementInfo)
+{
+
+    return QtOhAccessibility::findNextFocusAccessibilityNode(nullptr, elementId,
+                                                                 direction,
+                                                                 requestId,
+                                                                 elementInfo);
+}
+
+int32_t QOhAccessibilityProvider::executeAccessibilityAction(int64_t elementId, ArkUI_Accessibility_ActionType action,
+                                                         ArkUI_AccessibilityActionArguments *actionArguments,
+                                                         int32_t requestId)
+{
+
+    return QtOhAccessibility::executeAccessibilityAction(nullptr, elementId, action,
+                                                                actionArguments,
+                                                                requestId);
+}
+
+int32_t QOhAccessibilityProvider::clearFocusedFocusAccessibilityNode()
+{
+    return QtOhAccessibility::clearFocusedFocusAccessibilityNode(nullptr);
+}
+
+int32_t QOhAccessibilityProvider::getAccessibilityNodeCursorPosition(int64_t elementId, int32_t requestId, int32_t *index)
+{
+    return QtOhAccessibility::getAccessibilityNodeCursorPosition(nullptr, elementId, requestId, index);
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/openharmony/accessibility/qohaccessibilityprovider.h b/src/plugins/platforms/openharmony/accessibility/qohaccessibilityprovider.h
new file mode 100644
index 00000000000..e5f4e3f36a7
--- /dev/null
+++ b/src/plugins/platforms/openharmony/accessibility/qohaccessibilityprovider.h
@@ -0,0 +1,94 @@
+#ifndef QOHACCESSIBILITYPROVIDER_H
+#define QOHACCESSIBILITYPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+#include <QtGui/qaccessible.h>
+#include <QtCore/qhash.h>
+#include <ace/xcomponent/native_interface_xcomponent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAccessibleInterface;
+class QOhAccessibleNode;
+class QOhAccessibilityProvider : public QObject
+{
+    Q_OBJECT
+public:
+    explicit QOhAccessibilityProvider(OH_NativeXComponent *xcomponent);
+    virtual ~QOhAccessibilityProvider();
+
+    static void registerForWindow(QWindow *window);
+
+    static void playSound(const QString &sound);
+    static void processAccessibilityEvent(QAccessibleEvent *event, ArkUI_AccessibilityEventType eventType);
+    static void notifyFocusChange(QAccessibleEvent *event);
+    static void notifyStateChange(QAccessibleStateChangeEvent *event);
+    static void notifyValueChange(QAccessibleValueChangeEvent *event);
+    static void notifyNameChange(QAccessibleEvent *event);
+    static void notifySelectionChange(QAccessibleEvent *event);
+    static void notifyTextChange(QAccessibleEvent *event);
+    static void notifyPageChange(QAccessibleEvent *event);
+
+    virtual void sendAccessibilityEvent(QAccessibleInterface *iface, ArkUI_AccessibilityEventType eventType);
+    virtual void sendAccessibilityEvent(QOhAccessibleNode *node, ArkUI_AccessibilityEventType eventType);
+
+    static QOhAccessibilityProvider *provider(QAccessibleEvent *event);
+    static QOhAccessibilityProvider *provider(QAccessibleInterface *iface);
+private:
+#if OHOS_SDK_VERSION > 14
+    static int32_t findAccessibilityNodeInfosById(const char* instanceId, int64_t elementId, ArkUI_AccessibilitySearchMode mode,
+                                                  int32_t requestId,
+                                                  ArkUI_AccessibilityElementInfoList *elementList);
+    static int32_t findAccessibilityNodeInfosByText(const char* instanceId, int64_t elementId, const char *text, int32_t requestId,
+                                                    ArkUI_AccessibilityElementInfoList *elementList);
+    static int32_t findFocusedAccessibilityNode(const char* instanceId, int64_t elementId, ArkUI_AccessibilityFocusType focusType,
+                                                int32_t requestId,
+                                                ArkUI_AccessibilityElementInfo *elementInfo);
+    static int32_t findNextFocusAccessibilityNode(const char* instanceId, int64_t elementId,
+                                                  ArkUI_AccessibilityFocusMoveDirection direction,
+                                                  int32_t requestId,
+                                                  ArkUI_AccessibilityElementInfo *elementInfo);
+    static int32_t executeAccessibilityAction(const char* instanceId, int64_t elementId, ArkUI_Accessibility_ActionType action,
+                                              ArkUI_AccessibilityActionArguments *actionArguments,
+                                              int32_t requestId);
+    static int32_t clearFocusedFocusAccessibilityNode(const char* instanceId);
+    static int32_t getAccessibilityNodeCursorPosition(const char* instanceId, int64_t elementId, int32_t requestId, int32_t *index);
+#else
+    static int32_t findAccessibilityNodeInfosById(int64_t elementId, ArkUI_AccessibilitySearchMode mode,
+                                                  int32_t requestId,
+                                                  ArkUI_AccessibilityElementInfoList *elementList);
+    static int32_t findAccessibilityNodeInfosByText(int64_t elementId, const char *text, int32_t requestId,
+                                                    ArkUI_AccessibilityElementInfoList *elementList);
+    static int32_t findFocusedAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusType focusType,
+                                                int32_t requestId,
+                                                ArkUI_AccessibilityElementInfo *elementInfo);
+    static int32_t findNextFocusAccessibilityNode(int64_t elementId,
+                                                  ArkUI_AccessibilityFocusMoveDirection direction,
+                                                  int32_t requestId,
+                                                  ArkUI_AccessibilityElementInfo *elementInfo);
+    static int32_t executeAccessibilityAction(int64_t elementId, ArkUI_Accessibility_ActionType action,
+                                              ArkUI_AccessibilityActionArguments *actionArguments,
+                                              int32_t requestId);
+    static int32_t clearFocusedFocusAccessibilityNode();
+    static int32_t getAccessibilityNodeCursorPosition(int64_t elementId, int32_t requestId, int32_t *index);
+#endif
+    static void createOhNodeForWindow(QWindow *w, ArkUI_AccessibilityElementInfoList *elementList);
+private:
+    ArkUI_AccessibilityProvider *m_provider = nullptr;
+#if OHOS_SDK_VERSION > 14
+    ArkUI_AccessibilityProviderCallbacksWithInstance m_accessibilityProviderCallbacks;
+#else
+    ArkUI_AccessibilityProviderCallbacks m_accessibilityProviderCallbacks;
+#endif
+    static inline QHash<QWindow *, QOhAccessibilityProvider *> m_providers = {};
+    static void deleteTimer();
+    static inline QTimer *m_pageChangedTimer = nullptr;
+    static inline QList<QAccessible::Id> m_pedingInterfaces = {};
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QOHACCESSIBILITYPROVIDER_H
diff --git a/src/plugins/platforms/openharmony/accessibility/qohaccessiblenode.cpp b/src/plugins/platforms/openharmony/accessibility/qohaccessiblenode.cpp
new file mode 100644
index 00000000000..40ecd6471b1
--- /dev/null
+++ b/src/plugins/platforms/openharmony/accessibility/qohaccessiblenode.cpp
@@ -0,0 +1,427 @@
+#include "qohwindowcontext.h"
+#include "qohaccessiblenode.h"
+
+#include <limits>
+#include <qopenharmony.h>
+#include <private/qaccessiblecache_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
+#include <QtCore/qmetaobject.h>
+#include <QWindow>
+#include <private/qaccessiblebridgeutils_p.h> /* Qt6 only modify */
+
+QT_BEGIN_NAMESPACE
+
+static ArkUI_AccessibleAction qtAction2OhAction(const QString &name)
+{
+    ArkUI_AccessibleAction action;
+    action.actionType = ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID;
+    action.description = nullptr;
+    if (name == QAccessibleActionInterface::pressAction()
+            || name == QAccessibleActionInterface::showMenuAction()
+            || name == QAccessibleActionInterface::toggleAction()) {
+        action.actionType = ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK;
+    } else if (name == QAccessibleActionInterface::setFocusAction()) {
+        action.actionType = ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS;
+    } else if (name == QAccessibleActionInterface::scrollUpAction()
+               || name == QAccessibleActionInterface::scrollLeftAction()
+               || name == QAccessibleActionInterface::decreaseAction()) {
+        action.actionType = ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD;
+    } else if (name == QAccessibleActionInterface::scrollDownAction()
+               || name == QAccessibleActionInterface::increaseAction()
+               || name == QAccessibleActionInterface::scrollRightAction()) {
+        action.actionType = ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD;
+    } else if (name == QAccessibleActionInterface::nextPageAction()) {
+
+    } else if (name == QAccessibleActionInterface::previousPageAction()) {
+
+    }
+    return action;
+}
+
+QOhAccessibleNode::QOhAccessibleNode(QWindow *window)
+    : m_parent(nullptr)
+    , m_window(window)
+{
+    QAccessibleInterface *accessible = window->accessibleRoot();
+    if (accessible != nullptr) {
+        m_id = QAccessible::uniqueId(accessible);
+        createNode(accessible);
+    } else {
+        qWarning() << "the accessible is nullptr" << window;
+    }
+    AllNodes.insert(m_id, this);
+    RootNodes.insert(window, this);
+    if (m_parent != nullptr)
+        m_parent->m_children << this;
+
+    QObject::connect(window, &QWindow::destroyed, window, [id = m_id]() {
+        removeNode(id);
+    });
+}
+
+QOhAccessibleNode::QOhAccessibleNode(QWindow *window, QAccessibleInterface *accessible, QOhAccessibleNode *parent)
+    : m_parent(parent)
+    , m_window(window)
+{
+    if (accessible == nullptr)
+        return;
+    m_id = QAccessible::uniqueId(accessible);
+    AllNodes.insert(m_id, this);
+    createNode(accessible);
+    if (m_parent != nullptr)
+        m_parent->m_children << this;
+}
+
+QOhAccessibleNode::~QOhAccessibleNode()
+{
+    qDeleteAll(m_children);
+    m_children.clear();
+    AllNodes.remove(m_id);
+    if (m_parent == nullptr)
+        RootNodes.remove(m_window);
+    else {
+        m_parent->m_children.removeOne(this);
+    }
+    clearDatas();
+    m_window = nullptr;
+}
+
+QOhAccessibleNode *QOhAccessibleNode::node(QWindow *w)
+{
+    return RootNodes.value(w);
+}
+
+void QOhAccessibleNode::removeNode(QAccessible::Id id)
+{
+    if (AllNodes.contains(id))
+        delete AllNodes.take(id);
+}
+
+int64_t QOhAccessibleNode::id() const
+{
+    constexpr auto minAllowedNodeId = std::numeric_limits<std::uint32_t>::max() - std::numeric_limits<std::int32_t>::max();
+    
+    if (m_id < minAllowedNodeId) {
+        // error
+        return 0;
+    }
+    return m_id - minAllowedNodeId;
+}
+
+QString QOhAccessibleNode::type() const
+{
+    return m_type;
+}
+
+void QOhAccessibleNode::setName(const QString &name)
+{
+    m_name = name;
+}
+
+QString QOhAccessibleNode::name() const
+{
+    return m_name;
+}
+
+void QOhAccessibleNode::setContents(const QString &contents)
+{
+    m_contents = contents;
+}
+
+QString QOhAccessibleNode::contents() const
+{
+    return m_contents;
+}
+
+void QOhAccessibleNode::setHint(const QString &hint)
+{
+    m_hint = hint;
+}
+
+QString QOhAccessibleNode::hint() const
+{
+    return m_hint;
+}
+
+void QOhAccessibleNode::setState(QAccessible::State state)
+{
+    m_state = state;
+}
+
+QAccessible::State QOhAccessibleNode::state() const
+{
+    return m_state;
+}
+
+void QOhAccessibleNode::setGeometry(const QRect &r)
+{
+    m_geometry = { .leftTopX = r.left(),
+                   .leftTopY = r.top(),
+                   .rightBottomX = r.right(),
+                   .rightBottomY = r.bottom() };
+}
+
+ArkUI_AccessibleRect QOhAccessibleNode::geometry() const
+{
+    return m_geometry;
+}
+
+void QOhAccessibleNode::setParent(QOhAccessibleNode *parent)
+{
+    if (parent == nullptr || m_parent == parent)
+        return;
+    if (m_parent != nullptr)
+        m_parent->m_children.removeOne(this);
+    m_parent = parent;
+    m_parent->m_children << this;
+}
+
+QOhAccessibleNode *QOhAccessibleNode::parent() const
+{
+    return m_parent;
+}
+
+const QList<QOhAccessibleNode *> &QOhAccessibleNode::children() const
+{
+    return m_children;
+}
+
+QOhAccessibleNode *QOhAccessibleNode::find(QAccessibleInterface *accessible)
+{
+    if (accessible == nullptr)
+        return nullptr;
+    auto id = QAccessible::uniqueId(accessible);
+    auto iter = AllNodes.find(id);
+    return iter != AllNodes.end() ? iter.value() : nullptr;
+}
+
+QOhAccessibleNode *QOhAccessibleNode::find(int64_t id)
+{
+    auto nodes = AllNodes.values();
+    for (int i = 0; i < nodes.count(); ++i) {
+        if (nodes.at(i)->id() == id)
+            return nodes.at(i);
+    }
+    return nullptr;
+}
+
+QAccessibleInterface *QOhAccessibleNode::face() const
+{
+    return QAccessibleCache::instance()->interfaceForId(m_id);
+}
+
+QString QOhAccessibleNode::accelerator() const
+{
+    return m_accelerator;
+}
+
+std::vector<ArkUI_AccessibleAction> QOhAccessibleNode::actions() const
+{
+    return m_actions;
+}
+
+std::optional<ArkUI_AccessibleRangeInfo> QOhAccessibleNode::valueInfo() const
+{
+    return m_valueInfo;
+}
+
+std::optional<ArkUI_AccessibleGridInfo> QOhAccessibleNode::gridInfo() const
+{
+    return m_gridInfo;
+}
+
+std::vector<ArkUI_AccessibleGridItemInfo> QOhAccessibleNode::gridItemInfo() const
+{
+    return m_gridItemInfo;
+}
+
+QColor QOhAccessibleNode::backgroundColor() const
+{
+    return m_backgroundColor;
+}
+
+std::vector<std::pair<int32_t, int32_t> > QOhAccessibleNode::selections() const
+{
+    return m_selections;
+}
+
+bool QOhAccessibleNode::isVisible() const
+{
+    if (state().invisible == 1) {
+        return false;
+    }
+    return m_geometry.rightBottomX > m_geometry.leftTopX
+            && m_geometry.rightBottomY > m_geometry.leftTopY;
+}
+
+QRect QOhAccessibleNode::getRelativeGeometry(QAccessibleInterface *accessible, QWindow *window)
+{
+    if (window == nullptr) {
+        window = QOhWindowContext::windowForInterface(accessible);
+    }
+    QRect r = accessible->rect();
+    if (window == nullptr) {
+        return r;
+    }
+    window = QOhWindowContext::topLevelOf(window, QWindow::IncludeTransients);
+    // 15的坐标是相对于窗口的坐标,之前的版本是屏幕坐标
+    if (QtOh::apiVersion() > 14) {
+        QPoint pt = window->mapFromGlobal(r.topLeft());
+        r.moveTopLeft(pt);
+    } else {
+        int titleHeight = window->frameMargins().top();
+        r.translate(0, -titleHeight);
+    }
+    if (QHighDpiScaling::isActive())
+        r = QHighDpi::toNativePixels(r, window);
+    return r;
+}
+
+void QOhAccessibleNode::update()
+{
+    auto accessible = QAccessibleCache::instance()->interfaceForId(m_id);
+    if (!accessible || !m_window)
+        return;
+
+    m_name = accessible->text(QAccessible::Name);
+    m_contents = accessible->text(QAccessible::Value);
+    m_hint = accessible->text(QAccessible::Help);
+    m_description = accessible->text(QAccessible::Description);
+    m_accelerator = accessible->text(QAccessible::Accelerator);
+    m_backgroundColor = accessible->backgroundColor();
+    m_state = accessible->state();
+    setGeometry(getRelativeGeometry(accessible, m_window));
+
+    clearDatas();
+    QStringList actions = QAccessibleBridgeUtils::effectiveActionNames(accessible);
+    QAccessibleActionInterface *ac = accessible->actionInterface();
+    for (int i = 0; i < actions.count(); ++i) {
+        auto ohac = qtAction2OhAction(actions.at(i));
+        if (ohac.actionType != ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID) {
+            QString actionDesc = ac ? ac->localizedActionDescription(actions.at(i)) : QString();
+            switch (ohac.actionType) {
+            case ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK:
+                if (!clickable) {
+                    clickable = true;
+                    ohac.description = strdup(actionDesc.toUtf8().constData());
+                    m_actions.push_back(ohac);
+                }
+                break;
+            case ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS:
+                if (!focusable) {
+                    focusable = true;
+                    ohac.description = strdup(actionDesc.toUtf8().constData());
+                    m_actions.push_back(ohac);
+                }
+                break;
+            case ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD:
+                [[fallthrough]];
+            case ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD:
+                scrollable = true;
+                ohac.description = strdup(actionDesc.toUtf8().constData());
+                m_actions.push_back(ohac);
+                break;
+            default:
+                break;
+            }
+        }
+    }
+    if (!focusable && (clickable || scrollable)) {
+        focusable = true;
+        ArkUI_AccessibleAction action;
+        action.actionType = ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS;
+        // 使用nullptr会引起OHOS::Ace::Framework::TransformAccessbilityElementInfo崩溃
+        // action.description = nullptr;
+        action.description = strdup("");
+        m_actions.push_back(action);
+    }
+
+    QAccessibleValueInterface *valueInterface = accessible->valueInterface();
+    if (valueInterface != nullptr) {
+        m_valueInfo = { .min = valueInterface->minimumValue().toDouble(),
+                        .max = valueInterface->maximumValue().toDouble(),
+                        .current = valueInterface->currentValue().toDouble()};
+    }
+
+    QAccessibleTableInterface *tableInterface = accessible->tableInterface();
+    if (tableInterface != nullptr) {
+        m_gridInfo = { .rowCount = tableInterface->rowCount(),
+                       .columnCount = tableInterface->columnCount(),
+                       .selectionMode = 1 };
+        for (int i = 0; i < tableInterface->rowCount(); ++i) {
+            for (int j = 0; j < tableInterface->columnCount(); ++j) {
+                QAccessibleInterface *item = tableInterface->cellAt(i, j);
+                if (item == nullptr)
+                    continue;
+                QAccessibleTableCellInterface *cellInterface = (QAccessibleTableCellInterface *)item->interface_cast(QAccessible::TableCellInterface);
+                ArkUI_AccessibleGridItemInfo info = {
+                    .heading = false,
+                    .selected = cellInterface->isSelected(),
+                    .columnIndex = j,
+                    .rowIndex = i,
+                    .columnSpan = cellInterface->rowExtent(),
+                    .rowSpan = cellInterface->columnExtent()
+                };
+                m_gridItemInfo.push_back(info);
+            }
+        }
+    }
+
+    QAccessibleTextInterface *textInterface = accessible->textInterface();
+    if (textInterface != nullptr) {
+        int count = textInterface->selectionCount();
+        for (int i = 0; i < count; ++i) {
+            int start = 0;
+            int end = 0;
+            textInterface->selection(i, &start, &end);
+            m_selections.push_back(std::make_pair((int32_t)start, (int32_t)end));
+        }
+    }
+
+    for (int i = 0; i < accessible->childCount(); ++i) {
+        auto child = accessible->child(i);
+        if (auto childNode = find(child)) {
+            if (childNode->parent() != this) {
+                childNode->setParent(this);
+            }
+            continue;
+        }
+        new QOhAccessibleNode(m_window, child, this);
+    }
+}
+
+QString QOhAccessibleNode::description() const
+{
+    return m_description;
+}
+
+static const char *roleName(QAccessible::Role role) {
+    static const QMetaObject *metaObject = qt_getEnumMetaObject(role);
+    static const QMetaEnum me = metaObject->enumerator(metaObject->indexOfEnumerator(qt_getEnumName(role)));
+    return me.valueToKey(role);
+}
+
+void QOhAccessibleNode::createNode(QAccessibleInterface *accessible)
+{
+    if (QObject *obj = accessible->object()) {
+        const QMetaObject *mo = obj->metaObject();
+        m_type = mo->className();
+    }
+    if (m_type.isEmpty()) {
+        m_type = QString::fromLatin1(roleName(accessible->role()));
+    }
+    update();
+}
+
+void QOhAccessibleNode::clearDatas()
+{
+    for (size_t i = 0; i < m_actions.size(); ++i) {
+        if (m_actions[i].description != nullptr)
+            free((void *)m_actions[i].description);
+    }
+    m_gridItemInfo.clear();
+    m_actions.clear();
+    m_selections.clear();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/accessibility/qohaccessiblenode.h b/src/plugins/platforms/openharmony/accessibility/qohaccessiblenode.h
new file mode 100644
index 00000000000..f7ffb9140cf
--- /dev/null
+++ b/src/plugins/platforms/openharmony/accessibility/qohaccessiblenode.h
@@ -0,0 +1,103 @@
+#ifndef QOHACCESSIBLENODE_H
+#define QOHACCESSIBLENODE_H
+#include <QList>
+#include <QString>
+#include <QScopedPointer>
+#include <QAccessibleInterface>
+#include <arkui/native_interface_accessibility.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOhAccessibleNode
+{
+public:
+    explicit QOhAccessibleNode(QWindow *window);
+    QOhAccessibleNode(QWindow *window, QAccessibleInterface *accessible, QOhAccessibleNode *parent);
+    virtual ~QOhAccessibleNode();
+
+    static QOhAccessibleNode *node(QWindow *w);
+    static void removeNode(QAccessible::Id);
+    int64_t id() const;
+
+    QString type() const;
+
+    void setName(const QString &name);
+    QString name() const;
+
+    void setContents(const QString &contents);
+    QString contents() const;
+
+    void setHint(const QString &hint);
+    QString hint() const;
+
+    void setState(QAccessible::State state);
+    QAccessible::State state() const;
+
+    void setGeometry(const QRect &geometry);
+    ArkUI_AccessibleRect geometry() const;
+
+    void setParent(QOhAccessibleNode *parent);
+    QOhAccessibleNode *parent() const;
+
+    const QList<QOhAccessibleNode *> &children() const;
+
+    static QOhAccessibleNode *find(int64_t id);
+    static QOhAccessibleNode *find(QAccessibleInterface *accessible);
+
+    QAccessibleInterface *face() const;
+
+    QString description() const;
+
+    QString accelerator() const;
+
+    std::vector<ArkUI_AccessibleAction> actions() const;
+
+    std::optional<ArkUI_AccessibleRangeInfo> valueInfo() const;
+
+    std::optional<ArkUI_AccessibleGridInfo> gridInfo() const;
+
+    std::vector<ArkUI_AccessibleGridItemInfo> gridItemInfo() const;
+
+    QColor backgroundColor() const;
+
+    std::vector<std::pair<int32_t, int32_t>> selections() const;
+
+    bool isVisible() const;
+
+    static QRect getRelativeGeometry(QAccessibleInterface *accessible, QWindow *window);
+
+    void update();
+
+    bool clickable = false;
+    bool focusable = false;
+    bool scrollable = false;
+private:
+    void createNode(QAccessibleInterface *accessible);
+    void clearDatas();
+private:
+    QOhAccessibleNode *m_parent;
+    QWindow *m_window;
+    QAccessible::Id m_id;
+    QString m_type;
+    QString m_name;
+    QString m_contents;
+    QString m_description;
+    QString m_accelerator;
+    QString m_hint;
+    QAccessible::State m_state;
+    QColor m_backgroundColor;
+    ArkUI_AccessibleRect m_geometry;
+    std::vector<ArkUI_AccessibleAction> m_actions;
+    std::optional<ArkUI_AccessibleRangeInfo> m_valueInfo;
+    std::optional<ArkUI_AccessibleGridInfo> m_gridInfo;
+    std::vector<ArkUI_AccessibleGridItemInfo> m_gridItemInfo;
+    std::vector<std::pair<int32_t, int32_t>> m_selections;
+    QList<QOhAccessibleNode *> m_children;
+
+    static inline QHash<QAccessible::Id, QOhAccessibleNode *> AllNodes = {};
+    static inline QHash<QWindow*, QOhAccessibleNode *> RootNodes = {};
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHACCESSIBLENODE_H
diff --git a/src/plugins/platforms/openharmony/accessibility/qohplatformaccessibility.cpp b/src/plugins/platforms/openharmony/accessibility/qohplatformaccessibility.cpp
new file mode 100644
index 00000000000..6c856e63cba
--- /dev/null
+++ b/src/plugins/platforms/openharmony/accessibility/qohplatformaccessibility.cpp
@@ -0,0 +1,218 @@
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qohplatformaccessibility.h"
+#include "qohaccessibilityprovider.h"
+#include <QtGui/qaccessible.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <private/qaccessiblecache_p.h>
+#include <qpa/qplatformintegration.h>
+#include "qohauxiliary.h"
+#include "qohwindowcontext.h"
+#include "qohaccessiblenode.h"
+#include "qohplatformaccessibility.h"
+#include "qohaccessibilityprovider.h"
+QT_BEGIN_NAMESPACE
+
+namespace {
+void updateAccessibilityLater(QObject *qObject, QAccessible::Event accessibleEventType)
+{
+    QtOh::runOnQtMainThreadLater([qObject = QPointer<QObject>(qObject), accessibleEventType]() {
+        if (qObject.isNull()) {
+            return;
+        }
+        QAccessibleEvent accessibleEvent(qObject, accessibleEventType);
+        QAccessible::updateAccessibility(&accessibleEvent);
+    });
+}
+
+std::optional<ArkUI_AccessibilityEventType> tryMapQAccessibleEventToAccessibilityEvent(
+        QAccessibleEvent *event)
+{
+    auto *obj = event->object();
+    bool isTopWindow = obj && obj->isWindowType();
+    switch (event->type()) {
+    case QAccessible::ObjectCreated:
+    case QAccessible::ObjectDestroyed:
+    case QAccessible::ParentChanged:
+    case QAccessible::PageChanged:
+    case QAccessible::ObjectReorder:
+    case QAccessible::ObjectShow:
+    case QAccessible::ObjectHide:
+    case QAccessible::LocationChanged:
+        return {isTopWindow ? ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_STATE_UPDATE : ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE};
+    case QAccessible::Focus:
+            {
+                QAccessibleInterface *iface = event->accessibleInterface();
+                QAccessible::State s = iface->state();
+                return {s.focused == 1 ? ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED : ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED};
+                }
+            case QAccessible::ScrollingEnd:
+                return {ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED};
+            case QAccessible::SelectionAdd:
+                return {ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED};
+            case QAccessible::NameChanged:
+            case QAccessible::TextAttributeChanged:
+            case QAccessible::TextColumnChanged:
+            case QAccessible::TextInserted:
+            case QAccessible::TextRemoved:
+            case QAccessible::TextUpdated:
+            case QAccessible::TextSelectionChanged:
+            case QAccessible::TextCaretMoved:
+                return {ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_TEXT_UPDATE};
+
+            default:
+                break;
+        }
+
+        return {};
+}
+
+
+class AccessibilityEventFilter : public QObject
+{
+protected:
+    bool eventFilter(QObject *obj, QEvent *event) override;
+};
+
+bool AccessibilityEventFilter::eventFilter(QObject *qObject, QEvent *event)
+{
+    switch (event->type()) {
+    case QEvent::Create: {
+        updateAccessibilityLater(qObject, QAccessible::ObjectCreated);
+        break;
+    }
+    case QEvent::Resize:
+        updateAccessibilityLater(qObject, QAccessible::LocationChanged);
+        break;
+    case QEvent::Move: {
+        // 由于鸿蒙无障碍框架接收的是基于XC的坐标,因此窗体位置移动不需要做更新
+        if (qObject->isWindowType()) {
+            break;
+        }
+        updateAccessibilityLater(qObject, QAccessible::LocationChanged);
+        break;
+    }
+    default:
+        break;
+    }
+
+    return QObject::eventFilter(qObject, event);
+}
+}
+
+QOhPlatformAccessibility::QOhPlatformAccessibility()
+{
+    QCoreApplication::instance()->installEventFilter(new AccessibilityEventFilter());
+}
+
+QOhPlatformAccessibility::~QOhPlatformAccessibility()
+{
+}
+
+static QAccessibleInterface *topLevelAccessibleInterface(QAccessibleInterface *accessible)
+{
+    auto *result = accessible;
+    while (result != nullptr && result->parent() != nullptr && result->parent()->role() != QAccessible::Application) {
+        result = result->parent();
+    }
+    return result;
+}
+// Handles accessibility update notifications.
+void QOhPlatformAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
+{
+    bool enable = QtOh::isEnvironmentVariableIsTrue("QT_ENABLE_ACCESSIBILITY", false);
+    if (!enable || !event)
+        return;
+
+    switch (event->type()) {
+        case QAccessible::PopupMenuStart:
+        QOhAccessibilityProvider::playSound("MenuStart");
+            break;
+        case QAccessible::MenuCommand:
+        QOhAccessibilityProvider::playSound("MenuCommand");
+            break;
+        case QAccessible::Alert:
+        QOhAccessibilityProvider::playSound("Alert");
+            break;
+        default:
+            break;
+    }
+
+    QAccessibleInterface *accessible = event->accessibleInterface();
+    if (accessible == nullptr) {
+        return;
+    }
+
+    if (!accessible->isValid()) {
+        if (event->type() == QAccessible::ObjectDestroyed) {
+            QOhAccessibleNode::removeNode(event->uniqueId());
+        }
+        return;
+    }
+
+    auto createNode = [](QAccessibleInterface *accessible) {
+        QOhAccessibleNode *node = nullptr;
+        if (QAccessibleCache::instance()->idForInterface(accessible) == 0)
+            return node;
+        auto parent = accessible->parent();
+        QAccessibleInterface *topLevel = topLevelAccessibleInterface(accessible);
+        QOhAccessibleNode *nodeParent = QOhAccessibleNode::find(topLevel);
+        QWindow *window = QOhWindowContext::windowForInterface(topLevel);
+        if (window != nullptr) {
+            window = QOhWindowContext::topLevelOf(window);
+            if (nodeParent == nullptr) {
+                nodeParent = new QOhAccessibleNode(window);
+            }
+            /* 创建顶层节点时,childCount可能不对, Qt bug?
+         *  QGraphicsScene scene;
+         *  QGraphicsView view(&scene);
+         *  QPushButton *pushButton = new QPushButton("ttt", &view);
+         *
+         *  QGraphicsView的child没有包含pushButton, 但pushButton的parent是QGraphicsView
+         *  因此需要在下面创建子节点
+         */
+            node = QOhAccessibleNode::find(accessible);
+            if (node == nullptr) {
+                node = new QOhAccessibleNode(window, accessible, nodeParent);
+            }
+        } else {
+            qWarning() << Q_FUNC_INFO << "create a11y node error";
+        }
+        return node;
+    };
+
+    QOhAccessibleNode *node = QOhAccessibleNode::find(accessible);
+    if (node == nullptr) {
+        if (event->type() == QAccessible::ObjectCreated || event->type() == QAccessible::ObjectShow) {
+            createNode(accessible);
+        }
+    }
+
+    if (node == nullptr) {
+        qDebug() << Q_FUNC_INFO << "get a11y node failed";
+        // error
+        return;
+    }
+
+    switch (event->type()) {
+    case QAccessible::ParentChanged:
+        QOhAccessibleNode::removeNode(event->uniqueId());
+        createNode(accessible);
+    default:
+        break;
+    }
+    auto accessibilityEvent = tryMapQAccessibleEventToAccessibilityEvent(event);
+    if (accessibilityEvent.has_value()) {
+        if (*accessibilityEvent == ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE) {
+            QOhAccessibilityProvider::notifyPageChange(event);
+        } else {
+            QOhAccessibilityProvider::processAccessibilityEvent(event, *accessibilityEvent);
+        }
+    }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/openharmony/accessibility/qohplatformaccessibility.h b/src/plugins/platforms/openharmony/accessibility/qohplatformaccessibility.h
new file mode 100644
index 00000000000..0b9b6f14783
--- /dev/null
+++ b/src/plugins/platforms/openharmony/accessibility/qohplatformaccessibility.h
@@ -0,0 +1,23 @@
+#ifndef QOHPLATFORMACCESSIBILITY_H
+#define QOHPLATFORMACCESSIBILITY_H
+
+#include <QtGui/qtguiglobal.h>
+#include <QtCore/QMultiHash>
+#if QT_CONFIG(accessibility)
+
+#include <qpa/qplatformaccessibility.h>
+
+QT_BEGIN_NAMESPACE
+class QOhPlatformAccessibility : public QPlatformAccessibility
+{
+public:
+    explicit QOhPlatformAccessibility();
+    virtual ~QOhPlatformAccessibility();
+    void notifyAccessibilityUpdate(QAccessibleEvent *event) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QOHPLATFORMACCESSIBILITY_H
diff --git a/src/plugins/platforms/openharmony/arkui/arkui.pri b/src/plugins/platforms/openharmony/arkui/arkui.pri
new file mode 100644
index 00000000000..51cbeb1f668
--- /dev/null
+++ b/src/plugins/platforms/openharmony/arkui/arkui.pri
@@ -0,0 +1,8 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+    $$PWD/qohdragevent.h
+
+
+SOURCES += \
+    $$PWD/qohdragevent.cpp
diff --git a/src/plugins/platforms/openharmony/arkui/qohdragevent.cpp b/src/plugins/platforms/openharmony/arkui/qohdragevent.cpp
new file mode 100644
index 00000000000..bbb51bdc161
--- /dev/null
+++ b/src/plugins/platforms/openharmony/arkui/qohdragevent.cpp
@@ -0,0 +1,119 @@
+#include "qohdragevent.h"
+#include "qohkeys.h"		/* Qt 6 add */
+#include "qohauxiliary.h"
+#include "qohobjectholder.h"
+#include <qopenharmonydefines.h>
+#include <database/udmf/udmf_meta.h>
+
+QT_BEGIN_NAMESPACE
+
+QOhDragEvent::QOhDragEvent(ArkUI_DragEvent *event)
+    : m_dragEvent(event)
+{
+
+}
+
+
+
+Qt::DropActions QOhDragEvent::actions() const
+{
+    ArkUI_DropOperation operation;
+    if (ARKUI_ERROR_CODE_NO_ERROR != OH_ArkUI_DragEvent_GetDropOperation(m_dragEvent, &operation))
+        return Qt::IgnoreAction;
+    return operation == ARKUI_DROP_OPERATION_COPY ?
+                Qt::CopyAction : Qt::MoveAction;
+}
+
+QPoint QOhDragEvent::touchPoint() const
+{
+    return {static_cast<int>(OH_ArkUI_DragEvent_GetTouchPointXToWindow(m_dragEvent)),
+                static_cast<int>(OH_ArkUI_DragEvent_GetTouchPointYToWindow(m_dragEvent))};
+}
+
+void QOhDragEvent::failed()
+{
+    OH_ArkUI_DragEvent_SetDragResult(m_dragEvent, ARKUI_DRAG_RESULT_FAILED);
+}
+
+void QOhDragEvent::setSuggestedDropOperation(Qt::DropAction action)
+{
+    OH_ArkUI_DragEvent_SetSuggestedDropOperation(m_dragEvent, Qt::CopyAction == action ?
+                                                     ::ArkUI_DropOperation::ARKUI_DROP_OPERATION_COPY :
+                                                     ::ArkUI_DropOperation::ARKUI_DROP_OPERATION_MOVE);
+}
+
+void QOhDragEvent::setResult(bool isAccepted)
+{
+    OH_ArkUI_DragEvent_SetDragResult(m_dragEvent, isAccepted ? ARKUI_DRAG_RESULT_SUCCESSFUL :
+                                                               ARKUI_DRAG_RESULT_CANCELED);
+}
+
+QStringList QOhDragEvent::types() const
+{
+    QStringList resultList;
+    int32_t typeCount(0);
+    int32_t result = OH_ArkUI_DragEvent_GetDataTypeCount(m_dragEvent, &typeCount);
+    if (ARKUI_ERROR_CODE_NO_ERROR != result) {
+        LOGE("call OH_ArkUI_DragEvent_GetDataTypeCount failed. error:[%{public}d]", result);
+        return resultList;
+    }
+
+    std::vector<std::unique_ptr<char[]>> buffers;
+    buffers.reserve(typeCount);
+    std::vector<char*> types;
+    types.reserve(typeCount);
+    for (int i = 0; i < typeCount; ++i) {
+        buffers.emplace_back(std::make_unique<char[]>(SCHAR_MAX));
+        types.push_back(buffers.back().get());
+    }
+
+    result = OH_ArkUI_DragEvent_GetDataTypes(m_dragEvent, types.data(), typeCount, SCHAR_MAX);
+    if (ARKUI_ERROR_CODE_NO_ERROR != result) {
+        LOGE("call OH_ArkUI_DragEvent_GetDataTypes failed. error:[%{public}d]", result);
+        return resultList;
+    }
+    
+    for (int i = 0; i < typeCount; ++i) {
+        const QString ohType = QString::fromUtf8(types.at(i));
+        if ((ohType == QString::fromUtf8(UDMF_META_GENERAL_FILE)) ||
+            (ohType == QString::fromUtf8(UDMF_META_IMAGE)) ||
+            (ohType == QString::fromUtf8(UDMF_META_VIDEO)))
+            resultList <<  QStringLiteral("text/uri-list");
+        else if ((ohType == QString::fromUtf8(UDMF_META_TEXT)) ||
+                 (ohType == QString::fromUtf8(UDMF_META_PLAIN_TEXT)) ||
+                 (ohType == QString::fromUtf8(UDMF_META_SCRIPT)))
+            resultList << QStringLiteral("text/plain");
+        else if (ohType == QString::fromUtf8(UDMF_META_HTML))
+            resultList << QStringLiteral("text/html");
+        else if (ohType == QString::fromUtf8(UDMF_META_OPENHARMONY_PIXEL_MAP))
+            resultList << QStringLiteral("application/x-qt-image");
+        else
+            resultList << ohType;
+    }
+    return resultList;
+}
+
+void QOhDragEvent::acquireDatas(QMimeData * const mimeData)
+{
+    QOhObjectHolder<OH_UdmfData> data(OH_UdmfData_Create, OH_UdmfData_Destroy);
+    OH_UdmfData *nativeData = data.object();
+    if (nativeData == nullptr)
+        return;
+    int32_t result = ARKUI_ERROR_CODE_NO_ERROR;
+    result = OH_ArkUI_DragEvent_GetUdmfData(m_dragEvent, nativeData);
+    if (result != ARKUI_ERROR_CODE_NO_ERROR) {
+        LOGE("OH_ArkUI_DragEvent_GetUdmfData failed: %{public}d", result);
+        return;
+    }
+    data.take();
+    QtOh::UdmfHelper::acquireDatasFromUdmfToMime(nativeData, mimeData);
+}
+/* Qt 6 only modify */
+Qt::KeyboardModifiers QOhDragEvent::keyboardModifiers() const
+{
+    uint64_t keys = 0;
+    OH_ArkUI_DragEvent_GetModifierKeyStates(m_dragEvent, &keys);
+    return QOhKeys::ohKeys2Qt(keys);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/arkui/qohdragevent.h b/src/plugins/platforms/openharmony/arkui/qohdragevent.h
new file mode 100644
index 00000000000..5baeec5db0c
--- /dev/null
+++ b/src/plugins/platforms/openharmony/arkui/qohdragevent.h
@@ -0,0 +1,36 @@
+#ifndef QOHDRAGEVENT_H
+#define QOHDRAGEVENT_H
+
+#include <QtCore/qnamespace.h>
+#include <arkui/drag_and_drop.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qpoint.h>
+
+QT_BEGIN_NAMESPACE
+class QMimeData;
+class QOhDragEvent
+{
+public:
+    QOhDragEvent(ArkUI_DragEvent *event);
+
+    Qt::DropActions actions() const;
+
+    QPoint touchPoint() const;
+
+    void failed();
+
+    void setSuggestedDropOperation(Qt::DropAction action);
+
+    void setResult(bool isAccepted);
+
+    Qt::KeyboardModifiers keyboardModifiers() const; /* Qt 6 only modify */
+
+    QStringList types() const;
+    void acquireDatas(QMimeData * const mimeData);
+private:
+    ArkUI_DragEvent *m_dragEvent;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHDRAGEVENT_H
diff --git a/src/plugins/platforms/openharmony/inputmethod/inputmethod.pri b/src/plugins/platforms/openharmony/inputmethod/inputmethod.pri
new file mode 100644
index 00000000000..f0d79c79a36
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/inputmethod.pri
@@ -0,0 +1,24 @@
+INCLUDEPATH += $$PWD
+
+LIBS += -lohinputmethod
+
+HEADERS += \
+    $$PWD/qohcontroller.h \
+    $$PWD/qohtexteditorproxy.h \
+    $$PWD/qohinputmethodproxy.h \
+    $$PWD/qohinputmethod.h \
+    $$PWD/qohattachoptions.h \
+    $$PWD/qohcursorinfo.h \
+    $$PWD/qohtextconfig.h \
+    $$PWD/qohtextavoidinfo.h
+
+SOURCES += \
+    $$PWD/qohcontroller.cpp \
+    $$PWD/qohtexteditorproxy.cpp \
+    $$PWD/qohinputmethodproxy.cpp \
+    $$PWD/qohinputmethod.cpp \
+    $$PWD/qohattachoptions.cpp \
+    $$PWD/qohcursorinfo.cpp \
+    $$PWD/qohtextconfig.cpp \
+    $$PWD/qohtextavoidinfo.cpp
+
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohattachoptions.cpp b/src/plugins/platforms/openharmony/inputmethod/qohattachoptions.cpp
new file mode 100644
index 00000000000..b7d5eef30ea
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohattachoptions.cpp
@@ -0,0 +1,41 @@
+#include "qohattachoptions.h"
+#include "qohinputmethod.h"
+#include <inputmethod/inputmethod_types_capi.h>
+
+QT_BEGIN_NAMESPACE
+namespace InputMethod
+{
+
+QOhAttachOptions::QOhAttachOptions(bool showKeyboard
+#if OHOS_SDK_VERSION > 14
+    , RequestKeyboardReason reason
+#endif
+        )
+#if OHOS_SDK_VERSION > 14
+    : m_options(new QOhObjectHolder<InputMethod_AttachOptions>(OH_AttachOptions_CreateWithRequestKeyboardReason, OH_AttachOptions_Destroy, showKeyboard, (InputMethod_RequestKeyboardReason)reason))
+#else
+    : m_options(new QOhObjectHolder<InputMethod_AttachOptions>(OH_AttachOptions_Create, OH_AttachOptions_Destroy, showKeyboard))
+#endif
+{
+
+}
+
+bool QOhAttachOptions::isShowKeyboard() const
+{
+    if (native() == nullptr)
+        return false;
+    bool result = false;
+    auto code = OH_AttachOptions_IsShowKeyboard(native(), &result);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("OH_AttachOptions_IsShowKeyboard failed: ", code);
+    }
+    return result;
+}
+
+InputMethod_AttachOptions *QOhAttachOptions::native() const
+{
+    return m_options->object();
+}
+
+};
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohattachoptions.h b/src/plugins/platforms/openharmony/inputmethod/qohattachoptions.h
new file mode 100644
index 00000000000..e2e80d128f7
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohattachoptions.h
@@ -0,0 +1,31 @@
+#ifndef QOHATTACHOPTIONS_H
+#define QOHATTACHOPTIONS_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qscopedpointer.h>
+#include <inputmethod/inputmethod_attach_options_capi.h>
+#include "qohinputmethod.h"
+#include "qohobjectholder.h"
+
+QT_BEGIN_NAMESPACE
+namespace InputMethod
+{
+class QOhAttachOptions
+{
+public:
+    QOhAttachOptions(bool showKeyboard = true
+        #if OHOS_SDK_VERSION > 14
+            , RequestKeyboardReason reason = RequestKeyboardReason::MOUSE
+        #endif
+            );
+
+    bool isShowKeyboard() const;
+
+    InputMethod_AttachOptions *native() const;
+private:
+    QScopedPointer<QOhObjectHolder<InputMethod_AttachOptions>> m_options;
+};
+
+};
+QT_END_NAMESPACE
+#endif // QOHATTACHOPTIONS_H
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohcontroller.cpp b/src/plugins/platforms/openharmony/inputmethod/qohcontroller.cpp
new file mode 100644
index 00000000000..faf93b02270
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohcontroller.cpp
@@ -0,0 +1,77 @@
+#include "qohcontroller.h"
+#include "qohinputmethod.h"
+#include "qohattachoptions.h"
+#include "qohtexteditorproxy.h"
+#include "qohinputmethodproxy.h"
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+namespace InputMethod {
+
+QOhController::QOhController()
+    : m_textEditorProxy(nullptr)
+    , m_inputMethodProxy(nullptr)
+{
+
+}
+
+QOhController::~QOhController()
+{
+    if (isAttached())
+        detach();
+    if (m_textEditorProxy != nullptr) {
+        delete m_textEditorProxy;
+        m_textEditorProxy = nullptr;
+    }
+}
+
+bool QOhController::isAttached() const
+{
+    return m_inputMethodProxy != nullptr;
+}
+
+bool QOhController::attach(const QOhAttachOptions &options)
+{
+    if (isAttached()) {
+        return true;
+    }
+    InputMethod_TextEditorProxy *teProxy = textEditorProxy()->native();
+    InputMethod_InputMethodProxy *inputMethodProxy = nullptr;
+    auto code = OH_InputMethodController_Attach(teProxy, options.native(), &inputMethodProxy);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("Input method controller attach failed: ", code);
+        return false;
+    }
+    m_inputMethodProxy = new QOhInputMethodProxy(inputMethodProxy);
+    return true;
+}
+
+bool QOhController::detach()
+{
+    if (!isAttached())
+        return true;
+    auto code = OH_InputMethodController_Detach(m_inputMethodProxy->native());
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("Input method controller detach failed: ", code);
+        return false;
+    }
+    delete m_inputMethodProxy;
+    m_inputMethodProxy = nullptr;
+    return true;
+}
+
+QOhInputMethodProxy *QOhController::inputMethodProxy() const
+{
+    return m_inputMethodProxy;
+}
+
+QOhTextEditorProxy *QOhController::textEditorProxy() const
+{
+    if (m_textEditorProxy == nullptr)
+        m_textEditorProxy = new QOhTextEditorProxy();
+    return m_textEditorProxy;
+}
+
+};
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohcontroller.h b/src/plugins/platforms/openharmony/inputmethod/qohcontroller.h
new file mode 100644
index 00000000000..ff3e6f723b6
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohcontroller.h
@@ -0,0 +1,38 @@
+#ifndef QOHCONTROLLER_H
+#define QOHCONTROLLER_H
+
+#include <inputmethod/inputmethod_controller_capi.h>
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace InputMethod {
+class QOhTextEditorProxy;
+class QOhAttachOptions;
+class QOhInputMethodProxy;
+
+class QOhController
+{
+public:
+    QOhController();
+    ~QOhController();
+
+    bool attach(const QOhAttachOptions &options);
+
+    bool isAttached() const;
+
+    bool detach();
+
+    QOhInputMethodProxy *inputMethodProxy() const;
+
+    QOhTextEditorProxy *textEditorProxy() const;
+
+private:
+    mutable QOhTextEditorProxy *m_textEditorProxy;
+    QOhInputMethodProxy *m_inputMethodProxy;
+};
+
+};
+QT_END_NAMESPACE
+
+#endif // QOHCONTROLLER_H
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohcursorinfo.cpp b/src/plugins/platforms/openharmony/inputmethod/qohcursorinfo.cpp
new file mode 100644
index 00000000000..a4e309f6918
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohcursorinfo.cpp
@@ -0,0 +1,33 @@
+#include "qohcursorinfo.h"
+
+QT_BEGIN_NAMESPACE
+namespace InputMethod
+{
+
+QOhCursorInfo::QOhCursorInfo(InputMethod_CursorInfo *info)
+{
+    m_cursorInfoObject.reset(new QOhObjectHolder<InputMethod_CursorInfo>(info));
+}
+
+QOhCursorInfo::QOhCursorInfo(double left, double top, double width, double height)
+{
+    m_cursorInfoObject.reset(new QOhObjectHolder<InputMethod_CursorInfo>(OH_CursorInfo_Create, OH_CursorInfo_Destroy, left, top, width, height));
+}
+
+QRectF QOhCursorInfo::boundingRect() const
+{
+    double left = 0;
+    double top = 0;
+    double width = 0;
+    double height = 0;
+    OH_CursorInfo_GetRect(m_cursorInfoObject->object(), &left, &top, &width, &height);
+    return QRectF(left, top, width, height);
+}
+
+InputMethod_CursorInfo *QOhCursorInfo::native() const
+{
+    return m_cursorInfoObject->object();
+}
+
+};
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohcursorinfo.h b/src/plugins/platforms/openharmony/inputmethod/qohcursorinfo.h
new file mode 100644
index 00000000000..3cd51f81b8d
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohcursorinfo.h
@@ -0,0 +1,28 @@
+#ifndef QOHCURSORINFO_H
+#define QOHCURSORINFO_H
+
+#include <QtCore/qglobal.h>
+#include <inputmethod/inputmethod_cursor_info_capi.h>
+#include <QtCore/qrect.h>
+#include <QScopedPointer>
+#include "qohobjectholder.h"
+
+QT_BEGIN_NAMESPACE
+namespace InputMethod
+{
+class QOhCursorInfo
+{
+public:
+    QOhCursorInfo(InputMethod_CursorInfo *info);
+    QOhCursorInfo(double left, double top, double width, double height);
+    QRectF boundingRect() const;
+
+    InputMethod_CursorInfo *native() const;
+
+private:
+    QScopedPointer<QOhObjectHolder<InputMethod_CursorInfo>> m_cursorInfoObject;
+};
+
+};
+QT_END_NAMESPACE
+#endif // QOHCURSORINFO_H
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohinputmethod.cpp b/src/plugins/platforms/openharmony/inputmethod/qohinputmethod.cpp
new file mode 100644
index 00000000000..18f01613c4e
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohinputmethod.cpp
@@ -0,0 +1,163 @@
+#include "qohinputmethod.h"
+
+#include <QHash>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+static QHash<InputMethod_ErrorCode, QString> errors = {
+    {IME_ERR_OK,             "Correct case"},
+    {IME_ERR_UNDEFINED,      "Error is undefined"},
+    {IME_ERR_PARAMCHECK,     "Parameter check failed"},
+    {IME_ERR_PACKAGEMANAGER, "The bundle manager error"},
+    {IME_ERR_IMENGINE,       "Input method engine error"},
+    {IME_ERR_IMCLIENT,       "Input method client error"},
+    {IME_ERR_CONFIG_PERSIST, "Configuration persistence error"},
+    {IME_ERR_CONTROLLER,     "Input method controller error"},
+    {IME_ERR_SETTINGS,       "Input method setting error"},
+    {IME_ERR_IMMS,           "Input method manager service error"},
+    {IME_ERR_DETACHED,       "Input method client detached"},
+    {IME_ERR_NULL_POINTER,   "Unexpected null pointer"},
+    {IME_ERR_QUERY_FAILED,   "Query failed"}
+};
+
+QString InputMethod::ErrorCode::toString(InputMethod_ErrorCode code)
+{
+    return errors.value(code, "Unknow error");
+}
+
+void InputMethod::ErrorCode::printErrorCode(const QString &message, InputMethod_ErrorCode code)
+{
+    qWarning() << QString("%1---code is: %2, error string is: %3").arg(message).arg(code).arg(toString(code));
+}
+
+
+/*!
+ * \brief Qt-鸿蒙平台下的EnterKey功能值映射
+ * \param type Qt下的EnterKey功能枚举值
+ * \return 返回Qt-鸿蒙的EnterKey功能映射值
+ */
+InputMethod_EnterKeyType InputMethod::ohEnterKeyType(Qt::EnterKeyType type)
+{
+    switch (type) {
+    case Qt::EnterKeyDone:
+        return IME_ENTER_KEY_DONE;
+    case Qt::EnterKeyDefault:
+        return IME_ENTER_KEY_NONE;
+    case Qt::EnterKeyReturn:
+        return IME_ENTER_KEY_NEWLINE;
+    case Qt::EnterKeyPrevious:
+        return IME_ENTER_KEY_PREVIOUS;
+    case Qt::EnterKeyGo:
+        return IME_ENTER_KEY_GO;
+    case Qt::EnterKeySend:
+        return IME_ENTER_KEY_SEND;
+    case Qt::EnterKeySearch:
+        return IME_ENTER_KEY_SEARCH;
+    case Qt::EnterKeyNext:
+        return IME_ENTER_KEY_NEXT;
+    default: break;
+    }
+    return IME_ENTER_KEY_UNSPECIFIED;
+}
+
+Qt::EnterKeyType InputMethod::qtEnterKeyType(InputMethod_EnterKeyType type)
+{
+    switch (type) {
+    case IME_ENTER_KEY_GO:
+        return Qt::EnterKeyGo;
+    case IME_ENTER_KEY_SEARCH:
+        return Qt::EnterKeySearch;
+    case IME_ENTER_KEY_PREVIOUS:
+        return Qt::EnterKeyPrevious;
+    case IME_ENTER_KEY_SEND:
+        return Qt::EnterKeySend;
+    case IME_ENTER_KEY_NEXT:
+        return Qt::EnterKeyNext;
+    case IME_ENTER_KEY_DONE:
+        return Qt::EnterKeyDone;
+    case IME_ENTER_KEY_NEWLINE:
+        return Qt::EnterKeyReturn;
+    default: break;
+    }
+    return Qt::EnterKeyDefault;
+}
+
+
+/*!
+ * \brief Qt-鸿蒙平台下的输入类型枚举值映射
+ * \param hints Qt下的枚举值
+ * \return 返回Qt-鸿蒙的输入类型映射值
+ */
+InputMethod_TextInputType InputMethod::ohTextInputType(Qt::InputMethodHints hints)
+{
+    /* FIXME Qt支持位运算,鸿蒙文本类型不支持位运算的枚举值 */
+    if(hints.testFlag(Qt::ImhMultiLine))    /* 多行文本类型 */
+        return IME_TEXT_INPUT_TYPE_MULTILINE;
+
+    if ((hints.testFlag(Qt::ImhDigitsOnly) ||
+         hints.testFlag(Qt::ImhFormattedNumbersOnly)) &&
+        hints.testFlag(Qt::ImhHiddenText))  /* 数字密码类型 */
+        return IME_TEXT_INPUT_TYPE_NUMBER_PASSWORD;
+    if (hints.testFlag(Qt::ImhPreferNumbers) ||
+        hints.testFlag(Qt::ImhDigitsOnly))   /* 数字类型 */
+        return IME_TEXT_INPUT_TYPE_NUMBER;
+
+    if (hints.testFlag(Qt::ImhDate) ||
+        hints.testFlag(Qt::ImhTime))    /* 日期类型 */
+        return IME_TEXT_INPUT_TYPE_DATETIME;
+
+    if (hints.testFlag(Qt::ImhHiddenText))  /* 密码类型 */
+        return IME_TEXT_INPUT_TYPE_VISIBLE_PASSWORD;
+
+    if (hints.testFlag(Qt::ImhDialableCharactersOnly)) /* 电话号码类型 */
+        return IME_TEXT_INPUT_TYPE_PHONE;
+
+    if (hints.testFlag(Qt::ImhEmailCharactersOnly)) /* 邮箱地址类型 */
+        return IME_TEXT_INPUT_TYPE_EMAIL_ADDRESS;
+
+    if (hints.testFlag(Qt::ImhUrlCharactersOnly))   /* 链接类型 */
+        return IME_TEXT_INPUT_TYPE_URL;
+
+    return IME_TEXT_INPUT_TYPE_TEXT; /* 默认文本类型 */
+}
+
+Qt::InputMethodHints InputMethod::qtInputMethodHints(InputMethod_TextInputType type)
+{
+    Qt::InputMethodHints result = Qt::ImhNone;
+    switch (type) {
+    case IME_TEXT_INPUT_TYPE_TEXT:
+        result = Qt::ImhNone;
+        break;
+    case IME_TEXT_INPUT_TYPE_MULTILINE:
+        result = Qt::ImhMultiLine;
+        break;
+    case IME_TEXT_INPUT_TYPE_NUMBER:
+        result = Qt::ImhDigitsOnly;
+        break;
+    case IME_TEXT_INPUT_TYPE_PHONE:
+        result = Qt::ImhDialableCharactersOnly;
+        break;
+    case IME_TEXT_INPUT_TYPE_DATETIME:
+        result = Qt::ImhTime | Qt::ImhDate;
+        break;
+    case IME_TEXT_INPUT_TYPE_EMAIL_ADDRESS:
+        result = Qt::ImhEmailCharactersOnly;
+        break;
+    case IME_TEXT_INPUT_TYPE_URL:
+        result = Qt::ImhUrlCharactersOnly;
+        break;
+    case IME_TEXT_INPUT_TYPE_VISIBLE_PASSWORD:
+    case IME_TEXT_INPUT_TYPE_NUMBER_PASSWORD:
+    case IME_TEXT_INPUT_TYPE_NEW_PASSWORD:
+        result = Qt::ImhHiddenText;
+        break;
+    default:
+        break;
+    }
+    return result;
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohinputmethod.h b/src/plugins/platforms/openharmony/inputmethod/qohinputmethod.h
new file mode 100644
index 00000000000..c76b8b94859
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohinputmethod.h
@@ -0,0 +1,38 @@
+#ifndef QOHINPUTMETHOD_H
+#define QOHINPUTMETHOD_H
+
+#include <inputmethod/inputmethod_types_capi.h>
+#include <QString>
+
+QT_BEGIN_NAMESPACE
+
+namespace InputMethod
+{
+namespace ErrorCode {
+
+QString toString(InputMethod_ErrorCode code);
+
+void printErrorCode(const QString &message, InputMethod_ErrorCode code);
+};
+
+InputMethod_EnterKeyType ohEnterKeyType(Qt::EnterKeyType type);
+Qt::EnterKeyType qtEnterKeyType(InputMethod_EnterKeyType type);
+
+InputMethod_TextInputType ohTextInputType(Qt::InputMethodHints hints);
+Qt::InputMethodHints qtInputMethodHints(InputMethod_TextInputType type);
+
+enum class RequestKeyboardReason {
+    NONE = 0,
+
+    MOUSE = 1,
+
+    TOUCH = 2,
+
+    OTHER = 20
+};
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHINPUTMETHOD_H
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohinputmethodproxy.cpp b/src/plugins/platforms/openharmony/inputmethod/qohinputmethodproxy.cpp
new file mode 100644
index 00000000000..4675f980a2e
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohinputmethodproxy.cpp
@@ -0,0 +1,95 @@
+#include "qohinputmethodproxy.h"
+#include "qohinputmethod.h"
+#include "qohcursorinfo.h"
+#if OHOS_SDK_VERSION > 14
+#include "qohattachoptions.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+namespace InputMethod
+{
+
+QOhInputMethodProxy::QOhInputMethodProxy(InputMethod_InputMethodProxy *inputMethodProxy)
+    : m_inputMethodProxyObject(new QOhObjectHolder<InputMethod_InputMethodProxy>(inputMethodProxy))
+{
+
+}
+
+InputMethod_InputMethodProxy *QOhInputMethodProxy::native() const
+{
+    return m_inputMethodProxyObject->object();
+}
+
+bool QOhInputMethodProxy::notifyConfigurationChanged(Qt::EnterKeyType enterKeyType, Qt::InputMethodHints hints)
+{
+    if (native() == nullptr)
+        return false;
+    auto code = OH_InputMethodProxy_NotifyConfigurationChange(native(), InputMethod::ohEnterKeyType(enterKeyType),
+                                                              InputMethod::ohTextInputType(hints));
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("notify configuration change failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+bool QOhInputMethodProxy::notifySelectionChanged(const QString &text, int start, int end)
+{
+    if (native() == nullptr)
+        return false;
+    auto data = reinterpret_cast<char16_t *>(const_cast<ushort*>(text.utf16()));
+    auto code = OH_InputMethodProxy_NotifySelectionChange(native(), data,
+                                                              text.length() * sizeof(char16_t), start, end);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("notify selection change failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+bool QOhInputMethodProxy::notifyCursorUpdate(const QOhCursorInfo &info)
+{
+    auto native_info = info.native();
+    if (native() == nullptr || native_info == nullptr)
+        return false;
+    auto code = OH_InputMethodProxy_NotifyCursorUpdate(native(), native_info);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("notify selection change failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+bool QOhInputMethodProxy::showKeyboard()
+{
+    auto code = OH_InputMethodProxy_ShowKeyboard(native());
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("show keyboard failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+bool QOhInputMethodProxy::hideKeyboard()
+{
+    auto code = OH_InputMethodProxy_HideKeyboard(native());
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("hide keyboard failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+#if OHOS_SDK_VERSION > 14
+bool QOhInputMethodProxy::showTextInput(const QOhAttachOptions &options)
+{
+    auto code = OH_InputMethodProxy_ShowTextInput(native(), options.native());
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("show text input failed: ", code);
+        return false;
+    }
+    return true;
+}
+#endif
+};
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohinputmethodproxy.h b/src/plugins/platforms/openharmony/inputmethod/qohinputmethodproxy.h
new file mode 100644
index 00000000000..d5d59501250
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohinputmethodproxy.h
@@ -0,0 +1,39 @@
+#ifndef QOHINPUTMETHODPROXY_H
+#define QOHINPUTMETHODPROXY_H
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qscopedpointer.h>
+#include <inputmethod/inputmethod_controller_capi.h>
+#include "qohobjectholder.h"
+
+QT_BEGIN_NAMESPACE
+namespace InputMethod
+{
+class QOhCursorInfo;
+#if OHOS_SDK_VERSION > 14
+class QOhAttachOptions;
+#endif
+class QOhInputMethodProxy
+{
+public:
+    QOhInputMethodProxy(InputMethod_InputMethodProxy *inputMethodProxy);
+
+    InputMethod_InputMethodProxy *native() const;
+
+    bool notifyConfigurationChanged(Qt::EnterKeyType enterKeyType, Qt::InputMethodHints hints);
+
+    bool notifySelectionChanged(const QString &text, int start, int end);
+
+    bool notifyCursorUpdate(const QOhCursorInfo &info);
+    bool showKeyboard();
+    bool hideKeyboard();
+#if OHOS_SDK_VERSION > 14
+    bool showTextInput(const QOhAttachOptions &options);
+#endif
+private:
+    QScopedPointer<QOhObjectHolder<InputMethod_InputMethodProxy>> m_inputMethodProxyObject;
+};
+
+};
+QT_END_NAMESPACE
+#endif // QOHINPUTMETHODPROXY_H
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohtextavoidinfo.cpp b/src/plugins/platforms/openharmony/inputmethod/qohtextavoidinfo.cpp
new file mode 100644
index 00000000000..30b6b746f6c
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohtextavoidinfo.cpp
@@ -0,0 +1,75 @@
+#include "qohtextavoidinfo.h"
+#include "qohinputmethod.h"
+
+QT_BEGIN_NAMESPACE
+namespace InputMethod
+{
+
+QOhTextAvoidInfo::QOhTextAvoidInfo(InputMethod_TextAvoidInfo *info)
+    : m_textAvoidInfoObject(new QOhObjectHolder<InputMethod_TextAvoidInfo>(info))
+{
+
+}
+
+QOhTextAvoidInfo::QOhTextAvoidInfo(double positionY, double height)
+    : m_textAvoidInfoObject(new QOhObjectHolder<InputMethod_TextAvoidInfo>(OH_TextAvoidInfo_Create, OH_TextAvoidInfo_Destroy, positionY, height))
+{
+}
+
+InputMethod_TextAvoidInfo *QOhTextAvoidInfo::native() const
+{
+    return m_textAvoidInfoObject->object();
+}
+
+bool QOhTextAvoidInfo::setPositionY(double positionY)
+{
+    if (native() == nullptr)
+        return false;
+    auto code = OH_TextAvoidInfo_SetPositionY(native(), positionY);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("set text avoid position y failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+double QOhTextAvoidInfo::positionY() const
+{
+    if (native() == nullptr)
+        return -1;
+    double _positionY = -1;
+    auto code = OH_TextAvoidInfo_GetPositionY(native(), &_positionY);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("get text avoid position y failed: ", code);
+        return _positionY;
+    }
+    return _positionY;
+}
+
+bool QOhTextAvoidInfo::setHeight(double height)
+{
+    if (native() == nullptr)
+        return false;
+    auto code = OH_TextAvoidInfo_SetHeight(native(), height);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("set text avoid height failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+double QOhTextAvoidInfo::height() const
+{
+    if (native() == nullptr)
+        return -1;
+    double _height = -1;
+    auto code = OH_TextAvoidInfo_GetHeight(native(), &_height);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("get text avoid heigh failed: ", code);
+        return _height;
+    }
+    return _height;
+}
+
+};
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohtextavoidinfo.h b/src/plugins/platforms/openharmony/inputmethod/qohtextavoidinfo.h
new file mode 100644
index 00000000000..8593cd3e9d6
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohtextavoidinfo.h
@@ -0,0 +1,33 @@
+#ifndef QOHTEXTAVOIDINFO_H
+#define QOHTEXTAVOIDINFO_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qscopedpointer.h>
+#include <inputmethod/inputmethod_text_avoid_info_capi.h>
+#include "qohobjectholder.h"
+
+QT_BEGIN_NAMESPACE
+namespace InputMethod
+{
+class QOhTextAvoidInfo
+{
+public:
+    QOhTextAvoidInfo(InputMethod_TextAvoidInfo *info);
+    QOhTextAvoidInfo(double positionY, double height);
+
+    InputMethod_TextAvoidInfo *native() const;
+
+    bool setPositionY(double positionY);
+    double positionY() const;
+
+    bool setHeight(double height);
+    double height() const;
+
+private:
+    QScopedPointer<QOhObjectHolder<InputMethod_TextAvoidInfo>> m_textAvoidInfoObject;
+};
+
+};
+QT_END_NAMESPACE
+#endif // QOHTEXTAVOIDINFO_H
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohtextconfig.cpp b/src/plugins/platforms/openharmony/inputmethod/qohtextconfig.cpp
new file mode 100644
index 00000000000..67e27481791
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohtextconfig.cpp
@@ -0,0 +1,176 @@
+#include "qohtextconfig.h"
+#include "qohinputmethod.h"
+#include "qohcursorinfo.h"
+#include "qohtextavoidinfo.h"
+
+QT_BEGIN_NAMESPACE
+namespace InputMethod
+{
+
+QOhTextConfig::QOhTextConfig(InputMethod_TextConfig *config)
+{
+    if (config == nullptr)
+        m_configObject.reset(new QOhObjectHolder<InputMethod_TextConfig>(OH_TextConfig_Create, OH_TextConfig_Destroy));
+    else
+        m_configObject.reset(new QOhObjectHolder<InputMethod_TextConfig>(config));
+}
+
+bool QOhTextConfig::setInputType(Qt::InputMethodHints hints)
+{
+    if (native() == nullptr)
+        return false;
+    auto code = OH_TextConfig_SetInputType(native(), InputMethod::ohTextInputType(hints));
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("set config input type failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+Qt::InputMethodHints QOhTextConfig::inputType() const
+{
+    if (native() == nullptr)
+        return Qt::ImhNone;
+    InputMethod_TextInputType type = IME_TEXT_INPUT_TYPE_NONE;
+    auto code = OH_TextConfig_GetInputType(native(), &type);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("get config input type failed: ", code);
+        return Qt::ImhNone;
+    }
+    return InputMethod::qtInputMethodHints(type);
+}
+
+bool QOhTextConfig::setEnterKeyType(Qt::EnterKeyType enterKeyType)
+{
+    if (native() == nullptr)
+        return false;
+    auto code = OH_TextConfig_SetEnterKeyType(native(), InputMethod::ohEnterKeyType(enterKeyType));
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("set config enter key type failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+Qt::EnterKeyType QOhTextConfig::enterKeyType() const
+{
+    if (native() == nullptr)
+        return Qt::EnterKeyDefault;
+    InputMethod_EnterKeyType type = IME_ENTER_KEY_NONE;
+    auto code = OH_TextConfig_GetEnterKeyType(native(), &type);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("get config enter key type failed: ", code);
+        return Qt::EnterKeyDefault;
+    }
+    return InputMethod::qtEnterKeyType(type);
+}
+
+bool QOhTextConfig::setPreviewTextSupport(bool support)
+{
+    if (native() == nullptr)
+        return false;
+    auto code = OH_TextConfig_SetPreviewTextSupport(native(), support);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("set preview text support failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+bool QOhTextConfig::isPreviewTextSupport() const
+{
+    if (native() == nullptr)
+        return false;
+    bool result = false;
+    auto code = OH_TextConfig_IsPreviewTextSupported(native(), &result);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("get preview text support failed: ", code);
+        return false;
+    }
+    return result;
+}
+
+QOhCursorInfo *QOhTextConfig::cursorInfo() const
+{
+    if (native() == nullptr)
+        return nullptr;
+    InputMethod_CursorInfo *info = nullptr;
+    auto code = OH_TextConfig_GetCursorInfo(native(), &info);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("get cursor info failed: ", code);
+        return nullptr;
+    }
+    return new QOhCursorInfo(info);
+}
+
+QOhTextAvoidInfo *QOhTextConfig::textAvoidInfo() const
+{
+    if (native() == nullptr)
+        return nullptr;
+    InputMethod_TextAvoidInfo *info = nullptr;
+    auto code = OH_TextConfig_GetTextAvoidInfo(native(), &info);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("get text avoid info failed: ", code);
+        return nullptr;
+    }
+    return new QOhTextAvoidInfo(info);
+}
+
+bool QOhTextConfig::setSelection(int32_t start, int32_t end)
+{
+    if (native() == nullptr)
+        return false;
+    auto code = OH_TextConfig_SetSelection(native(), start, end);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("set selection failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+std::pair<int32_t, int32_t> QOhTextConfig::selection() const
+{
+    if (native() == nullptr)
+        return {0, 0};
+    int32_t start = 0;
+    int32_t end = 0;
+    auto code = OH_TextConfig_GetSelection(native(), &start, &end);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("get selection failed: ", code);
+        return {0, 0};
+    }
+    return { start, end };
+}
+
+bool QOhTextConfig::setWindowId(int32_t id)
+{
+    if (native() == nullptr)
+        return false;
+    auto code = OH_TextConfig_SetWindowId(native(), id);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("set window id failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+int32_t QOhTextConfig::windowId() const
+{
+    if (native() == nullptr)
+        return -1;
+    int32_t id = -1;
+    auto code = OH_TextConfig_GetWindowId(native(), &id);
+    if (code != IME_ERR_OK) {
+        InputMethod::ErrorCode::printErrorCode("get window id failed: ", code);
+    }
+    return id;
+}
+
+InputMethod_TextConfig *QOhTextConfig::native() const
+{
+    return m_configObject->object();
+}
+
+
+};
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohtextconfig.h b/src/plugins/platforms/openharmony/inputmethod/qohtextconfig.h
new file mode 100644
index 00000000000..77b32b0223e
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohtextconfig.h
@@ -0,0 +1,48 @@
+#ifndef QOHTEXTCONFIG_H
+#define QOHTEXTCONFIG_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qscopedpointer.h>
+#include <inputmethod/inputmethod_text_config_capi.h>
+#include "qohobjectholder.h"
+
+QT_BEGIN_NAMESPACE
+namespace InputMethod
+{
+class QOhCursorInfo;
+class QOhTextAvoidInfo;
+
+class QOhTextConfig
+{
+public:
+    QOhTextConfig(InputMethod_TextConfig *config = nullptr);
+
+    bool setInputType(Qt::InputMethodHints hints);
+    Qt::InputMethodHints inputType() const;
+
+    bool setEnterKeyType(Qt::EnterKeyType enterKeyType);
+    Qt::EnterKeyType enterKeyType() const;
+
+    bool setPreviewTextSupport(bool support);
+    bool isPreviewTextSupport() const;
+
+    QOhCursorInfo *cursorInfo() const;
+    QOhTextAvoidInfo *textAvoidInfo() const;
+
+    bool setSelection(int32_t start, int32_t end);
+    std::pair<int32_t, int32_t> selection() const;
+
+    bool setWindowId(int32_t id);
+    int32_t windowId() const;
+
+    InputMethod_TextConfig *native() const;
+
+private:
+    QScopedPointer<QOhObjectHolder<InputMethod_TextConfig>> m_configObject;
+};
+
+};
+
+QT_END_NAMESPACE
+#endif // QOHTEXTCONFIG_H
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohtexteditorproxy.cpp b/src/plugins/platforms/openharmony/inputmethod/qohtexteditorproxy.cpp
new file mode 100644
index 00000000000..a72e71b4f14
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohtexteditorproxy.cpp
@@ -0,0 +1,254 @@
+#include "qohtexteditorproxy.h"
+#include <QHash>
+#include <QGuiApplication>
+#include <QInputMethodQueryEvent>
+#include "qohauxiliary.h"
+#include "qohtextconfig.h"
+
+QT_BEGIN_NAMESPACE
+
+static QHash<InputMethod_TextEditorProxy *, InputMethod::QOhTextEditorProxy *> g_editors;
+
+namespace InputMethod
+{
+
+QOhTextEditorProxy::QOhTextEditorProxy()
+{
+   create();
+}
+
+QOhTextEditorProxy::~QOhTextEditorProxy()
+{
+    destroy();
+}
+
+InputMethod_TextEditorProxy *QOhTextEditorProxy::native() const
+{
+    return m_textEditorProxyObject->object();
+}
+
+bool QOhTextEditorProxy::isKeyboardVisible() const
+{
+    return m_keyboardVisible;
+}
+
+bool QOhTextEditorProxy::create()
+{
+    m_textEditorProxyObject.reset(new QOhObjectHolder<InputMethod_TextEditorProxy>(OH_TextEditorProxy_Create, OH_TextEditorProxy_Destroy));
+    auto textEditorProxy = m_textEditorProxyObject->object();
+    if (textEditorProxy == nullptr)
+        return false;
+    g_editors.insert(textEditorProxy, this);
+    OH_TextEditorProxy_SetSendKeyboardStatusFunc(textEditorProxy, &QOhTextEditorProxy::keyboardStatusChangeCallback);
+    OH_TextEditorProxy_SetDeleteBackwardFunc(textEditorProxy, &QOhTextEditorProxy::deleteBackwardCallback);
+    OH_TextEditorProxy_SetDeleteForwardFunc(textEditorProxy, &QOhTextEditorProxy::deleteForwardCallback);
+    OH_TextEditorProxy_SetInsertTextFunc(textEditorProxy, &QOhTextEditorProxy::insertTextCallback);
+    OH_TextEditorProxy_SetMoveCursorFunc(textEditorProxy, &QOhTextEditorProxy::moveCursorCallback);
+    OH_TextEditorProxy_SetSetPreviewTextFunc(textEditorProxy, &QOhTextEditorProxy::setPreviewTextCallback);
+    OH_TextEditorProxy_SetGetTextConfigFunc(textEditorProxy, &QOhTextEditorProxy::getTextConfigCallback);
+    OH_TextEditorProxy_SetSendEnterKeyFunc(textEditorProxy, &QOhTextEditorProxy::sendEnterKeyCallback);
+    OH_TextEditorProxy_SetHandleSetSelectionFunc(textEditorProxy, &QOhTextEditorProxy::handleSetSelectionCallback);
+    OH_TextEditorProxy_SetHandleExtendActionFunc(textEditorProxy, &QOhTextEditorProxy::handleExtendActionCallback);
+    OH_TextEditorProxy_SetGetLeftTextOfCursorFunc(textEditorProxy, &QOhTextEditorProxy::getLeftTextOfCursorCallback);
+    OH_TextEditorProxy_SetGetRightTextOfCursorFunc(textEditorProxy, &QOhTextEditorProxy::getRightTextOfCursorCallback);
+    OH_TextEditorProxy_SetGetTextIndexAtCursorFunc(textEditorProxy, &QOhTextEditorProxy::getTextIndexAtCursorCallback);
+    OH_TextEditorProxy_SetReceivePrivateCommandFunc(textEditorProxy, &QOhTextEditorProxy::receivePrivateCommandCallback);
+    OH_TextEditorProxy_SetFinishTextPreviewFunc(textEditorProxy, &QOhTextEditorProxy::finishTextPreviewCallback);
+    return true;
+}
+
+void QOhTextEditorProxy::destroy()
+{
+    g_editors.remove(native());
+}
+
+void QOhTextEditorProxy::setKeyboardVisible(bool visible)
+{
+    if (m_keyboardVisible == visible)
+        return;
+    m_keyboardVisible = visible;
+    emit keyboardVisibleChanged();
+}
+
+void QOhTextEditorProxy::keyboardStatusChangeCallback(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_KeyboardStatus keyboardStatus)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return;
+    proxy->setKeyboardVisible(keyboardStatus == IME_KEYBOARD_STATUS_SHOW);
+}
+
+void QOhTextEditorProxy::deleteBackwardCallback(InputMethod_TextEditorProxy *textEditorProxy, int32_t length)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return;
+    proxy->deleteBackward(length);
+}
+
+void QOhTextEditorProxy::deleteForwardCallback(InputMethod_TextEditorProxy *textEditorProxy, int32_t length)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return;
+    proxy->deleteForward(length);
+}
+
+void QOhTextEditorProxy::insertTextCallback(InputMethod_TextEditorProxy *textEditorProxy, const char16_t *text, size_t length)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return;
+    proxy->commitText(QString::fromUtf16(text, length));
+}
+
+void QOhTextEditorProxy::moveCursorCallback(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_Direction direction)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return;
+    proxy->moveCursor(direction);
+}
+
+void QOhTextEditorProxy::sendEnterKeyCallback(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_EnterKeyType enterKeyType)
+{
+    Q_UNUSED(enterKeyType)
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return;
+    proxy->enterKeyDown();
+}
+
+int32_t QOhTextEditorProxy::setPreviewTextCallback(InputMethod_TextEditorProxy *textEditorProxy, const char16_t text[], size_t length, int32_t start, int32_t end)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return -1;
+    proxy->preeditText(QString::fromUtf16(text, length));
+    return 0;
+}
+
+void QOhTextEditorProxy::getTextConfigCallback(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_TextConfig *config)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return;
+
+    QOhTextConfig textConfig(config);
+    textConfig.setPreviewTextSupport(QtOh::isEnvironmentVariableIsTrue("QT_INPUTMETHOD_PREVIEW_TEXT_SUPPORT"));
+}
+
+void QOhTextEditorProxy::handleSetSelectionCallback(InputMethod_TextEditorProxy *textEditorProxy, int32_t start, int32_t end)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return;
+}
+
+void QOhTextEditorProxy::handleExtendActionCallback(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_ExtendAction action)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return;
+}
+
+void QOhTextEditorProxy::getLeftTextOfCursorCallback(InputMethod_TextEditorProxy *textEditorProxy, int32_t number, char16_t text[], size_t *length)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return;
+
+    QString beforeText = QtOh::runOnQtMainThreadWithResult([] {
+        QObject *input = qGuiApp->focusObject();
+        if (!input)
+            return QString();
+        QInputMethodQueryEvent query(Qt::ImTextBeforeCursor);
+        QCoreApplication::sendEvent(input, &query);
+        QVariant result = query.value(Qt::ImTextBeforeCursor);
+        QString text;
+        if (result.isValid()) {
+            text = result.toString();
+        } else {
+            QInputMethodQueryEvent query =QInputMethodQueryEvent(Qt::ImCursorPosition | Qt::ImSurroundingText); /* Qt 6 only modify */
+            QCoreApplication::sendEvent(input, &query);
+            const int cursorPos = query.value(Qt::ImCursorPosition).toInt();
+            text = query.value(Qt::ImSurroundingText).toString().left(cursorPos);
+        }
+        return text;
+    });
+    if (beforeText.isEmpty())
+        return;
+    const char16_t *data = reinterpret_cast<const char16_t *>(beforeText.utf16());
+    size_t l = qMin(number, beforeText.length());
+    *length = l;
+    memcpy(text, data, l);
+    Q_EMIT proxy->updateCursor();
+}
+
+void QOhTextEditorProxy::getRightTextOfCursorCallback(InputMethod_TextEditorProxy *textEditorProxy, int32_t number, char16_t text[], size_t *length)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return;
+
+    QString afterText = QtOh::runOnQtMainThreadWithResult([] {
+        QObject *input = qGuiApp->focusObject();
+        if (!input)
+            return QString();
+        QInputMethodQueryEvent query(Qt::ImTextAfterCursor);
+        QCoreApplication::sendEvent(input, &query);
+        QVariant result = query.value(Qt::ImTextAfterCursor);
+        QString text;
+        if (result.isValid()) {
+            text = result.toString();
+        } else {
+            QInputMethodQueryEvent query = QInputMethodQueryEvent(Qt::ImCursorPosition | Qt::ImSurroundingText); /* Qt 6 only modify */
+            QCoreApplication::sendEvent(input, &query);
+            const int cursorPos = query.value(Qt::ImCursorPosition).toInt();
+            text = query.value(Qt::ImSurroundingText).toString().mid(cursorPos);
+        }
+        return text;
+    });
+    if (afterText.isEmpty())
+        return;
+    const char16_t *data = reinterpret_cast<const char16_t *>(afterText.utf16());
+    size_t l = qMin(number, afterText.length());
+    *length = l;
+    memcpy(text, data, l);
+}
+
+int32_t QOhTextEditorProxy::getTextIndexAtCursorCallback(InputMethod_TextEditorProxy *textEditorProxy)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return -1;
+    int32_t result = QtOh::runOnQtMainThreadWithResult([] {
+        QObject *input = qGuiApp->focusObject();
+        if (!input)
+            return 0;
+        QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImSurroundingText); /* Qt 6 only modify */
+        QCoreApplication::sendEvent(input, &query);
+        const int cursorPos = query.value(Qt::ImCursorPosition).toInt();
+        return cursorPos;
+    });
+    return result;
+}
+
+int32_t QOhTextEditorProxy::receivePrivateCommandCallback(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_PrivateCommand *privateCommand[], size_t size)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return -1;
+    return 0;
+}
+
+void QOhTextEditorProxy::finishTextPreviewCallback(InputMethod_TextEditorProxy *textEditorProxy)
+{
+    QOhTextEditorProxy *proxy = g_editors.value(textEditorProxy);
+    if (proxy == nullptr)
+        return;
+    proxy->finishTextPreview();
+}
+
+};
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/inputmethod/qohtexteditorproxy.h b/src/plugins/platforms/openharmony/inputmethod/qohtexteditorproxy.h
new file mode 100644
index 00000000000..36742f38f5a
--- /dev/null
+++ b/src/plugins/platforms/openharmony/inputmethod/qohtexteditorproxy.h
@@ -0,0 +1,60 @@
+#ifndef QOHTEXTEDITORPROXY_H
+#define QOHTEXTEDITORPROXY_H
+
+#include <QObject>
+#include <QScopedPointer>
+#include <inputmethod/inputmethod_text_editor_proxy_capi.h>
+#include "qohobjectholder.h"
+
+QT_BEGIN_NAMESPACE
+namespace InputMethod
+{
+class QOhTextEditorProxy : public QObject
+{
+    Q_OBJECT
+public:
+    QOhTextEditorProxy();
+    ~QOhTextEditorProxy();
+
+    InputMethod_TextEditorProxy *native() const;
+
+    bool isKeyboardVisible() const;
+
+    bool create();
+    void destroy();
+
+signals:
+    void updateCursor();
+    void keyboardVisibleChanged();
+    void deleteBackward(int length);
+    void deleteForward(int length);
+    void commitText(const QString &text);
+    void preeditText(const QString &text);
+    void moveCursor(int direction);
+    void enterKeyDown();
+    void finishTextPreview();
+private:
+    void setKeyboardVisible(bool visible);
+    static void keyboardStatusChangeCallback(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_KeyboardStatus keyboardStatus);
+    static void deleteBackwardCallback(InputMethod_TextEditorProxy *textEditorProxy, int32_t length);
+    static void deleteForwardCallback(InputMethod_TextEditorProxy *textEditorProxy, int32_t length);
+    static void insertTextCallback(InputMethod_TextEditorProxy *textEditorProxy, const char16_t *text, size_t length);
+    static void moveCursorCallback(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_Direction direction);
+    static void sendEnterKeyCallback(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_EnterKeyType enterKeyType);
+    static int32_t setPreviewTextCallback(InputMethod_TextEditorProxy *textEditorProxy, const char16_t text[], size_t length, int32_t start, int32_t end);
+    static void getTextConfigCallback(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_TextConfig *config);
+    static void handleSetSelectionCallback(InputMethod_TextEditorProxy *textEditorProxy, int32_t start, int32_t end);
+    static void handleExtendActionCallback(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_ExtendAction action);
+    static void getLeftTextOfCursorCallback(InputMethod_TextEditorProxy *textEditorProxy, int32_t number, char16_t text[], size_t *length);
+    static void getRightTextOfCursorCallback(InputMethod_TextEditorProxy *textEditorProxy, int32_t number, char16_t text[], size_t *length);
+    static int32_t getTextIndexAtCursorCallback(InputMethod_TextEditorProxy *textEditorProxy);
+    static int32_t receivePrivateCommandCallback(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_PrivateCommand *privateCommand[], size_t size);
+    static void finishTextPreviewCallback(InputMethod_TextEditorProxy *textEditorProxy);
+private:
+    QScopedPointer<QOhObjectHolder<InputMethod_TextEditorProxy>> m_textEditorProxyObject;
+    bool m_keyboardVisible = false;
+};
+
+};
+QT_END_NAMESPACE
+#endif // QOHTEXTEDITORPROXY_H
diff --git a/src/plugins/platforms/openharmony/jsclass/jsclass.pri b/src/plugins/platforms/openharmony/jsclass/jsclass.pri
new file mode 100644
index 00000000000..07852b11db4
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/jsclass.pri
@@ -0,0 +1,47 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+    $$PWD/qjsability.h \
+    $$PWD/qjsabilityfactory.h \
+    $$PWD/qjsabilitystage.h \
+    $$PWD/qjsaccessmanager.h \
+    $$PWD/qjsdisplay.h \
+    $$PWD/qjsscreen.h \
+    $$PWD/qjsdeviceinfo.h \
+    $$PWD/qjsuiability.h \
+    $$PWD/qjsbasecontext.h \
+    $$PWD/qjscontext.h \
+    $$PWD/qjsapplicationcontext.h \
+    $$PWD/qjsuiabilitycontext.h \
+    $$PWD/qjsuiextensionability.h \
+    $$PWD/qjsuiextensioncontext.h \
+    $$PWD/qjsuiextensioncontextsession.h \
+    $$PWD/qjswant.h \
+    $$PWD/qjswindowproxy.h \
+    $$PWD/qjswindowstage.h \
+    $$PWD/qjscursor.h \
+    $$PWD/qjssettings.h \
+    $$PWD/qjsabilityinfo.h
+
+SOURCES += \
+    $$PWD/qjsability.cpp \
+    $$PWD/qjsabilityfactory.cpp \
+    $$PWD/qjsabilitystage.cpp \
+    $$PWD/qjsaccessmanager.cpp \
+    $$PWD/qjsdisplay.cpp \
+    $$PWD/qjsscreen.cpp \
+    $$PWD/qjsdeviceinfo.cpp \
+    $$PWD/qjsuiability.cpp \
+    $$PWD/qjsbasecontext.cpp \
+    $$PWD/qjscontext.cpp \
+    $$PWD/qjsapplicationcontext.cpp \
+    $$PWD/qjsuiabilitycontext.cpp \
+    $$PWD/qjsuiextensionability.cpp \
+    $$PWD/qjsuiextensioncontext.cpp \
+    $$PWD/qjsuiextensioncontextsession.cpp \
+    $$PWD/qjswant.cpp \
+    $$PWD/qjswindowproxy.cpp \
+    $$PWD/qjswindowstage.cpp \
+    $$PWD/qjscursor.cpp \
+    $$PWD/qjssettings.cpp \
+    $$PWD/qjsabilityinfo.cpp
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsability.cpp b/src/plugins/platforms/openharmony/jsclass/qjsability.cpp
new file mode 100644
index 00000000000..d6bc609274a
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsability.cpp
@@ -0,0 +1,111 @@
+#include "qjswant.h"
+#include "qjsability.h"
+#include "qjscontext.h"
+#include "qjsuiability.h"
+#include "qohnativewindowmanager.h"
+#include <private/qopenharmony_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QJsAbility::QJsAbility(Napi::Object jsUIAbility)
+    : QJsObject(jsUIAbility)
+    , m_context(nullptr)
+    , m_want(nullptr)
+    , m_canTerminateSelf(true)
+{
+    setOnDestroy();
+}
+
+QJsAbility::~QJsAbility()
+{
+    QtOh::runOnJsUIThreadAndWait([this]{
+        if (!m_onDestroy.IsEmpty()) {
+            set("onDestroy", m_onDestroy.Value());
+            m_onDestroy.Reset();
+        }
+    });
+}
+
+QString QJsAbility::name() const
+{
+    return QtOh::runOnJsUIThreadWithResult([this]{
+        auto want = launchWant();
+        QString result;
+        if (want != nullptr) {
+            result = want->windowName();
+        }
+        if (result.isEmpty())
+            result = QJsWant::defaultWindowName;
+        return result;
+    });
+}
+
+Napi::Value QJsAbility::newLocalStorage() const
+{
+    return call("newLocalStorage");
+}
+
+QString QJsAbility::loadContentUrl() const
+{
+    return QtOh::runOnJsUIThreadWithResult([this]{
+        return QString::fromStdString(get("loadContentUrl").ToString());
+    });
+}
+
+QJsWant *QJsAbility::launchWant() const
+{
+    if (m_want == nullptr) {
+        m_want = QtOh::runOnJsUIThreadWithResult([this]{
+            return new QJsWant(get("launchWant").ToObject());
+        });
+    }
+    return m_want;
+}
+
+QByteArray QJsAbility::launchQtApplication() const
+{
+    return QtOh::runOnJsUIThreadWithResult([this]{
+        return QByteArray::fromStdString(get("launchApplication").ToString());
+    });
+}
+
+QList<QByteArray> QJsAbility::launchQtParams() const
+{
+    return QtOh::runOnJsUIThreadWithResult([this]{
+        QList<QByteArray> result;
+        QJsWant *want = launchWant();
+        if (want) {
+            result << want->launchParams();
+        }
+        result << QByteArray::fromStdString(get("launchParams").ToString()).split(' ');
+        return result;
+    });
+}
+
+void QJsAbility::terminateSelf()
+{
+    if (m_canTerminateSelf)
+        context()->terminateSelf();
+}
+
+void QJsAbility::setCanTerminateSelf(bool enable)
+{
+    m_canTerminateSelf = enable;
+}
+
+void QJsAbility::setOnDestroy()
+{
+    Napi::Function old = get("onDestroy").As<Napi::Function>();
+    m_onDestroy = Napi::Persistent(old);
+    Napi::Function onDestroy = QNapi::create([this](const Napi::CallbackInfo& info) {
+        if (m_onDestroy.IsEmpty())
+            return;
+        m_onDestroy.Call(info.This(), {});
+        m_onDestroy.Reset();
+
+        qNativeWindowManager->handleTopWindowDestroyed(this->name());
+    });
+    set("onDestroy", onDestroy);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsability.h b/src/plugins/platforms/openharmony/jsclass/qjsability.h
new file mode 100644
index 00000000000..35e95cd9836
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsability.h
@@ -0,0 +1,55 @@
+#ifndef QJSABILITY_H
+#define QJSABILITY_H
+
+#include "qjsobject.h"
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+
+class QJsContext;
+class QJsWant;
+
+class QJsAbility : public QJsObject
+{
+public:
+    enum AbilityType
+    {
+        UIAbility,
+        UIExtensionAbility
+    };
+    QJsAbility(Napi::Object jsUIAbility);
+    virtual ~QJsAbility();
+
+    QString name() const;
+
+    virtual QJsContext *context() const = 0;
+
+    virtual Napi::Value newLocalStorage() const final;
+
+    QString loadContentUrl() const;
+
+    QJsWant *launchWant() const;
+
+    QByteArray launchQtApplication() const;
+
+    virtual QList<QByteArray> launchQtParams() const;
+
+    virtual AbilityType abilityType() const = 0;
+
+    void terminateSelf();
+
+    void setCanTerminateSelf(bool enable);
+
+protected:
+    void setOnDestroy();
+
+    mutable QJsContext *m_context;
+    mutable QJsWant *m_want;
+    bool m_canTerminateSelf;
+
+    Napi::FunctionReference m_onDestroy;
+    QAtomicInteger<bool> m_isAbilityDestryed;
+};
+
+QT_END_NAMESPACE
+#endif // QJSABILITY_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsabilityfactory.cpp b/src/plugins/platforms/openharmony/jsclass/qjsabilityfactory.cpp
new file mode 100644
index 00000000000..177959fac03
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsabilityfactory.cpp
@@ -0,0 +1,39 @@
+#include "qjsabilityfactory.h"
+#include "qjsuiability.h"
+#include "qjsuiextensionability.h"
+#include <QtCore/qnapi.h>
+#include <QtCore/QJsModule>
+
+QT_BEGIN_NAMESPACE
+
+namespace QJsAbilityFactory {
+
+QJsAbility *create(const Napi::CallbackInfo& info)
+{
+    if (info.Length() == 0)
+        return nullptr;
+    auto ability = QNapi::getFirst<Napi::Object>(info);
+    if (ability.IsEmpty() || ability.IsUndefined())
+        return nullptr;
+
+    static QJsModule uiAbility("@ohos.app.ability.UIAbility");
+    auto prototypeOfUiAbility = uiAbility.get<Napi::Object>("prototype");
+    Napi::Function uiAbilityConstructor = prototypeOfUiAbility.Get("constructor").As<Napi::Function>();
+    if (ability.InstanceOf(uiAbilityConstructor))
+        return new QJsUIAbility(ability);
+
+    if (info.Length() < 2)
+        return nullptr;
+    auto session = info[1].As<Napi::Object>();
+    static QJsModule embeddedUIExtensionAbility("@ohos.app.ability.EmbeddedUIExtensionAbility");
+    auto prototypeOfEmbeddedUIExtensionAbility = embeddedUIExtensionAbility.get<Napi::Object>("prototype");
+    Napi::Function embeddedUIExtensionAbilityConstructor = prototypeOfEmbeddedUIExtensionAbility.Get("constructor").As<Napi::Function>();
+
+    if (ability.InstanceOf(embeddedUIExtensionAbilityConstructor))
+        return new QJsUIExtensionAbility(ability, session);
+    return nullptr;
+}
+
+}
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsabilityfactory.h b/src/plugins/platforms/openharmony/jsclass/qjsabilityfactory.h
new file mode 100644
index 00000000000..857ff41bc1a
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsabilityfactory.h
@@ -0,0 +1,13 @@
+#ifndef QJSABILITYFACTORY_H
+#define QJSABILITYFACTORY_H
+
+#include "qjsability.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QJsAbilityFactory {
+QJsAbility *create(const Napi::CallbackInfo &info);
+}
+
+QT_END_NAMESPACE
+#endif // QJSABILITYFACTORY_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsabilityinfo.cpp b/src/plugins/platforms/openharmony/jsclass/qjsabilityinfo.cpp
new file mode 100644
index 00000000000..dd27606828d
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsabilityinfo.cpp
@@ -0,0 +1,45 @@
+#include "qjsabilityinfo.h"
+#include <private/qopenharmony_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QJsAbilityInfo::QJsAbilityInfo(Napi::Object info)
+    : QJsObject(info)
+{
+
+}
+
+QHash<QString, QString> QJsAbilityInfo::metadata() const
+{
+   return QtOh::runOnJsUIThreadWithResult([this]{
+        QHash<QString, QString> result;
+        Napi::Array data = get("metadata").As<Napi::Array>();
+        for (uint32_t i = 0; i < data.Length(); ++i) {
+            Napi::Value keyValue = data[i];
+            Napi::Object keyValueObject = keyValue.ToObject();
+            QString key = QString::fromStdString(keyValueObject.Get("name").ToString());
+            QString value = QString::fromStdString(keyValueObject.Get("value").ToString());
+            result.insert(key, value);
+        }
+        return result;
+   });
+}
+
+bool QJsAbilityInfo::isInitGeometrySetted() const
+{
+    return QtOh::runOnJsUIThreadWithResult([this]{
+        static QStringList keys = {"ohos.ability.window.height", "ohos.ability.window.width",
+                                  "ohos.ability.window.left", "ohos.ability.window.right"};
+        Napi::Array data = get("metadata").As<Napi::Array>();
+        for (uint32_t i = 0; i < data.Length(); ++i) {
+            Napi::Value keyValue = data[i];
+            Napi::Object keyValueObject = keyValue.ToObject();
+            QString key = QString::fromStdString(keyValueObject.Get("name").ToString());
+            if (keys.contains(key))
+                return true;
+        }
+        return false;
+    });
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsabilityinfo.h b/src/plugins/platforms/openharmony/jsclass/qjsabilityinfo.h
new file mode 100644
index 00000000000..4c6949c07e4
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsabilityinfo.h
@@ -0,0 +1,20 @@
+#ifndef QJSABILITYINFO_H
+#define QJSABILITYINFO_H
+
+#include <QJsObject>
+#include <QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QJsAbilityInfo : public QJsObject
+{
+public:
+    QJsAbilityInfo(Napi::Object info);
+
+    QHash<QString, QString> metadata() const;
+
+    bool isInitGeometrySetted() const;
+};
+
+QT_END_NAMESPACE
+#endif // QJSABILITYINFO_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsabilitystage.cpp b/src/plugins/platforms/openharmony/jsclass/qjsabilitystage.cpp
new file mode 100644
index 00000000000..f63c92a7105
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsabilitystage.cpp
@@ -0,0 +1,174 @@
+#include <mutex>
+#include <qpa/qwindowsysteminterface.h>
+
+#include "qjswant.h"
+#include "qjsability.h"
+#include "qjsabilitystage.h"
+#include "private/qjsobject_p.h"
+#include "qopenharmonydefines.h"
+#include "qohnativewindowmanager.h"
+#include "private/qohhiappevent_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QJsAbilityStagePrivate : public QJsObjectPrivate
+{
+    Q_DECLARE_PUBLIC(QJsAbilityStage)
+    Q_DISABLE_COPY_MOVE(QJsAbilityStagePrivate)
+
+public:
+    explicit QJsAbilityStagePrivate(QJsAbilityStage *const qq);
+    ~QJsAbilityStagePrivate();
+
+    static void attachAbilityStage(const Napi::CallbackInfo& info);
+
+    void setAcceptWant();
+    void setNewProcessRequest();
+
+private:
+    bool m_created;
+    Napi::FunctionReference m_funcRef;
+    Napi::FunctionReference m_onNewProcessRequest;
+    Napi::FunctionReference m_onAcceptWant;
+};
+
+QJsAbilityStagePrivate::QJsAbilityStagePrivate(QJsAbilityStage * const qq)
+    : QJsObjectPrivate(qq)
+    , m_created(false)
+{
+
+}
+
+QJsAbilityStagePrivate::~QJsAbilityStagePrivate()
+{
+    m_created = false;
+    m_funcRef.Reset();
+    m_onAcceptWant.Reset();
+    m_onNewProcessRequest.Reset();
+}
+
+void QJsAbilityStagePrivate::attachAbilityStage(const Napi::CallbackInfo &info)
+{
+    if (info.Length() < 1) {
+        LOGW("%{public}s param error", Q_FUNC_INFO);
+        return;
+    }
+
+    Napi::Object stage = info[0].As<Napi::Object>();
+    QJsAbilityStage::instance()->setObject(stage);
+    QJsAbilityStage::instance()->d_func()->m_created = true;
+    QJsAbilityStage::instance()->d_func()->setAcceptWant();
+    QJsAbilityStage::instance()->d_func()->setNewProcessRequest();
+
+#if OHOS_SDK_VERSION >= 15
+    Napi::Function prepareToTerminateAsync = Napi::Function::New(QJsAbilityStage::instance()->env(), [](const Napi::CallbackInfo& info){
+        QtOhosWatchdog::QOhHiAppEvent::instance()->writeDataTag("apt_begin");
+        Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(info.Env());
+        QWindowSystemInterface::handleApplicationTermination();
+        deferred.Resolve(Napi::Number::New(deferred.Env(), int(1)));
+        return deferred.Promise();
+    });
+    QJsAbilityStage::instance()->d_func()->m_funcRef = Napi::Persistent(prepareToTerminateAsync);
+    QJsAbilityStage::instance()->set("onPrepareTerminationAsync", prepareToTerminateAsync);
+#else
+    Q_UNUSED(info);
+    LOGW("support for api 15 and above is available.");
+#endif
+}
+
+void QJsAbilityStagePrivate::setAcceptWant()
+{
+    /*
+     * 返回ability的Key,如果已存在则直接拉起,否则创建新的ability。
+     * @param want
+     * @returns
+     */
+
+    Napi::Function old = QJsAbilityStage::instance()->get("onAcceptWant").As<Napi::Function>();
+    m_onAcceptWant = Napi::Persistent(old);
+    Napi::Function onAcceptWant = QNapi::create([this](const Napi::CallbackInfo& info){
+        std::vector<napi_value> args;
+        args.reserve(info.Length());
+        for (size_t i = 0; i < info.Length(); i++) {
+            args.push_back(info[i]);
+        }
+        auto result = m_onAcceptWant.Call(info.This(), args);
+        QString key = QNapi::get<QString>(result);
+        if (!key.isEmpty())
+            return result;
+        if (info.Length() < 1)
+            return QNapi::create(QJsWant::defaultWindowName);
+
+        static bool first = true;
+        QJsWant want(info[0].As<Napi::Object>());
+        if (!want.hasWindowName()) {
+            if (first) {
+                first = false;
+                key = QJsWant::defaultWindowName;
+            } else {
+                auto ability = qNativeWindowManager->defaultAbility();
+                if (ability == nullptr)
+                    key = QJsWant::defaultWindowName;
+                else
+                    key = ability->name();
+            }
+        } else {
+            key = want.windowName();
+        }
+        return QNapi::create(key);
+    });
+    QJsAbilityStage::instance()->set("onAcceptWant", onAcceptWant);
+}
+
+void QJsAbilityStagePrivate::setNewProcessRequest()
+{
+    auto old = QJsAbilityStage::instance()->get("onNewProcessRequest").As<Napi::Function>();
+    m_onNewProcessRequest = Napi::Persistent(old);
+    Napi::Function onNewProcessRequest = QNapi::create([this](const Napi::CallbackInfo& info){
+        QJsWant want(info[0].As<Napi::Object>());
+        if (!want.hasProcessIdentifier())
+            return m_onNewProcessRequest.Call(info.This(), {info[0]});
+        QString processIdentifier = want.processIdentifier();
+        return QNapi::create(processIdentifier);
+    });
+    QJsAbilityStage::instance()->set("onNewProcessRequest", onNewProcessRequest);
+}
+
+QJsAbilityStage::QJsAbilityStage()
+    : QJsObject(*(new QJsAbilityStagePrivate(this)))
+{
+
+}
+
+QJsAbilityStage::~QJsAbilityStage()
+{
+
+}
+
+bool QJsAbilityStage::isCreated() const
+{
+    Q_D(const QJsAbilityStage);
+    return d->m_created;
+}
+
+QJsAbilityStage *QJsAbilityStage::instance()
+{
+    static std::once_flag once;
+    std::call_once(once, []{
+        m_self.reset(new QJsAbilityStage());
+    });
+
+    return m_self.get();
+}
+
+void QJsAbilityStage::init(Napi::Env env, Napi::Object exports)
+{
+    static bool inited = false;
+    if (!inited) {
+        exports.Set(Napi::String::New(env, "attachAbilityStage"), Napi::Function::New(env, QJsAbilityStagePrivate::attachAbilityStage));
+        inited = true;
+    }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsabilitystage.h b/src/plugins/platforms/openharmony/jsclass/qjsabilitystage.h
new file mode 100644
index 00000000000..b0f0bdbb3fb
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsabilitystage.h
@@ -0,0 +1,26 @@
+#ifndef QJSABILITYSTAGE_H
+#define QJSABILITYSTAGE_H
+
+#include "qjsobject.h"
+
+QT_BEGIN_NAMESPACE
+
+class QJsAbilityStagePrivate;
+class QJsAbilityStage : public QJsObject
+{
+    Q_DECLARE_PRIVATE(QJsAbilityStage)
+    Q_DISABLE_COPY_MOVE(QJsAbilityStage)
+
+    QJsAbilityStage();
+    inline static QScopedPointer<QJsAbilityStage> m_self { nullptr };
+
+public:
+    ~QJsAbilityStage();
+    bool isCreated() const;
+
+    static QJsAbilityStage *instance();
+    static void init(Napi::Env env, Napi::Object exports);
+};
+
+QT_END_NAMESPACE
+#endif // QJSABILITYSTAGE_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsaccessmanager.cpp b/src/plugins/platforms/openharmony/jsclass/qjsaccessmanager.cpp
new file mode 100644
index 00000000000..4cbfc35299c
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsaccessmanager.cpp
@@ -0,0 +1,240 @@
+#include <mutex>
+#include <QDebug>
+#include <QObject>
+#include <QThread>
+#include <QJsModule>
+#include <QJsObject>
+#include <QGuiApplication>
+
+#include "private/qopenharmony_p.h"
+#include "qjscontext.h"
+#include "qjsaccessmanager.h"
+#include "qohnativewindowmanager.h"
+#include <private/qjspromise_p.h>
+QT_BEGIN_NAMESPACE
+
+static std::once_flag sg_once;
+static QScopedPointer<QJsAccessManager> sg_self(Q_NULLPTR);
+
+class PermissionsResultClass : public QObject
+{
+    Q_OBJECT
+
+public:
+    PermissionsResultClass(const QtOhPrivate::PermissionsResultFunc &func) : m_func(func) {}
+    Q_INVOKABLE void sendResult(const QtOhPrivate::PermissionRequestResult &result) { m_func(result); delete this;}
+
+private:
+    QtOhPrivate::PermissionsResultFunc m_func;
+};
+
+class NotificationResultClass : public QObject
+{
+    Q_OBJECT
+
+public:
+    NotificationResultClass(const QtOhPrivate::enableNotificationFunc &func) : m_func(func) {}
+    Q_INVOKABLE void sendResult(bool result) { m_func(result); delete this;}
+
+private:
+    QtOhPrivate::enableNotificationFunc m_func;
+};
+
+QJsAccessManager::QJsAccessManager()
+{
+
+}
+
+QJsAccessManager *QJsAccessManager::instance()
+{
+    std::call_once(sg_once, []{
+        sg_self.reset(new QJsAccessManager());
+    });
+    return sg_self.data();
+}
+
+static void sendFailureRequestResults(const QStringList &permissions, PermissionsResultClass *result)
+{
+    QtOhPrivate::PermissionRequestResult requestResult;
+    requestResult.permissions.append(permissions);
+    for (int i = 0; i < permissions.length(); ++i) {
+        requestResult.authResults.append(QtOhPrivate::PermissionsResult::Denied);
+        requestResult.dialogShownResults.append(false);
+    }
+    Qt::ConnectionType connection = QThread::currentThread() == result->thread() ? Qt::DirectConnection : Qt::QueuedConnection;
+    QMetaObject::invokeMethod(result, "sendResult", connection, Q_ARG(QtOhPrivate::PermissionRequestResult, requestResult));
+}
+
+static void sendResult(bool res, NotificationResultClass *result){
+    Qt::ConnectionType connection = QThread::currentThread() == result->thread() ? Qt::DirectConnection : Qt::QueuedConnection;
+    QMetaObject::invokeMethod(result, "sendResult", connection, Q_ARG(bool, res));
+}
+
+void QJsAccessManager::requestPermissions(const QStringList &permissions, const QtOhPrivate::PermissionsResultFunc &callbackFunc)
+{
+    PermissionsResultClass *result = new PermissionsResultClass(callbackFunc);
+    QJsObject *atManager = atManagerAcquire();
+    if (nullptr == atManager) {
+        qWarning() << Q_FUNC_INFO << "abilityAccessCtrl acquire failed.";
+        sendFailureRequestResults(permissions, result);
+        return;
+    }
+
+    QtOh::runOnJsUIThreadNoWait([=]{
+        Napi::Array ps = Napi::Array::New(atManager->env(), permissions.length());
+        for (int i = 0; i < permissions.length(); ++i) {
+            ps.Set(i, permissions.at(i).toStdString());
+        }
+
+        QJsContext *context = qNativeWindowManager->context(qApp->focusWindow());
+        QJsPromise promise(atManager->call("requestPermissionsFromUser", { context->object(), ps }).As<Napi::Promise>());
+        promise.onThen([result](const Napi::CallbackInfo &info) {
+            Napi::Object data = info[0].As<Napi::Object>();
+            Napi::Array rps = data.Get("permissions").As<Napi::Array>();
+            Napi::Array auths = data.Get("authResults").As<Napi::Array>();
+            Napi::Array dialogShownResults = data.Get("dialogShownResults").As<Napi::Array>();
+
+            QtOhPrivate::PermissionRequestResult requestResult;
+            for (uint32_t i = 0; i < rps.Length(); ++i) {
+                Napi::Value tmpArg1 = rps[i];
+                Napi::Value tmpArg2 = auths[i];
+                Napi::Value tmpArg3 = dialogShownResults[i];
+                requestResult.permissions.append(QString::fromStdString(tmpArg1.ToString()));
+                requestResult.authResults.append((QtOhPrivate::PermissionsResult)(int32_t(tmpArg2.ToNumber())));
+                requestResult.dialogShownResults.append(tmpArg3.ToBoolean());
+            }
+            Qt::ConnectionType connection = QThread::currentThread() == result->thread() ? Qt::DirectConnection : Qt::QueuedConnection;
+            QMetaObject::invokeMethod(result, "sendResult", connection, Q_ARG(QtOhPrivate::PermissionRequestResult, requestResult));
+        }).onCatch([=](const Napi::CallbackInfo &info) {
+            Q_UNUSED(info);
+            sendFailureRequestResults(permissions, result);
+        });
+    });
+}
+
+void QJsAccessManager::requestPermissionsOnSetting(const QStringList &permissions, const QtOhPrivate::PermissionsResultFunc &callbackFunc)
+{
+    PermissionsResultClass *result = new PermissionsResultClass(callbackFunc);
+    QJsObject *atManager = atManagerAcquire();
+    if (nullptr == atManager) {
+        qWarning() << Q_FUNC_INFO << "abilityAccessCtrl acquire failed.";
+        sendFailureRequestResults(permissions, result);
+        return;
+    }
+
+    QtOh::runOnJsUIThreadNoWait([=]{
+        Napi::Array ps = Napi::Array::New(atManager->env(), permissions.length());
+        for (int i = 0; i < permissions.length(); ++i) {
+            ps.Set(i, permissions.at(i).toStdString());
+        }
+
+        QJsContext *context = qNativeWindowManager->context(qApp->focusWindow());
+
+        QJsPromise promise(atManager->call("requestPermissionOnSetting", { context->object(), ps }).As<Napi::Promise>());
+        promise.onThen([permissions, result](const Napi::CallbackInfo &info) {
+            Napi::Array grantStatus = info[0].As<Napi::Array>();
+            QtOhPrivate::PermissionRequestResult requestResult;
+            for (uint32_t i = 0; i < grantStatus.Length(); ++i) {
+                Napi::Value tmpArg1 = grantStatus[i];
+                requestResult.permissions.append(permissions.at(i));
+                requestResult.authResults.append((QtOhPrivate::PermissionsResult)(int32_t(tmpArg1.ToNumber())));
+                requestResult.dialogShownResults.append(false);
+            }
+            Qt::ConnectionType connection = QThread::currentThread() == result->thread() ? Qt::DirectConnection : Qt::QueuedConnection;
+            QMetaObject::invokeMethod(result, "sendResult", connection, Q_ARG(QtOhPrivate::PermissionRequestResult, requestResult));
+        }).onCatch([=](const Napi::CallbackInfo &info) {
+            Q_UNUSED(info);
+            sendFailureRequestResults(permissions, result);
+        });
+    });
+}
+
+void QJsAccessManager::requestEnableNotification(const QtOhPrivate::enableNotificationFunc &callbackFunc)
+{
+    NotificationResultClass *result = new NotificationResultClass(callbackFunc);
+
+    QJsObject *notifyMgr = notificationManagerAcquire();
+    if (nullptr == notifyMgr) {
+        qWarning() << Q_FUNC_INFO << "abilityAccessCtrl acquire failed.";
+        sendResult(false, result);
+        return;
+    }
+
+    QtOh::runOnJsUIThreadNoWait([=]{
+        QJsContext *context = qNativeWindowManager->context(qApp->focusWindow());
+        QJsPromise promise(notifyMgr->call("requestEnableNotification", { context->object() }).As<Napi::Promise>());
+        promise.onThen([result](const Napi::CallbackInfo &info) {
+            Q_UNUSED(info);
+            sendResult(true, result);
+        }).onCatch([result](const Napi::CallbackInfo &info) {
+            Q_UNUSED(info);
+            sendResult(false, result);
+        });
+    });
+}
+
+bool QJsAccessManager::isNotificationEnabled()
+{
+    QJsObject *notifyMgr = notificationManagerAcquire();
+    if (nullptr == notifyMgr) {
+        qWarning() << Q_FUNC_INFO << "abilityAccessCtrl acquire failed.";
+        return false;
+    }
+
+    return QtOh::runOnJsUIThreadWithResult([=]{
+        return notifyMgr->call<bool>("isNotificationEnabledSync");
+    });
+}
+
+void QJsAccessManager::openNotificationSettings()
+{
+    QJsObject *notifyMgr = notificationManagerAcquire();
+    if (nullptr == notifyMgr) {
+        qWarning() << Q_FUNC_INFO << "abilityAccessCtrl acquire failed.";
+        return;
+    }
+
+    QtOh::runOnJsUIThreadNoWait([=]{
+        QJsContext *context = qNativeWindowManager->context(qApp->focusWindow());
+        notifyMgr->call("openNotificationSettings", { context->object() });
+    });
+}
+
+QJsObject *QJsAccessManager::atManagerAcquire()
+{
+    if (m_atManager.isNull()) {        
+        QtOh::runOnJsUIThreadAndWait([this]{
+            QJsModule atModule("@ohos.abilityAccessCtrl");
+            Napi::Object atMgrObject = atModule.call("createAtManager").As<Napi::Object>();
+            if (!atMgrObject.IsUndefined())
+                m_atManager.reset(new QJsObject(atMgrObject));
+        });
+    }
+
+    return m_atManager.data();
+}
+
+QJsObject *QJsAccessManager::bundleManagerAcquire()
+{
+    if (m_bundleMgr.isNull()) {
+        QtOh::runOnJsUIThreadAndWait([this]{
+            m_bundleMgr.reset(new QJsModule("@ohos.bundle.bundleManager"));
+        });
+    }
+    return m_bundleMgr.data();
+}
+
+QJsObject *QJsAccessManager::notificationManagerAcquire()
+{
+    if (m_notificationMgr.isNull()) {
+        QtOh::runOnJsUIThreadAndWait([this]{
+            m_notificationMgr.reset(new QJsModule("@ohos.notificationManager"));
+        });
+    }
+    return m_notificationMgr.data();
+}
+
+QT_END_NAMESPACE
+
+#include "qjsaccessmanager.moc"
+
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsaccessmanager.h b/src/plugins/platforms/openharmony/jsclass/qjsaccessmanager.h
new file mode 100644
index 00000000000..8ddca518f7f
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsaccessmanager.h
@@ -0,0 +1,33 @@
+#ifndef QJSACCESSMANAGER_H
+#define QJSACCESSMANAGER_H
+
+#include <QScopedPointer>
+#include <QtGui/qpa/qplatformaccessctrl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QJsAccessManager : public QPlatformAccessCtrl
+{
+    explicit QJsAccessManager();
+
+public:
+    static QJsAccessManager *instance();
+    void requestPermissions(const QStringList &permissions, const QtOhPrivate::PermissionsResultFunc &callbackFunc) override;
+    void requestPermissionsOnSetting(const QStringList &permissions, const QtOhPrivate::PermissionsResultFunc &callbackFunc) override;
+
+    void requestEnableNotification(const QtOhPrivate::enableNotificationFunc &callbackFunc) override;
+    bool isNotificationEnabled() override;
+    void openNotificationSettings() override;
+protected:
+    QJsObject *atManagerAcquire() override;
+    QJsObject *bundleManagerAcquire() override;
+    QJsObject *notificationManagerAcquire() override;
+
+private:
+    QScopedPointer<QJsObject> m_atManager;
+    QScopedPointer<QJsObject> m_bundleMgr;
+    QScopedPointer<QJsObject> m_notificationMgr;
+};
+
+QT_END_NAMESPACE
+#endif // QJSACCESSMANAGER_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsapplicationcontext.cpp b/src/plugins/platforms/openharmony/jsclass/qjsapplicationcontext.cpp
new file mode 100644
index 00000000000..73b260abde9
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsapplicationcontext.cpp
@@ -0,0 +1,21 @@
+#include "qjsapplicationcontext.h"
+
+QT_BEGIN_NAMESPACE
+
+QJsApplicationContext::QJsApplicationContext(Napi::Object jsObject)
+    : QJsContext(jsObject)
+{
+
+}
+
+QJsApplicationContext::~QJsApplicationContext()
+{
+
+}
+
+QJsContext::ContextType QJsApplicationContext::contextType() const
+{
+    return ContextType::ApplicationContext;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsapplicationcontext.h b/src/plugins/platforms/openharmony/jsclass/qjsapplicationcontext.h
new file mode 100644
index 00000000000..5227c7d8726
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsapplicationcontext.h
@@ -0,0 +1,18 @@
+#ifndef QJSAPPLICATIONCONTEXT_H
+#define QJSAPPLICATIONCONTEXT_H
+
+#include "qjscontext.h"
+
+QT_BEGIN_NAMESPACE
+
+class QJsApplicationContext : public QJsContext
+{
+public:
+    QJsApplicationContext(Napi::Object jsObject);
+    ~QJsApplicationContext();
+
+    ContextType contextType() const override;
+};
+
+QT_END_NAMESPACE
+#endif // QJSAPPLICATIONCONTEXT_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsbasecontext.cpp b/src/plugins/platforms/openharmony/jsclass/qjsbasecontext.cpp
new file mode 100644
index 00000000000..cfd11041538
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsbasecontext.cpp
@@ -0,0 +1,21 @@
+#include "qjsbasecontext.h"
+
+QT_BEGIN_NAMESPACE
+
+QJsBaseContext::QJsBaseContext(Napi::Object jsObject)
+    : QJsObject(jsObject)
+{
+
+}
+
+QJsBaseContext::~QJsBaseContext()
+{
+
+}
+
+bool QJsBaseContext::stageMode() const
+{
+    return get("stageMode").ToBoolean();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsbasecontext.h b/src/plugins/platforms/openharmony/jsclass/qjsbasecontext.h
new file mode 100644
index 00000000000..ab8d5c9e846
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsbasecontext.h
@@ -0,0 +1,18 @@
+#ifndef QJSBASECONTEXT_H
+#define QJSBASECONTEXT_H
+
+#include "qjsobject.h"
+
+QT_BEGIN_NAMESPACE
+
+class QJsBaseContext : public QJsObject
+{
+public:
+    QJsBaseContext(Napi::Object jsObject);
+    virtual ~QJsBaseContext();
+
+    bool stageMode() const;
+};
+
+QT_END_NAMESPACE
+#endif // QJSBASECONTEXT_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjscontext.cpp b/src/plugins/platforms/openharmony/jsclass/qjscontext.cpp
new file mode 100644
index 00000000000..ae56dffe6e1
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjscontext.cpp
@@ -0,0 +1,215 @@
+#include <rawfile/raw_file_manager.h>
+
+#include <qnapi.h>
+#include "qjscontext.h"
+#include "qjswindowstage.h"
+#include "qjsapplicationcontext.h"
+#include <private/qopenharmony_p.h>
+#include <private/qjspromise_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QJsContext::QJsContext(Napi::Object jsObject)
+    : QJsBaseContext(jsObject)
+    , m_windowStage(nullptr)
+    , m_resourceManager(nullptr)
+    , m_context(nullptr)
+{
+
+}
+
+QJsContext::~QJsContext()
+{
+    if (m_windowStage != nullptr)
+        delete m_windowStage;
+    if (m_resourceManager != nullptr)
+        OH_ResourceManager_ReleaseNativeResourceManager(m_resourceManager);
+    if (m_context != nullptr)
+        delete m_context;
+}
+
+int QJsContext::colorMode() const
+{
+    return QtOh::runOnJsUIThreadWithResult([this]{
+        Napi::Object config = get<Napi::Object>("config");
+        return QNapi::get<int>(config, "colorMode");
+    });
+}
+
+QString QJsContext::cacheDir() const
+{
+    return get<QString>("cacheDir");
+}
+
+QString QJsContext::tempDir() const
+{
+    return get<QString>("tempDir");
+}
+
+QString QJsContext::filesDir() const
+{
+    return get<QString>("filesDir");
+}
+
+QString QJsContext::databaseDir() const
+{
+    return get<QString>("databaseDir");
+}
+
+QString QJsContext::preferencesDir() const
+{
+    return get<QString>("preferencesDir");
+}
+
+QString QJsContext::bundleCodeDir() const
+{
+    return get<QString>("bundleCodeDir");
+}
+
+QString QJsContext::distributedFilesDir() const
+{
+    return get<QString>("distributedFilesDir");
+}
+
+QString QJsContext::resourceDir() const
+{
+    return get<QString>("resourceDir");
+}
+
+QString QJsContext::cloudFileDir() const
+{
+    return get<QString>("cloudFileDir");
+}
+
+QString QJsContext::qmlDir() const
+{
+    return resourceDir() + "/qml";
+}
+
+QJsContext *QJsContext::applicationContext() const
+{
+    if (m_context == nullptr)
+        m_context = new QJsApplicationContext(call("getApplicationContext").ToObject());
+    return m_context;
+}
+
+QJsWindowStage *QJsContext::windowStage() const
+{
+    if (m_windowStage == nullptr) {
+        m_windowStage = QtOh::runOnJsUIThreadWithResult([this]{
+            return new QJsWindowStage(get("windowStage").ToObject());
+        });
+    }
+    return m_windowStage;
+}
+
+NativeResourceManager *QJsContext::resourceManager() const
+{
+    if (m_resourceManager == nullptr){
+        m_resourceManager = QtOh::runOnJsUIThreadWithResult([this]{
+            return OH_ResourceManager_InitNativeResourceManager(env(), get("resourceManager"));
+        });
+    }
+    return m_resourceManager;
+}
+
+static Napi::Value makeWant(const Want &want)
+{
+    auto d = QVariantMap{
+            {"bundleName", want.bundleName},
+            {"moduleName", want.moduleName},
+            {"abilityName", want.abilityName},
+    };
+    d.insert("parameters", QVariantMap{
+                                   {"windowName", want.parameters.windowName},
+                                   {"instanceKey", want.parameters.instanceKey}
+                           }
+             );
+    Napi::Value jsWant = QNapi::create(d);
+    return jsWant;
+}
+
+void QJsContext::startAbility(const Want &want, const StartOptions &options, const Napi::Function &callback)
+{
+    Napi::Value jsWant = makeWant(want);
+    Napi::Value jsOptions = QNapi::create(QVariantMap{
+        {"windowLeft", options.windowLeft},
+        {"windowTop", options.windowTop},
+        {"windowWidth", options.windowWidth},
+        {"windowHeight", options.windowHeight},
+        {"withAnimation", options.withAnimation},
+        {"displayId", options.displayId}
+    });
+
+    call("startAbility", { jsWant, jsOptions, callback });
+}
+
+void QJsContext::startAbility(const Want &want, const Napi::Function &callback)
+{
+    call("startAbility", { makeWant(want), callback });
+}
+
+void QJsContext::startAbility(const Napi::Value &want)
+{
+    call("startAbility", { want });
+}
+
+void QJsContext::startAbility(const Napi::Value &want, const Napi::Function &callback)
+{
+    call("startAbility", { want, callback });
+}
+
+void QJsContext::startAbility(const Napi::Value &want, const Napi::Value &options, const Napi::Function &callback)
+{
+    call("startAbility", { want, options, callback });
+}
+
+void QJsContext::startAbilityForResult(const Napi::Value &want, const Napi::Value &options,const Napi::Function &callback)
+{
+    call("startAbilityForResult", { want, options, callback });
+}
+
+void QJsContext::terminateSelfWithResult(const Napi::Object &abilityResult)
+{
+    call("terminateSelfWithResult", { abilityResult });
+}
+
+bool QJsContext::showAbility()
+{
+    return QtOh::runOnJsUIThreadWithPromise<bool>([this](auto p){
+        QJsPromise promise(call("showAbility").As<Napi::Promise>());
+        promise.onThen([p](const Napi::CallbackInfo &info){
+                   Q_UNUSED(info)
+                   p->set_value(true);
+               }).onCatch([p](const Napi::CallbackInfo &info){
+                    Q_UNUSED(info)
+                    LOGW("call showAbility failed.");
+                    p->set_value(false);
+                });
+    });
+}
+
+bool QJsContext::hideAbility()
+{
+    return QtOh::runOnJsUIThreadWithPromise<bool>([this](auto p){
+        QJsPromise promise(call("hideAbility").As<Napi::Promise>());
+
+        promise.onThen([p](const Napi::CallbackInfo &info){
+                   Q_UNUSED(info)
+                   p->set_value(true);
+               }).onCatch([p](const Napi::CallbackInfo &info){
+                    Q_UNUSED(info)
+                    LOGW("call hideAbility failed.");
+                    p->set_value(false);
+                });
+    });
+}
+
+void QJsContext::terminateSelf()
+{
+    QtOh::runOnJsUIThreadAndWait([this]{
+        call("terminateSelf");
+    });
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjscontext.h b/src/plugins/platforms/openharmony/jsclass/qjscontext.h
new file mode 100644
index 00000000000..50170cdf66c
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjscontext.h
@@ -0,0 +1,99 @@
+#ifndef QJSCONTEXT_H
+#define QJSCONTEXT_H
+
+#include <QString>
+
+#include "qjsbasecontext.h"
+
+QT_BEGIN_NAMESPACE
+
+struct Want
+{
+    QString bundleName;
+    QString moduleName;
+    QString abilityName;
+    struct Parameters {
+        QString windowName;
+        QString instanceKey;
+    } parameters;
+};
+
+struct StartOptions
+{
+    int windowMode;
+    int windowLeft;
+    int windowTop;
+    int windowWidth;
+    int windowHeight;
+    uint32_t displayId;
+    bool withAnimation;
+};
+
+class QJsWindowStage;
+class QJsApplicationContext;
+struct NativeResourceManager;
+class QJsContext : public QJsBaseContext
+{
+public:
+    enum ContextType
+    {
+        UIContext,
+        UIExtensionContext,
+        ApplicationContext
+    };
+    QJsContext(Napi::Object jsObject);
+    ~QJsContext();
+
+    int colorMode() const;
+
+    QString cacheDir() const;
+
+    QString tempDir() const;
+
+    QString filesDir() const;
+
+    QString databaseDir() const;
+
+    QString preferencesDir() const;
+
+    QString bundleCodeDir() const;
+
+    QString distributedFilesDir() const;
+
+    QString resourceDir() const;
+
+    QString cloudFileDir() const;
+
+    QString qmlDir() const;
+
+    QJsContext *applicationContext() const;
+
+    QJsWindowStage *windowStage() const;
+
+    NativeResourceManager *resourceManager() const;
+    void startAbility(const Want &want, const Napi::Function &callback = Napi::Function());
+
+    virtual ContextType contextType() const = 0;
+
+    void startAbility(const Want &want, const StartOptions &options, const Napi::Function &callback = Napi::Function());
+
+    void startAbility(const Napi::Value &want);
+    void startAbility(const Napi::Value &want, const Napi::Function &callback);
+    void startAbility(const Napi::Value &want, const Napi::Value &options, const Napi::Function &callback);
+
+    void startAbilityForResult(const Napi::Value &want, const Napi::Value &options = Napi::Value(),const Napi::Function &callback = Napi::Function());
+
+    void terminateSelfWithResult(const Napi::Object &abilityResult);
+
+    bool showAbility();
+    bool hideAbility();
+
+    void terminateSelf();
+private:
+    mutable QJsWindowStage *m_windowStage;
+    mutable NativeResourceManager *m_resourceManager;
+    mutable QJsApplicationContext *m_context;
+};
+
+QT_END_NAMESPACE
+#endif // QJSCONTEXT_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjscursor.cpp b/src/plugins/platforms/openharmony/jsclass/qjscursor.cpp
new file mode 100644
index 00000000000..77b44cf0383
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjscursor.cpp
@@ -0,0 +1,87 @@
+#include <QDebug>
+#include <QThread>
+#include <private/qopenharmony_p.h>
+#include <QCoreApplication>
+#include <multimedia/image_framework/image/pixelmap_native.h>
+
+#include "qjscursor.h"
+#include "qohauxiliary.h"
+
+QT_BEGIN_NAMESPACE
+
+QJsCursor::QJsCursor()
+    : QJsModule("@ohos.multimodalInput.pointer")
+{
+
+}
+
+QJsCursor::~QJsCursor()
+{
+
+}
+
+bool QJsCursor::isVisible() const
+{
+    return QtOh::runOnJsUIThreadWithResult([this]{
+        return call<bool>("isPointerVisibleSync");
+    });
+}
+
+void QJsCursor::setVisible(bool visible)
+{
+    QtOh::runOnJsUIThreadAndWait([this, visible]{
+        call("setPointerVisible", { Napi::Value::From(env(), visible)} );
+    });
+}
+
+void QJsCursor::setCursor(int windowId, QCursorInfo *info)
+{
+    if (info == nullptr)
+        return;
+
+    if (info->shape == HIDE) {
+        setVisible(false);
+        return;
+    } else {
+        setVisible(true);
+    }
+
+    // if (!isVisible()) {
+    //   setVisible(true);
+    // }
+
+    if (info->shape != CUSTOM) {
+        QtOh::runOnJsUIThreadAndWait([this, windowId, info]{
+            call("setPointerStyleSync", {Napi::Number::New(env(), windowId), Napi::Number::New(env(), info->shape)});
+        });
+    } else {
+        QtOh::runOnJsUIThreadAndWait([this, windowId, info]{
+            OH_PixelmapNative *nativePixel = QtOh::UdmfHelper::createNativePixelMapFromQImage(info->pixMap.toImage());
+            napi_value pixelMap { nullptr };
+            int result = ::OH_PixelmapNative_ConvertPixelmapNativeToNapi(env(), nativePixel, &pixelMap);
+            if (Image_ErrorCode::IMAGE_SUCCESS != result) {
+                ::OH_PixelmapNative_Release(nativePixel);
+                qWarning("%s convert cursor pixmap failed. code: %d", Q_FUNC_INFO, result);
+                return;
+            }
+    
+            if (QtOh::apiVersion() >= 15) {
+                Napi::Object cursor = Napi::Object::New(env());
+                cursor.Set("pixelMap", Napi::Value::From(env(), pixelMap));
+                cursor.Set("focusX", Napi::Number::New(env(), info->focusX));
+                cursor.Set("focusY", Napi::Number::New(env(), info->focusY));
+    
+                Napi::Object config = Napi::Object::New(env());
+                config.Set("followSystem", Napi::Boolean::New(env(), false));
+    
+                call("setCustomCursor", { Napi::Number::New(env(), windowId), cursor, config });
+            } else {
+                call("setCustomCursor", {Napi::Number::New(env(), windowId), Napi::Value::From(env(), pixelMap),
+                                          Napi::Number::New(env(), info->focusX), Napi::Number::New(env(), info->focusY)});
+            }
+            ::OH_PixelmapNative_Release(nativePixel);
+        });
+    }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjscursor.h b/src/plugins/platforms/openharmony/jsclass/qjscursor.h
new file mode 100644
index 00000000000..a2d486e30e1
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjscursor.h
@@ -0,0 +1,79 @@
+#ifndef QJSCURSOR_H
+#define QJSCURSOR_H
+
+#include <QPixmap>
+#include <QJsModule>
+
+QT_BEGIN_NAMESPACE
+
+struct QCursorInfo {
+    int shape;
+    int focusX = 0;
+    int focusY = 0;
+    QPixmap pixMap;
+};
+
+class QJsCursor : public QJsModule
+{
+public:
+    enum PointerStyle{
+        DEFAULT,
+        EAST,
+        WEST,
+        SOUTH,
+        NORTH,
+        WEST_EAST,
+        NORTH_SOUTH,
+        NORTH_EAST,
+        NORTH_WEST,
+        SOUTH_EAST,
+        SOUTH_WEST,
+        NORTH_EAST_SOUTH_WEST,
+        NORTH_WEST_SOUTH_EAST,
+        CROSS,
+        CURSOR_COPY,
+        CURSOR_FORBID,
+        COLOR_SUCKER,
+        HAND_GRABBING,
+        HAND_OPEN,
+        HAND_POINTING,
+        HELP,
+        MOVE,
+        RESIZE_LEFT_RIGHT,
+        RESIZE_UP_DOWN,
+        SCREENSHOT_CHOOSE,
+        SCREENSHOT_CURSOR,
+        TEXT_CURSOR,
+        ZOOM_IN,
+        ZOOM_OUT,
+        MIDDLE_BTN_EAST,
+        MIDDLE_BTN_WEST,
+        MIDDLE_BTN_SOUTH,
+        MIDDLE_BTN_NORTH,
+        MIDDLE_BTN_NORTH_SOUTH,
+        MIDDLE_BTN_NORTH_EAST,
+        MIDDLE_BTN_NORTH_WEST,
+        MIDDLE_BTN_SOUTH_EAST,
+        MIDDLE_BTN_SOUTH_WEST,
+        MIDDLE_BTN_NORTH_SOUTH_WEST_EAST,
+        HORIZONTAL_TEXT_CURSOR,
+        CURSOR_CROSS,
+        CURSOR_CIRCLE,
+        LOADING,
+        RUNNING,
+        HIDE,
+        CUSTOM=99
+    };
+    QJsCursor();
+    ~QJsCursor();
+
+    bool isVisible() const;
+
+    void setVisible(bool visible);
+
+    void setCursor(int windowId, QCursorInfo *info);
+
+};
+
+QT_END_NAMESPACE
+#endif // QJSCURSOR_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsdeviceinfo.cpp b/src/plugins/platforms/openharmony/jsclass/qjsdeviceinfo.cpp
new file mode 100644
index 00000000000..e67e8435495
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsdeviceinfo.cpp
@@ -0,0 +1,38 @@
+#include "qjsdeviceinfo.h"
+#include <qopenharmony.h>
+#include <QtCore/QRegularExpression>
+
+Q_GLOBAL_STATIC(QJsDeviceInfo, info)
+QT_BEGIN_NAMESPACE
+
+QJsDeviceInfo::QJsDeviceInfo()
+    : QJsModule("@ohos.deviceInfo")
+{
+}
+
+QJsDeviceInfo *QJsDeviceInfo::instance()
+{
+    return info();
+}
+
+QString QJsDeviceInfo::deviceType() const
+{
+    Napi::Value result = get("deviceType");
+    return QString::fromStdString(result.ToString());
+}
+
+QString QJsDeviceInfo::displayVersion() const
+{
+    //    HYM-W5821 2.0.0.66(SP59DEVC00E66R1P4log)
+    Napi::Value result = get("displayVersion");
+    QString dv = QString::fromStdString(result.ToString());
+    QRegularExpression regex("(\\d+\\.\\d+\\.\\d+\\.\\d+)");
+    QRegularExpressionMatch match = regex.match(dv);
+    if (match.hasMatch()) {
+        QString version = match.captured(1);
+        return version;
+    }
+    return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsdeviceinfo.h b/src/plugins/platforms/openharmony/jsclass/qjsdeviceinfo.h
new file mode 100644
index 00000000000..4566de9a267
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsdeviceinfo.h
@@ -0,0 +1,22 @@
+#ifndef QJSDEVICEINFO_H
+#define QJSDEVICEINFO_H
+
+#include <QSize>
+#include <QJsModule>
+
+QT_BEGIN_NAMESPACE
+
+class QJsDeviceInfo : public QJsModule
+{
+public:
+    QJsDeviceInfo();
+
+    static QJsDeviceInfo *instance();
+
+    QString deviceType() const;
+
+    QString displayVersion() const;
+};
+
+QT_END_NAMESPACE
+#endif // QJSDEVICEINFO_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsdisplay.cpp b/src/plugins/platforms/openharmony/jsclass/qjsdisplay.cpp
new file mode 100644
index 00000000000..352fc387cb7
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsdisplay.cpp
@@ -0,0 +1,115 @@
+#include <qopenharmonydefines.h>
+#include <window_manager/oh_display_info.h>
+#include <window_manager/oh_display_manager.h>
+
+#include "qohmain.h"
+#include "qjsscreen.h"
+#include "qjsdisplay.h"
+#include "qohauxiliary.h"
+#include "qohjsonlistener.h"
+
+QT_BEGIN_NAMESPACE
+
+QJsDisplay::QJsDisplay()
+    : QJsModule("@ohos.display")
+{
+    m_self = this;
+}
+
+QJsDisplay::~QJsDisplay()
+{
+    OH_NativeDisplayManager_UnregisterDisplayChangeListener(m_listenerIndex);
+    for (int i = 0; i < m_listeners.count(); ++i) {
+        m_listeners.at(i)->off();
+    }
+    qDeleteAll(m_listeners);
+    m_self = nullptr;
+}
+
+
+void QJsDisplay::initialize()
+{
+    // defaultDisplayInfo = getDisplayInfoForPrimaryDisplay(jsState);
+    auto screen = getPrimaryDisplay();
+    if (Q_UNLIKELY(screen == nullptr)) {
+        //fatal error
+        LOGE("cannot get primary display");
+        return;
+    }
+    m_screens.append(screen);
+
+    this->initialize(CreateInfo{
+        .displayChangeCb = &QJsDisplay::displayChangeCallback,
+        .displayAddedCb = [](uint64_t displayId) {
+            //todo
+        },
+        .displayRemovedCb = [](uint64_t displayId) {
+            //todo
+        },
+    });
+}
+
+void QJsDisplay::initialize(const CreateInfo& createInfo)
+{
+    NativeDisplayManager_ErrorCode errCode = NativeDisplayManager_ErrorCode::DISPLAY_MANAGER_OK;
+    errCode = OH_NativeDisplayManager_RegisterDisplayChangeListener(createInfo.displayChangeCb, &m_listenerIndex);
+    if (DISPLAY_MANAGER_OK != errCode) {
+        LOGE("register display change listener failed, err code:[%{public}d]", errCode);
+    }
+
+    QtOh::runOnJsUIThreadAndWait([this, createInfo]{
+        m_listeners << new QOhJsOnListener(this, "add", [this, createInfo](const Napi::CallbackInfo& info) {
+            if (info.Length() < 1 || !info[0].IsNumber()) {
+                return;
+            }
+            Napi::Number displayId = info[0].As<Napi::Number>();
+
+            createInfo.displayAddedCb(displayId.Uint32Value());
+        });
+        m_listeners << new QOhJsOnListener(this, "remove", [createInfo](const Napi::CallbackInfo& info) {
+            if (info.Length() < 1 || !info[0].IsNumber()) {
+                return;
+            }
+            Napi::Number displayId = info[0].As<Napi::Number>();
+
+            createInfo.displayRemovedCb(displayId.Uint32Value());
+        });
+        for (int i = 0; i < m_listeners.count(); ++i) {
+            m_listeners.at(i)->on();
+        }
+    });
+}
+
+QJsScreen *QJsDisplay::defaultScreen() const
+{
+    return m_screens.at(0);
+}
+
+QJsScreen *QJsDisplay::getPrimaryDisplay()
+{
+   Napi::Value result = call("getPrimaryDisplaySync");
+   QJsScreen *screen = result.IsObject() ? new QJsScreen(result.As<Napi::Object>()) : nullptr;
+   return screen;
+}
+
+void QJsDisplay::displayChangeCallback(uint64_t displayId)
+{
+    auto it = std::find_if(m_screens.constBegin(), m_screens.constEnd(), [displayId](QJsScreen *s){
+            return s->id() == displayId;
+    });
+    if (it == m_screens.constEnd())
+        return;
+    QJsScreen *s = *it;
+    QtOh::runOnQtMainThread([s, displayId]{
+        if (m_self == nullptr)
+            return;
+        Napi::Value result = m_self->call("getDisplayByIdSync", {Napi::Number::New(m_self->env(), displayId)});
+        if (result.IsObject()) {
+            s->setObject(result.As<Napi::Object>());
+            s->reObtainInfo();
+        }
+    });
+    LOGW("displayChangeCallback displayId=%{public}lu.", displayId);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsdisplay.h b/src/plugins/platforms/openharmony/jsclass/qjsdisplay.h
new file mode 100644
index 00000000000..224a74813d3
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsdisplay.h
@@ -0,0 +1,39 @@
+#ifndef QJSDISPLAY_H
+#define QJSDISPLAY_H
+
+#include <QSize>
+#include <QJsModule>
+#include <QList>
+class QOhJsOnListener;
+QT_BEGIN_NAMESPACE
+
+class QJsScreen;
+class QJsDisplay : public QJsModule
+{
+public:
+    QJsDisplay();
+    ~QJsDisplay();
+
+    QJsScreen *defaultScreen() const;
+    typedef void (*DisplayChangeCallback)(uint64_t displayId);
+
+    struct CreateInfo
+    {
+        DisplayChangeCallback displayChangeCb;
+        std::function<void(uint64_t)> displayAddedCb;
+        std::function<void(uint64_t)> displayRemovedCb;
+    };
+    void initialize();
+    void initialize(const CreateInfo& info);
+    static void displayChangeCallback(uint64_t displayId);
+private:
+    QJsScreen *getPrimaryDisplay();
+private:
+    static inline QList<QJsScreen *> m_screens = {};
+    static inline uint32_t m_listenerIndex = 0;
+    static inline QJsDisplay *m_self = nullptr;
+    QList<QOhJsOnListener *> m_listeners;
+};
+
+QT_END_NAMESPACE
+#endif // QJSDISPLAY_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsinputmethod.cpp b/src/plugins/platforms/openharmony/jsclass/qjsinputmethod.cpp
new file mode 100644
index 00000000000..ac6b40ceb69
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsinputmethod.cpp
@@ -0,0 +1,60 @@
+#include "qjsinputmethod.h"
+#include "qjsinputmethodcontroller.h"
+#include <QPointer>
+#include <QRect>
+#include <QDebug>
+namespace QJsInputMethod
+{
+QJsInputMethodController *getController()
+{
+    return QtOh::runOnJsUIThreadWithResult([]{
+        return new QJsInputMethodController(QSharedPointer<QJsModule>::create("@ohos.inputMethod").data());
+    });
+}
+
+const QStringList InputAttributeKeys = {"textInputType" , "enterKeyType"};
+QJsInputAttribute::QJsInputAttribute(QJsTextInputType inputType, QJsEnterKeyType enterType)
+    :m_values({int(inputType), int(enterType)})
+{
+}
+
+Napi::Object QJsInputAttribute::toObject(napi_env env) const
+{
+    Napi::Object obj = Napi::Object::New(env);
+    for(int i = 0; i < InputAttributeKeys.size(); i++)
+    {
+        obj.Set(InputAttributeKeys[i].toStdString(), Napi::Number::New(env, m_values[i]));
+    }
+    return obj;
+}
+
+QJsTextConfig::QJsTextConfig(const QJsInputAttribute &attribute)
+    :m_attribute(attribute)
+{
+}
+
+Napi::Object QJsTextConfig::toObject(napi_env env) const
+{
+    Napi::Object obj = Napi::Object::New(env);
+    obj.Set("inputAttribute", m_attribute.toObject(env));
+    return obj;
+}
+
+const QStringList cursorInfoKeys = {"left", "top", "width", "height"};
+QJsCursorInfo::QJsCursorInfo(int left, int top, int width, int height)
+    :m_values({left, top, width, height})
+{
+}
+
+Napi::Object QJsCursorInfo::toObject(napi_env env) const
+{
+    Napi::Object obj = Napi::Object::New(env);
+    for(int i = 0; i < cursorInfoKeys.size(); i++)
+    {
+        obj.Set(cursorInfoKeys[i].toStdString(), Napi::Number::New(env, m_values[i]));
+    }
+    return obj;
+}
+
+}
+
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsinputmethod.h b/src/plugins/platforms/openharmony/jsclass/qjsinputmethod.h
new file mode 100644
index 00000000000..7d1b90f3de5
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsinputmethod.h
@@ -0,0 +1,169 @@
+#ifndef QJSINPUTMETHOD_H
+#define QJSINPUTMETHOD_H
+#include <qopenharmony.h>
+#include <QRect>
+#include <QJsObject>
+namespace QJsInputMethod
+{
+    class QJsInputMethodController;
+    enum QJsTextInputType {
+        /**
+         * The text input type is NONE.
+         * @since 10
+         */
+        NONE_TEXT = -1,
+        /**
+         * The text input type is TEXT.
+         * @since 10
+         */
+        TEXT = 0,
+        /**
+         * The text input type is MULTILINE.
+         * @since 10
+         */
+        MULTILINE,
+        /**
+         * The text input type is NUMBER.
+         * @since 10
+         */
+        NUMBER,
+        /**
+         * The text input type is PHONE.
+         * @since 10
+         */
+        PHONE,
+        /**
+         * The text input type is DATETIME.
+         * @since 10
+         */
+        DATETIME,
+        /**
+         * The text input type is EMAIL_ADDRESS.
+         * @since 10
+         */
+        EMAIL_ADDRESS,
+        /**
+         * The text input type is URL.
+         * @since 10
+         */
+        URL,
+        /**
+         * The text input type is VISIBLE_PASSWORD.
+         * @since 10
+         */
+        VISIBLE_PASSWORD,
+        /**
+         * The text input type is NUMBER_PASSWORD.
+         * @since 11
+         */
+        NUMBER_PASSWORD
+    };
+    /**
+     * Enumerates the enter key type.
+     *
+     * @enum { number }
+     * @syscap SystemCapability.MiscServices.InputMethodFramework
+     * @since 10
+     */
+    enum QJsEnterKeyType {
+        /**
+         * The enter key type is UNSPECIFIED.
+         * @since 10
+         */
+        UNSPECIFIED = 0,
+        /**
+         * The enter key type is NONE.
+         * @since 10
+         */
+        NONE_ENTER = 1,
+        /**
+         * The enter key type is GO.
+         * @since 10
+         */
+        GO,
+        /**
+         * The enter key type is SEARCH.
+         * @since 10
+         */
+        SEARCH,
+        /**
+         * The enter key type is SEND.
+         * @since 10
+         */
+        SEND,
+        /**
+         * The enter key type is NEXT.
+         * @since 10
+         */
+        NEXT,
+        /**
+         * The enter key type is DONE.
+         * @since 10
+         */
+        DONE,
+        /**
+         * The enter key type is PREVIOUS.
+         * @since 10
+         */
+        PREVIOUS,
+        /**
+         * The enter key type is NEWLINE.
+         * @since 12
+         */
+        NEWLINE
+    };
+
+    enum QJsRequestKeyboardReason {
+        /**
+         * The request keyboard reason is NONE.
+         * @since 15
+         */
+        NONE = 0,
+        /**
+         * The request keyboard reason is MOUSE.
+         * @since 15
+         */
+        MOUSE = 1,
+        /**
+         * The request keyboard reason is TOUCH.
+         * @since 15
+         */
+        TOUCH = 2,
+        /**
+         * The request keyboard reason is OTHER.
+         * @since 15
+         */
+        OTHER = 20
+    };
+    class QJsInputAttribute
+    {
+    public:
+        QJsInputAttribute(QJsTextInputType, QJsEnterKeyType);
+        Napi::Object toObject(napi_env) const;
+    private:
+        QList<int> m_values = {0, 0};
+    };
+    class QJsCursorInfo
+    {
+    public:
+        QJsCursorInfo(int left, int top, int width, int height);
+        Napi::Object toObject(napi_env) const;
+    private:
+        QList<int> m_values = {0, 0, 0, 0};
+    };
+    class QJsTextConfig
+    {
+    public:
+        QJsTextConfig(const QJsInputAttribute &);
+        Napi::Object toObject(napi_env) const;
+    private:
+        QJsInputAttribute m_attribute;
+    };
+    /**
+     * @brief getController
+     * @return
+     */
+    QJsInputMethodController *getController();
+} // namespace QJsInputMethod
+
+#endif // QJSINPUTMETHOD_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsinputmethodcontroller.cpp b/src/plugins/platforms/openharmony/jsclass/qjsinputmethodcontroller.cpp
new file mode 100644
index 00000000000..37f6fc38430
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsinputmethodcontroller.cpp
@@ -0,0 +1,361 @@
+#include "qjsinputmethodcontroller.h"
+#include "qjsinputmethod.h"
+#include "qohplatforminputcontext.h"
+#include "qohwindowcontext.h"
+#include <private/qopenharmony_p.h>
+#include <private/qjspromise_p.h>
+#include <QRect>
+#include <QDebug>
+namespace QJsInputMethod
+{
+class QJsInputMethodControllerPrivate
+{
+public:
+    QJsInputMethodControllerPrivate(QJsInputMethodController *controller)
+        : q_ptr(controller)
+    {
+        Q_UNUSED(q_ptr);
+    }
+    void subscribe()
+    {
+        QHash<QString, Napi::Function>::const_iterator i = m_functions.constBegin();
+        while (i != m_functions.constEnd()) {
+            q_ptr->call("on", {Napi::String::New(q_ptr->env(), i.key().toStdString()), i.value()});
+            ++i;
+        }
+    }
+    void unsubscribe()
+    {
+        QHash<QString, Napi::Function>::const_iterator i = m_functions.constBegin();
+        while (i != m_functions.constEnd()) {
+            q_ptr->call("off",  {Napi::String::New(q_ptr->env(), i.key().toStdString())});
+            ++i;
+        }
+    }
+    bool m_attached = false;
+    bool m_visible = false;
+    QHash<QString, Napi::Function> m_functions;
+private:
+    QJsInputMethodController *q_ptr;
+};
+void QJsInputMethodController::on(QJsSubEvent *event) const
+{
+    if (event)
+    {
+        d_ptr->m_functions.insert(QString::fromStdString(event->type), event->callback);
+    }
+}
+
+void QJsInputMethodController::off(QJsSubEvent *event) const
+{
+    if (event)
+    {
+        d_ptr->m_functions.remove(QString::fromStdString(event->type));
+        delete event;
+        event = nullptr;
+    }
+}
+
+bool QJsInputMethodController::isAttached() const
+{
+    return d_ptr->m_attached;
+}
+
+#if OHOS_SDK_VERSION >= 15
+bool QJsInputMethodController::attach(const bool &, const QJsTextConfig &textConfig, QJsRequestKeyboardReason reason)
+{
+    qDebug() << "attach reason:" << reason;
+    if (isAttached()) {
+        return true;
+    }
+    d_ptr->m_attached = QtOh::runOnJsUIThreadWithPromise<bool>([&textConfig, reason, this](auto p){
+        Napi::HandleScope scope(env());
+        QJsPromise promise(call("attach", {Napi::Boolean::New(env(), true),
+                                                       textConfig.toObject(env()),
+                                                       Napi::Number::New(env(), reason)
+                                               }).As<Napi::Promise>());
+        promise.onThen([this, p](const Napi::CallbackInfo &info){
+            Q_UNUSED(info);
+            d_ptr->subscribe();
+            p->set_value(true);
+        }).onCatch([p](const Napi::CallbackInfo &info){
+                   Q_UNUSED(info);
+                   p->set_value(false);
+               });
+    });
+    d_ptr->m_visible = d_ptr->m_attached;
+    return isAttached();
+}
+void QJsInputMethodController::showTextInput(QJsRequestKeyboardReason reason)
+{
+    qDebug() << "showTextInput reason:" << reason;
+    QtOh::runOnJsUIThreadAndWait([reason, this]{
+        QJsPromise promise(call("showTextInput", {Napi::Number::New(env(), reason)}).As<Napi::Promise>());
+        promise.onThen([](const Napi::CallbackInfo &info){
+            Q_UNUSED(info);
+        });
+    });
+}
+#else
+bool QJsInputMethodController::attach(const bool &, const QJsTextConfig &textConfig)
+{
+    if (isAttached()) {
+        return true;
+    }
+    d_ptr->m_attached = QtOh::runOnJsUIThreadWithPromise<bool>([&textConfig, this](auto p){
+        Napi::HandleScope scope(env());
+        QJsPromise promise(call("attach", { Napi::Boolean::New(env(), true), textConfig.toObject(env()) }).As<Napi::Promise>());
+        promise.onThen([p](const Napi::CallbackInfo &info){
+            Q_UNUSED(info);
+            d_ptr->subscribe();
+            p->set_value(true);
+        }.onCatch([p](const Napi::CallbackInfo &info){
+                   Q_UNUSED(info);
+                   p->set_value(false);
+               });
+    });
+    d_ptr->m_visible = d_ptr->m_attached;
+    return isAttached();
+}
+
+void QJsInputMethodController::showTextInput()
+{
+    QtOh::runOnJsUIThreadAndWait([this]{
+        QJsPromise promise(call("showTextInput").As<Napi::Promise>());
+        promise.onThen([](const Napi::CallbackInfo &info){
+            Q_UNUSED(info);
+        });
+    });
+}
+#endif
+
+void QJsInputMethodController::hideTextInput()
+{
+    QtOh::runOnJsUIThreadAndWait([this]{
+        QJsPromise promise(call("hideTextInput").As<Napi::Promise>());
+        promise.onThen([](const Napi::CallbackInfo &info){
+            Q_UNUSED(info);
+        });
+    });
+}
+
+bool QJsInputMethodController::detach()
+{
+    if (!isAttached())
+        return true;
+
+    d_ptr->m_attached = QtOh::runOnJsUIThreadWithPromise<bool>([this](auto p){
+        d_ptr->unsubscribe();
+        QJsPromise promise(call("detach").As<Napi::Promise>());
+        promise.onThen([this, p](const Napi::CallbackInfo &info){
+            Q_UNUSED(info);
+            p->set_value(false);
+        }).onCatch([this](const Napi::CallbackInfo &info){
+                   Q_UNUSED(info);
+                   p->set_value(true);
+               });
+    });
+    d_ptr->m_visible = d_ptr->m_attached;
+    return !isAttached();
+}
+
+void QJsInputMethodController::setCallingWindow(int windowId)
+{
+    QtOh::runOnJsUIThreadAndWait([windowId, this]{
+        call("setCallingWindow", { Napi::Number::New(env(), windowId) });
+    });
+}
+
+void QJsInputMethodController::updateCursor(const QJsCursorInfo &cursorInfo)
+{
+    QtOh::runOnJsUIThreadAndWait([&cursorInfo, this]{
+        call("updateCursor", {cursorInfo.toObject(env())});
+    });
+}
+
+void QJsInputMethodController::changeSelection(const QString &text, int start, int end)
+{
+    QtOh::runOnJsUIThreadAndWait([text, start, end, this]{
+        call("changeSelection", {Napi::String::New(env(), text.toStdString()),
+                                 Napi::Number::New(env(), start),
+                                 Napi::Number::New(env(), end)});
+    });
+}
+
+void QJsInputMethodController::updateAttribute(const  QJsInputAttribute &attribute)
+{
+    QtOh::runOnJsUIThreadAndWait([&attribute, this]{
+        call("updateAttribute", {attribute.toObject(env())});
+    });
+}
+
+void QJsInputMethodController::stopInputSession()
+{
+    QtOh::runOnJsUIThreadAndWait([this]{
+        call("stopInputSession");
+    });
+}
+
+void QJsInputMethodController::showSoftKeyboard()
+{
+    QtOh::runOnJsUIThreadAndWait([=, this]{
+        auto asyncFunc = Napi::Function::New(env(), [this](const Napi::CallbackInfo& info){
+            Q_UNUSED(info);
+            d_ptr->m_visible = true;
+        });
+        call("showSoftKeyboard", {asyncFunc});
+    });
+}
+
+void QJsInputMethodController::hideSoftKeyboard()
+{
+    QtOh::runOnJsUIThreadAndWait([this]{
+        auto asyncFunc = Napi::Function::New(env(), [this](const Napi::CallbackInfo& info){
+            Q_UNUSED(info);
+            d_ptr->m_visible = false;
+        });
+        call("hideSoftKeyboard", { asyncFunc });
+    });
+}
+
+bool QJsInputMethodController::isInputPanelVisible() const
+{
+    return d_ptr->m_visible;
+}
+
+void QJsInputMethodController::setInputPanelVisible(bool visible)
+{
+    d_ptr->m_visible = visible;
+}
+
+static QJsSubEvent *insertTextEvent = nullptr;
+QJsSubEvent *QJsInputMethodController::insertText()
+{
+    if (!insertTextEvent || !QOhPlatformInputContext::inputMethodController())
+        QtOh::runOnJsUIThreadAndWait([]{
+            auto context = QOhPlatformInputContext::ohInputContext();
+            insertTextEvent = new QJsSubEvent("insertText", [context](const Napi::CallbackInfo& info) {
+                if (info.Length() < 1)
+                    return;
+                QString text = QString::fromStdString(info[0].ToString());
+                QMetaObject::invokeMethod(context,
+                                          "commitText", Qt::QueuedConnection, Q_ARG(QString, text));
+            }, context->inputMethodController()->env());
+        });
+    return insertTextEvent;
+}
+
+static QJsSubEvent *sendFunctionKeyEvent = nullptr;
+QJsSubEvent *QJsInputMethodController::sendFunctionKey()
+{
+    if (!sendFunctionKeyEvent || !QOhPlatformInputContext::inputMethodController())
+        QtOh::runOnJsUIThreadAndWait([]{
+            auto context = QOhPlatformInputContext::ohInputContext();
+            sendFunctionKeyEvent = new QJsSubEvent("sendFunctionKey", [context](const Napi::CallbackInfo& info) {
+                Q_UNUSED(info);
+                QMetaObject::invokeMethod(context, "enterKeyDown", Qt::QueuedConnection);
+            }, context->inputMethodController()->env());
+        });
+    return sendFunctionKeyEvent;
+}
+
+static QJsSubEvent *sendKeyboardStatusEvent = nullptr;
+QJsSubEvent *QJsInputMethodController::sendKeyboardStatus()
+{
+    if (!sendKeyboardStatusEvent || !QOhPlatformInputContext::inputMethodController())
+        QtOh::runOnJsUIThreadAndWait([]{
+            sendKeyboardStatusEvent = new QJsSubEvent("sendKeyboardStatus", [](const Napi::CallbackInfo& info) {
+                if (!QOhPlatformInputContext::inputMethodController())
+                    return;
+                if (info.Length() < 1)
+                    return;
+                int status = info[0].ToNumber();
+                switch (status) {
+                //NOTE:只能收到NONE(12 release beta1)
+                case 0:
+                case 1:
+                    QOhPlatformInputContext::inputMethodController()->setInputPanelVisible(false);
+                    QOhPlatformInputContext::inputMethodController()->detach();
+                    break;
+                case 2:
+                    QOhPlatformInputContext::inputMethodController()->setInputPanelVisible(true);
+                    break;
+                default:
+                    break;
+                }
+            }, QOhPlatformInputContext::inputMethodController()->env());
+        });
+    return sendKeyboardStatusEvent;
+}
+
+static QJsSubEvent *deleteLeftEvent = nullptr;
+QJsSubEvent *QJsInputMethodController::deleteLeft()
+{
+    if (!deleteLeftEvent || !QOhPlatformInputContext::inputMethodController())
+        QtOh::runOnJsUIThreadAndWait([]{
+            auto context = QOhPlatformInputContext::ohInputContext();
+            deleteLeftEvent = new QJsSubEvent("deleteLeft", [context](const Napi::CallbackInfo& info) {
+                Q_UNUSED(info);
+                Qt::KeyboardModifiers mods = context->queryKeyboardModifiers();
+                QWindowSystemInterface::handleExtendedKeyEvent(QOhWindowContext::mouseGrabberWindow(),
+                                                               QEvent::KeyPress, Qt::Key_Backspace,
+                                                               mods, KEY_DEL, KEY_DEL, int(mods));
+
+                QWindowSystemInterface::handleExtendedKeyEvent(QOhWindowContext::mouseGrabberWindow(),
+                                                               QEvent::KeyRelease, Qt::Key_Backspace,
+                                                               mods, KEY_DEL, KEY_DEL, int(mods));
+            }, context->inputMethodController()->env());
+        });
+    return deleteLeftEvent;
+
+}
+static QJsSubEvent *deleteRightEvent = nullptr;
+QJsSubEvent *QJsInputMethodController::deleteRight()
+{
+    if (!deleteRightEvent || !QOhPlatformInputContext::inputMethodController())
+        QtOh::runOnJsUIThreadAndWait([]{
+            auto context = QOhPlatformInputContext::ohInputContext();
+            deleteRightEvent = new QJsSubEvent("deleteRight", [context](const Napi::CallbackInfo& info) {
+                Q_UNUSED(info);
+                Qt::KeyboardModifiers mods = context->queryKeyboardModifiers();
+                QWindowSystemInterface::handleExtendedKeyEvent(QOhWindowContext::mouseGrabberWindow(),
+                                                               QEvent::KeyPress, Qt::Key_Delete,
+                                                               mods, KEY_FORWARD_DEL, KEY_FORWARD_DEL, int(mods));
+
+                QWindowSystemInterface::handleExtendedKeyEvent(QOhWindowContext::mouseGrabberWindow(),
+                                                               QEvent::KeyRelease, Qt::Key_Delete,
+                                                               mods, KEY_FORWARD_DEL, KEY_FORWARD_DEL, int(mods));
+            }, context->inputMethodController()->env());
+        });
+    return deleteRightEvent;
+}
+
+static QJsSubEvent *moveCursorEvent = nullptr;
+QJsSubEvent *QJsInputMethodController::moveCursor()
+{
+    if (!moveCursorEvent || !QOhPlatformInputContext::inputMethodController())
+        QtOh::runOnJsUIThreadAndWait([]{
+            auto context = QOhPlatformInputContext::ohInputContext();
+            moveCursorEvent = new QJsSubEvent("moveCursor", [context](const Napi::CallbackInfo& info) {
+                if (info.Length() < 1)
+                    return;
+                int direction = info[0].ToNumber();
+                QMetaObject::invokeMethod(context, "commitMoveCursor", Qt::QueuedConnection, Q_ARG(int, direction));
+            }, context->inputMethodController()->env());
+        });
+    return moveCursorEvent;
+}
+
+QJsInputMethodController::QJsInputMethodController(QJsModule *inputMethod)
+    : QJsObject(inputMethod->call("getController").As<Napi::Object>()),
+    d_ptr(new QJsInputMethodControllerPrivate(this))
+{
+
+}
+
+QJsInputMethodController::~QJsInputMethodController()
+{
+    detach();
+    delete d_ptr;
+}
+}
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsinputmethodcontroller.h b/src/plugins/platforms/openharmony/jsclass/qjsinputmethodcontroller.h
new file mode 100644
index 00000000000..89c9711594d
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsinputmethodcontroller.h
@@ -0,0 +1,59 @@
+#ifndef QJSINPUTMETHODCONTROLLER_H
+#define QJSINPUTMETHODCONTROLLER_H
+// #include "qjsinputmethod.h"
+
+#include "qjsinputmethod.h"
+#include <QJsModule>
+namespace QJsInputMethod
+{
+
+class QJsInputMethodControllerPrivate;
+
+
+class QJsInputMethodController : public QJsObject
+{
+public:
+
+    ~QJsInputMethodController();
+    bool isAttached() const;
+#if OHOS_SDK_VERSION >= 15
+
+    bool attach(const bool &, const QJsTextConfig &, QJsRequestKeyboardReason reason = QJsRequestKeyboardReason::OTHER);
+    void showTextInput(QJsRequestKeyboardReason reason = QJsRequestKeyboardReason::OTHER);
+#else
+    bool attach(const bool &, const QJsTextConfig &);
+    void showTextInput();
+#endif
+    void hideTextInput();
+    bool detach();
+    void setCallingWindow(int windowId);
+    void updateCursor(const QJsCursorInfo &);
+    void changeSelection(const QString &, int, int);
+    void updateAttribute(const QJsInputAttribute &);
+    void stopInputSession();
+    void showSoftKeyboard();
+    void hideSoftKeyboard();
+    bool isInputPanelVisible() const;
+    void setInputPanelVisible(bool visible);
+    /**
+     * @brief InputMethodController订阅事件
+     */
+public:
+    void on(QJsSubEvent *) const;
+    void off(QJsSubEvent *) const;
+    static QJsSubEvent *insertText();
+    static QJsSubEvent *sendFunctionKey();
+    static QJsSubEvent *sendKeyboardStatus();
+    static QJsSubEvent *deleteLeft();
+    static QJsSubEvent *deleteRight();
+    static QJsSubEvent *moveCursor();
+
+private:
+    friend QJsInputMethodController* QJsInputMethod::getController();
+    QJsInputMethodController(QJsModule *inputMethod);
+
+    QJsInputMethodControllerPrivate *d_ptr = nullptr;
+};
+}; // namespace QJsInputMethod
+
+#endif // QJSINPUTMETHODCONTROLLER_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsscreen.cpp b/src/plugins/platforms/openharmony/jsclass/qjsscreen.cpp
new file mode 100644
index 00000000000..2fad10eb8d3
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsscreen.cpp
@@ -0,0 +1,199 @@
+#include <QDebug>
+
+#include "qohmain.h"
+#include "qjsscreen.h"
+#include <qopenharmony.h>
+#include "qohauxiliary.h"
+#include "qohjsonlistener.h"
+#include "qohplatformscreen.h"
+#include <private/qjspromise_p.h>
+QT_BEGIN_NAMESPACE
+
+QJsScreen::QJsScreen(Napi::Object jsObject)
+    : QJsObject(jsObject)
+    , m_platformScreen(nullptr)
+{
+    obtainInfo();
+    m_availableAreaChangeListener = new QOhJsOnListener(this, "availableAreaChange", [this](const Napi::CallbackInfo& info) {
+        if (info.Length() < 1 || !info[0].IsObject()) {
+            return;
+        }
+        auto rectObj = info[0].ToObject();
+        QRect rect = QtOh::jsRect2QRect(rectObj);
+
+        qDebug() << "availableAreaChange" << this->m_info.id << rect;
+
+        QtOh::runOnQtMainThread([this, rect]{
+            if (m_platformScreen) {
+                m_platformScreen->setAvailableGeometry(rect);
+            }
+        });
+    });
+    m_availableAreaChangeListener->on();
+}
+
+QJsScreen::~QJsScreen()
+{
+    m_availableAreaChangeListener->off();
+    delete m_availableAreaChangeListener;
+}
+
+void QJsScreen::attach(QOhPlatformScreen *platformScreen)
+{
+    m_platformScreen = platformScreen;
+}
+
+uint32_t QJsScreen::id() const
+{
+    return m_info.id;
+}
+
+Qt::ScreenOrientation QJsScreen::orientation() const
+{
+    return m_info.orientation;
+}
+
+QSize QJsScreen::size() const
+{
+    return m_info.s;
+}
+
+QRect QJsScreen::availableGeometry() const
+{
+    return m_info.available;
+}
+
+QSize QJsScreen::physicalSize() const
+{
+    return m_info.ps;
+}
+
+qreal QJsScreen::densityPixels() const
+{
+    return m_info.densityPixels;
+}
+
+qreal QJsScreen::scaledDensity() const
+{
+    return m_info.scaledDensity;
+}
+
+qreal QJsScreen::oldScaledDensity() const
+{
+    return m_info.oldScaledDensity;
+}
+
+qreal QJsScreen::pixelDensity() const
+{
+    return m_info.densityDPI / 160; // 96?
+}
+
+int QJsScreen::refreshRate() const
+{
+    return m_info.refreshRate;
+}
+
+qreal QJsScreen::densityDPI() const
+{
+    return m_info.densityDPI;
+}
+
+qreal QJsScreen::xDPI() const
+{
+    return m_info.xDPI;
+}
+
+qreal QJsScreen::yDPI() const
+{
+    return m_info.yDPI;
+}
+
+void QJsScreen::reObtainInfo()
+{
+    ScreenInfo old = m_info;
+    obtainInfo();
+
+    bool orientationChanged = (old.orientation != m_info.orientation);
+    if (orientationChanged)
+        m_platformScreen->handleScreenOrientationChange();
+    bool refreshRateChanged = (old.refreshRate != m_info.refreshRate);
+    if (refreshRateChanged)
+        m_platformScreen->handlerefreshRateChange(m_info.refreshRate);
+
+    bool scaledDensityChanged = !qFuzzyCompare(old.scaledDensity, m_info.scaledDensity);
+    if (scaledDensityChanged)
+        m_platformScreen->handleScreenLogicalDotsPerInchChange();
+    if (m_info.ps != old.ps)
+        m_platformScreen->setPhysicalSize(m_info.ps);
+    if (m_info.available != old.available)
+        m_platformScreen->setAvailableGeometry(availableGeometry());
+    m_platformScreen->setSize(m_info.s);
+    if (scaledDensityChanged) {
+        m_info.oldScaledDensity = old.scaledDensity;
+        m_platformScreen->handleScreenChanged();
+    }
+}
+
+void QJsScreen::obtainInfo()
+{
+    Napi::Value width = get("width");
+    Napi::Value height = get("height");
+    QSize s = QSize(width.ToNumber().Int32Value(), height.ToNumber().Int32Value());
+    m_info.s = s;
+    m_info.id = get("id").ToNumber().Int32Value();
+    Napi::Value densityPixels = get("densityPixels");
+    Napi::Value scaledDensity = get("scaledDensity");
+    m_info.densityPixels = densityPixels.ToNumber().DoubleValue();
+    m_info.scaledDensity = scaledDensity.ToNumber().DoubleValue();
+    m_info.oldScaledDensity = m_info.scaledDensity;
+    m_info.refreshRate = get("refreshRate").ToNumber().Int32Value();
+
+    // openharmony old api, xdpi and ydpi is 0
+    double xdpi = get("xDPI").ToNumber().DoubleValue();
+    double ydpi = get("yDPI").ToNumber().DoubleValue();
+
+    double densityDPI = get("densityDPI").ToNumber().DoubleValue();
+    if (qFuzzyCompare(xdpi, 0))
+        xdpi = densityDPI;
+    if (qFuzzyCompare(ydpi, 0))
+        ydpi = densityDPI;
+
+    m_info.xDPI = xdpi;
+    m_info.yDPI = ydpi;
+    m_info.densityDPI = densityDPI;
+    m_info.ps = QSize(qRound(double(s.width()) / xdpi * 25.4), qRound(double(s.height()) / ydpi * 25.4));
+    int32_t orientation = get("orientation").ToNumber();
+    switch (orientation) {
+    case 0:
+        m_info.orientation = Qt::PortraitOrientation;
+        break;
+    case 1:
+        m_info.orientation = Qt::LandscapeOrientation;
+        break;
+    case 2:
+        m_info.orientation = Qt::InvertedPortraitOrientation;
+        break;
+    case 3:
+        m_info.orientation = Qt::InvertedLandscapeOrientation;
+        break;
+    }
+
+    const QtOh::Utility::DeviceType deviceType = QtOh::Utility::type();
+    if (deviceType == QtOh::Utility::PC || deviceType == QtOh::Utility::Tablet) {
+        Napi::Value result = call("getAvailableArea");
+        if (!result.IsPromise()) {
+            return;
+        }
+        QJsPromise promise(result.As<Napi::Promise>());
+        promise.onThen([&](const Napi::CallbackInfo &info) {
+            if (info.Length() < 1)
+                return;
+            Napi::Object object = info[0].ToObject();
+            m_info.available = QtOh::jsRect2QRect(object);
+        });
+    } else {
+        m_info.available = QRect(0, 0, s.width(), s.height());
+    }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsscreen.h b/src/plugins/platforms/openharmony/jsclass/qjsscreen.h
new file mode 100644
index 00000000000..97e7a0fcbad
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsscreen.h
@@ -0,0 +1,73 @@
+#ifndef QJSSCREEN_H
+#define QJSSCREEN_H
+
+#include "qjsobject.h"
+
+#include <QSize>
+#include <QRect>
+
+QT_BEGIN_NAMESPACE
+class QOhPlatformScreen;
+class QOhJsOnListener;
+class QJsScreen : public QJsObject
+{
+    struct ScreenInfo
+    {
+        uint32_t id;
+        QSize s;
+        QSize ps;
+        QRect available;
+        int densityDPI;
+        qreal xDPI;
+        qreal yDPI;
+        qreal densityPixels;
+        qreal scaledDensity;
+        qreal oldScaledDensity;
+        int refreshRate;
+        Qt::ScreenOrientation orientation;
+    };
+
+public:
+    QJsScreen(Napi::Object jsObject);
+    ~QJsScreen();
+
+    void attach(QOhPlatformScreen *platformScreen);
+
+    uint32_t id() const;
+
+    Qt::ScreenOrientation orientation() const;
+
+    QSize size() const;
+
+    QRect availableGeometry() const;
+
+    QSize physicalSize() const;
+
+    qreal densityPixels() const;
+
+    qreal scaledDensity() const;
+
+    qreal oldScaledDensity() const;
+
+    qreal pixelDensity() const;
+
+    int refreshRate() const;
+
+    qreal densityDPI() const;
+
+    qreal xDPI() const;
+
+    qreal yDPI() const;
+
+    void reObtainInfo();
+
+private:
+    void obtainInfo();
+private:
+    ScreenInfo m_info;
+    QOhPlatformScreen *m_platformScreen;
+    QOhJsOnListener *m_availableAreaChangeListener;
+};
+
+QT_END_NAMESPACE
+#endif // QJSSCREEN_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjssettings.cpp b/src/plugins/platforms/openharmony/jsclass/qjssettings.cpp
new file mode 100644
index 00000000000..30ed8cc010c
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjssettings.cpp
@@ -0,0 +1,116 @@
+#include <qdebug.h>
+
+#include "qjssettings.h"
+#include "qjscontext.h"
+#include "qohauxiliary.h"
+#include "qohnativewindow.h"
+#include "qohnativewindowmanager.h"
+#include <private/qopenharmony_p.h>
+
+namespace DomainName {
+const char DEVICE_SHARED[] = "global";
+const char USER_PROPERTY[] = "system";
+}
+
+QT_BEGIN_NAMESPACE
+Q_GLOBAL_STATIC(QJsSettings, settings)
+
+QJsSettings::QJsSettings()
+    : QJsModule("@ohos.settings")
+{
+    m_freeWindowEnable = getValueSync("window_pcmode_switch_status", "false", DomainName::USER_PROPERTY)== "true";
+
+    registerKeyObserver("window_pcmode_switch_status", [this]{
+        if (!QtOh::isPhoneDevice() && !QtOh::isTabletDevice()) {
+            return;
+        }
+
+        bool isFreeWindowEnable = QJsSettings::instance()->isFreeWindowEnable();
+        QtOh::runOnQtMainThread([isFreeWindowEnable]{
+            for (QOhNativeWindow *nativeWindow : QOhNativeWindow::allWindows()) {
+                nativeWindow->handleFreeWindowEnableChanged(isFreeWindowEnable);
+            }
+        });
+
+        auto extraHandler = get("pcModeChangedListener");
+        if (extraHandler.IsEmpty() || !extraHandler.IsFunction())
+            return;
+        call("pcModeChangedListener", {Napi::Boolean::New(env(), isFreeWindowEnable)});
+
+    }, true, qNativeWindowManager->context());
+}
+
+QJsSettings::~QJsSettings()
+{
+    unregisterKeyObserver("window_pcmode_switch_status", true, qNativeWindowManager->context());
+}
+
+
+
+bool QJsSettings::isFreeWindowEnable() const
+{
+    m_freeWindowEnable = getValueSync("window_pcmode_switch_status", "false", DomainName::USER_PROPERTY)== "true";
+    return m_freeWindowEnable;
+}
+
+QString QJsSettings::getValueFromUserDomain(const QString &name) const
+{
+    return getValueSync(name, "", DomainName::USER_PROPERTY);
+}
+
+QString QJsSettings::getValueFromSharedDomain(const QString &name) const
+{
+    return getValueSync(name, "", DomainName::DEVICE_SHARED);
+}
+
+QString QJsSettings::getValueSync(const QString &name, const QString &defaultValue, const QString &domainName) const
+{
+    QJsContext *context = qNativeWindowManager->context();
+    if (context == nullptr)
+        return QString();
+    return QtOh::runOnJsUIThreadWithResult([this, context](const QString &defaultValue, const QString &name, const QString &domainName){
+        return call<QString>("getValueSync", { context->object(), Napi::String::New(env(), name.toStdString()),
+                                                    Napi::String::New(env(), defaultValue.toStdString()), Napi::String::New(env(), domainName.toStdString())});
+    }, defaultValue, name, domainName);
+}
+
+void QJsSettings::registerKeyObserver(const QString &name, const std::function<void()> &task, bool userDomain, QJsContext *context)
+{
+    QJsContext *_context = context;
+    if (_context == nullptr) {
+        _context = qNativeWindowManager->context();
+        return;
+    }
+    if (_context == nullptr)
+        return;
+    QtOh::runOnJsUIThreadAndWait([&](){
+        QString domainName = userDomain ? DomainName::USER_PROPERTY : DomainName::DEVICE_SHARED;
+        Napi::Function callback = Napi::Function::New(env(), [jsTask = std::move(task)](const Napi::CallbackInfo& info) {
+            jsTask();
+        });
+        call("registerKeyObserver", { _context->object(), Napi::String::New(env(), name.toStdString()),
+                                                    Napi::String::New(env(), domainName.toStdString()), callback});
+    });
+}
+
+void QJsSettings::unregisterKeyObserver(const QString &name, bool userDomain, QJsContext *context)
+{
+    QJsContext *_context = context;
+    if (_context == nullptr) {
+        _context = qNativeWindowManager->context();
+        return;
+    }
+    if (_context == nullptr)
+        return;
+    QtOh::runOnJsUIThreadAndWait([&](){
+        QString domainName = userDomain ? DomainName::USER_PROPERTY : DomainName::DEVICE_SHARED;
+        call("unregisterKeyObserver", { _context->object(), Napi::String::New(env(), name.toStdString()),
+                                      Napi::String::New(env(), domainName.toStdString())});
+    });
+}
+
+QJsSettings *QJsSettings::instance()
+{
+    return settings();
+}
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjssettings.h b/src/plugins/platforms/openharmony/jsclass/qjssettings.h
new file mode 100644
index 00000000000..8f48a692863
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjssettings.h
@@ -0,0 +1,31 @@
+#ifndef QJSSETTINGS_H
+#define QJSSETTINGS_H
+
+#include <QString>
+#include <QJsModule>
+
+QT_BEGIN_NAMESPACE
+class QJsContext;
+class QJsSettings : public QJsModule
+{
+public:
+    QJsSettings();
+    ~QJsSettings();
+
+    static QJsSettings *instance();
+
+    bool isFreeWindowEnable() const;
+
+    QString getValueFromUserDomain(const QString &name) const;
+
+    QString getValueFromSharedDomain(const QString &name) const;
+
+    void registerKeyObserver(const QString &name, const std::function<void()> &task, bool userDomain = true, QJsContext *context = nullptr);
+    void unregisterKeyObserver(const QString &name, bool userDomain = true, QJsContext *context = nullptr);
+private:
+    QString getValueSync(const QString &name, const QString &defaultValue, const QString &domainName) const;
+    mutable bool m_freeWindowEnable = false;
+};
+
+QT_END_NAMESPACE
+#endif // QJSSETTINGS_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsuiability.cpp b/src/plugins/platforms/openharmony/jsclass/qjsuiability.cpp
new file mode 100644
index 00000000000..2a766ba134f
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsuiability.cpp
@@ -0,0 +1,35 @@
+#include "qjsuiability.h"
+#include "qohnativewindowmanager.h"
+#include "qjsuiabilitycontext.h"
+#include <private/qopenharmony_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QJsUIAbility::QJsUIAbility(Napi::Object jsUIAbility)
+    : QJsAbility(jsUIAbility)
+{
+
+}
+
+QJsUIAbility::~QJsUIAbility()
+{
+    if (m_context != nullptr)
+        delete m_context;
+}
+
+QJsContext *QJsUIAbility::context() const
+{
+    if (m_context == nullptr) {
+        m_context = QtOh::runOnJsUIThreadWithResult([this]{
+            return new QJsUIAbilityContext(get("context").ToObject());
+        });
+    }
+    return m_context;
+}
+
+QJsAbility::AbilityType QJsUIAbility::abilityType() const
+{
+    return AbilityType::UIAbility;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsuiability.h b/src/plugins/platforms/openharmony/jsclass/qjsuiability.h
new file mode 100644
index 00000000000..4a8e61c9bd2
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsuiability.h
@@ -0,0 +1,25 @@
+#ifndef QJSUIABILITY_H
+#define QJSUIABILITY_H
+
+#include <QByteArray>
+
+#include "qjsability.h"
+
+QT_BEGIN_NAMESPACE
+
+class QJsWant;
+class QJsUIAbilityContext;
+
+class QJsUIAbility : public QJsAbility
+{
+public:
+    QJsUIAbility(Napi::Object jsUIAbility);
+    virtual ~QJsUIAbility();
+
+    QJsContext *context() const override;
+
+    AbilityType abilityType() const override;
+};
+
+QT_END_NAMESPACE
+#endif // QJSUIABILITY_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsuiabilitycontext.cpp b/src/plugins/platforms/openharmony/jsclass/qjsuiabilitycontext.cpp
new file mode 100644
index 00000000000..47ecdc26a0a
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsuiabilitycontext.cpp
@@ -0,0 +1,34 @@
+#include "qjsabilityinfo.h"
+#include "qjsuiabilitycontext.h"
+#include <private/qopenharmony_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QJsUIAbilityContext::QJsUIAbilityContext(Napi::Object jsObject)
+    : QJsContext(jsObject)
+    , m_abilityInfo(nullptr)
+{
+
+}
+
+QJsUIAbilityContext::~QJsUIAbilityContext()
+{
+
+}
+
+QJsAbilityInfo *QJsUIAbilityContext::abilityInfo()
+{
+    if (m_abilityInfo == nullptr) {
+        m_abilityInfo = QtOh::runOnJsUIThreadWithResult([this]{
+            return new QJsAbilityInfo(get("abilityInfo").ToObject());
+        });
+    }
+    return m_abilityInfo;
+}
+
+QJsContext::ContextType QJsUIAbilityContext::contextType() const
+{
+    return ContextType::UIContext;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsuiabilitycontext.h b/src/plugins/platforms/openharmony/jsclass/qjsuiabilitycontext.h
new file mode 100644
index 00000000000..8330ce8d1bf
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsuiabilitycontext.h
@@ -0,0 +1,28 @@
+#ifndef QJSUIABILITYCONTEXT_H
+#define QJSUIABILITYCONTEXT_H
+
+#include "qjscontext.h"
+
+struct NativeResourceManager;
+
+QT_BEGIN_NAMESPACE
+
+class QJsWindowStage;
+class QJsAbilityInfo;
+class QJsApplicationContext;
+
+class QJsUIAbilityContext : public QJsContext
+{
+public:
+    QJsUIAbilityContext(Napi::Object jsObject);
+    ~QJsUIAbilityContext();
+
+    QJsAbilityInfo *abilityInfo();
+
+    ContextType contextType() const override;
+private:
+    QJsAbilityInfo *m_abilityInfo;
+};
+
+QT_END_NAMESPACE
+#endif // QJSUIABILITYCONTEXT_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsuiextensionability.cpp b/src/plugins/platforms/openharmony/jsclass/qjsuiextensionability.cpp
new file mode 100644
index 00000000000..404ace5cc5c
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsuiextensionability.cpp
@@ -0,0 +1,43 @@
+#include <QtCore/qopenharmonydefines.h>
+
+#include "qjsuiextensionability.h"
+#include "qjsuiextensioncontext.h"
+#include "qjsuiextensioncontextsession.h"
+#include <private/qopenharmony_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QJsUIExtensionAbility::QJsUIExtensionAbility(Napi::Object jsUIAbility, Napi::Object session)
+    : QJsAbility(jsUIAbility),
+    m_session(new QJsUIExtensionContextSession(session))
+{
+
+}
+
+QJsUIExtensionAbility::~QJsUIExtensionAbility()
+{
+    if (m_context != nullptr)
+        delete m_context;
+}
+
+QJsContext *QJsUIExtensionAbility::context() const
+{
+    if (m_context == nullptr) {
+        m_context = QtOh::runOnJsUIThreadWithResult([this]{
+            return new QJsUIExtensionContext(get("context").ToObject());
+        });
+    }
+    return m_context;
+}
+
+QJsAbility::AbilityType QJsUIExtensionAbility::abilityType() const
+{
+    return AbilityType::UIExtensionAbility;
+}
+
+QJsUIExtensionContextSession *QJsUIExtensionAbility::session() const
+{
+    return m_session;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsuiextensionability.h b/src/plugins/platforms/openharmony/jsclass/qjsuiextensionability.h
new file mode 100644
index 00000000000..3c51e1c101e
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsuiextensionability.h
@@ -0,0 +1,26 @@
+#ifndef QJSUIEXTENSIONABILITY_H
+#define QJSUIEXTENSIONABILITY_H
+
+#include "qjsability.h"
+
+QT_BEGIN_NAMESPACE
+
+class QJsUIExtensionContextSession;
+
+class QJsUIExtensionAbility : public QJsAbility
+{
+public:
+    QJsUIExtensionAbility(Napi::Object jsUIAbility, Napi::Object session);
+    virtual ~QJsUIExtensionAbility();
+
+    QJsContext *context() const override;
+
+    AbilityType abilityType() const override;
+
+    QJsUIExtensionContextSession* session() const;
+private:
+    mutable QJsUIExtensionContextSession* m_session = nullptr;
+};
+
+QT_END_NAMESPACE
+#endif // QJSUIEXTENSIONABILITY_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsuiextensioncontext.cpp b/src/plugins/platforms/openharmony/jsclass/qjsuiextensioncontext.cpp
new file mode 100644
index 00000000000..20219ed6b2d
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsuiextensioncontext.cpp
@@ -0,0 +1,21 @@
+#include "qjsuiextensioncontext.h"
+
+QT_BEGIN_NAMESPACE
+
+QJsUIExtensionContext::QJsUIExtensionContext(Napi::Object jsObject)
+    : QJsContext(jsObject)
+{
+
+}
+
+QJsUIExtensionContext::~QJsUIExtensionContext()
+{
+
+}
+
+QJsContext::ContextType QJsUIExtensionContext::contextType() const
+{
+    return ContextType::UIExtensionContext;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsuiextensioncontext.h b/src/plugins/platforms/openharmony/jsclass/qjsuiextensioncontext.h
new file mode 100644
index 00000000000..5c0ef56d1fb
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsuiextensioncontext.h
@@ -0,0 +1,18 @@
+#ifndef QJSUIEXTENSIONCONTEXT_H
+#define QJSUIEXTENSIONCONTEXT_H
+
+#include "qjscontext.h"
+
+QT_BEGIN_NAMESPACE
+
+class QJsUIExtensionContext : public QJsContext
+{
+public:
+    QJsUIExtensionContext(Napi::Object jsObject);
+    ~QJsUIExtensionContext();
+
+    ContextType contextType() const override;
+};
+
+QT_END_NAMESPACE
+#endif // QJSUIEXTENSIONCONTEXT_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsuiextensioncontextsession.cpp b/src/plugins/platforms/openharmony/jsclass/qjsuiextensioncontextsession.cpp
new file mode 100644
index 00000000000..c0c4930d194
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsuiextensioncontextsession.cpp
@@ -0,0 +1,19 @@
+#include "qjsuiextensioncontextsession.h"
+#include <QtCore/qopenharmonydefines.h>
+
+QT_BEGIN_NAMESPACE
+
+QJsUIExtensionContextSession::QJsUIExtensionContextSession(Napi::Object jsObject)
+    : QJsWindowProxy(jsObject)
+{
+}
+
+QJsUIExtensionContextSession::~QJsUIExtensionContextSession() { }
+
+Napi::Object QJsUIExtensionContextSession::mainwindow()
+{ 
+    Napi::Value result = call("getUIExtensionWindowProxy");
+    return result.As<Napi::Object>();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjsuiextensioncontextsession.h b/src/plugins/platforms/openharmony/jsclass/qjsuiextensioncontextsession.h
new file mode 100644
index 00000000000..749fd54d8ea
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjsuiextensioncontextsession.h
@@ -0,0 +1,19 @@
+#ifndef QJSUIEXTENSIONCONTEXTSESSION_H
+#define QJSUIEXTENSIONCONTEXTSESSION_H
+
+#include "qjswindowproxy.h"
+
+QT_BEGIN_NAMESPACE
+
+class QJsWindowStage;
+class QJsUIExtensionContextSession : public QJsWindowProxy
+{
+public:
+    QJsUIExtensionContextSession(Napi::Object jsObject);
+    ~QJsUIExtensionContextSession();
+
+    Napi::Object mainwindow() override;
+};
+
+QT_END_NAMESPACE
+#endif // QJSUIEXTENSIONCONTEXTSESSION_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjswant.cpp b/src/plugins/platforms/openharmony/jsclass/qjswant.cpp
new file mode 100644
index 00000000000..ff5edce37b6
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjswant.cpp
@@ -0,0 +1,152 @@
+#include "qjswant.h"
+#include <qnapi.h>
+#include <private/qopenharmony_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QString QJsWant::defaultWindowName = "qt_entry_window";
+
+QJsWant::QJsWant(Napi::Object jsObject)
+    : QJsObject(jsObject)
+{
+
+}
+
+QJsWant::~QJsWant()
+{
+
+}
+
+bool QJsWant::isSilentStart() const
+{
+    if (!object().Has("parameters"))
+        return false;
+
+    auto jsParameters = get("parameters");
+    return QNapi::getOrDefault<bool>(jsParameters, "ability.param.extra.isSilentStart", false);
+}
+
+QString QJsWant::bundleName() const
+{
+    return QString::fromStdString(get("bundleName").ToString());
+}
+
+QString QJsWant::abilityName() const
+{
+    return QString::fromStdString(get("abilityName").ToString());
+}
+
+void QJsWant::saveParamsToEnv()
+{
+    auto setEnv = [](const char *name, const QByteArray &value) {
+        if (::setenv(name, value.constData(), 1) != 0) {
+             LOGE("Can't set environment for %{public}s", name);
+        } else {
+             LOGI("Set environment for %{public}s", name);
+        }
+    };
+    if (object().Has("parameters")) {
+        Napi::Object jsParameters = get("parameters").As<Napi::Object>();
+        auto keys = jsParameters.GetPropertyNames();
+        for (uint32_t i = 0; i < keys.Length(); ++i) {
+            Napi::Value key = keys.Get(i);
+            Napi::Value value = jsParameters.Get(key);
+            std::string keyStr = key.As<Napi::String>();
+            setEnv(keyStr.data(), QByteArray::fromStdString(value.ToString()));
+        }
+    }
+}
+
+static inline QByteArray pathFromUri(const QByteArray &uri)
+{
+    return QtOh::pathFromUri(QString::fromUtf8(uri)).toUtf8();
+}
+
+QList<QByteArray> QJsWant::launchParams() const
+{
+    QList<QByteArray> result;
+    auto u = uri();
+    if (!u.isEmpty()) {
+        result << pathFromUri(u);
+    }
+
+    if (object().Has("parameters")) {
+        Napi::Object jsParameters = get("parameters").As<Napi::Object>();
+        auto keys = jsParameters.GetPropertyNames();
+        for (uint32_t i = 0; i < keys.Length(); ++i) {
+            Napi::Value key = keys.Get(i);
+            Napi::Value value = jsParameters.Get(key);
+            std::string keyStr = key.As<Napi::String>();
+            if ((keyStr == "uriList" || keyStr == "ability.params.stream") && value.IsArray()) {
+                Napi::Array uriLists = value.As<Napi::Array>();
+                for (uint32_t j = 0; j < uriLists.Length(); ++j) {
+                    Napi::Value uri = uriLists.Get(j);
+                    if (uri.IsString()) {
+                        auto u = QByteArray::fromStdString(uri.ToString());
+                        if (u.isEmpty())
+                            continue;
+                        auto path = pathFromUri(u);
+                        if (result.contains(path))
+                            continue;
+                        result << path;
+                    }
+                }
+                break;
+            }
+        }
+    }
+    return result;
+}
+
+QString QJsWant::moduleName() const
+{
+    return QString::fromStdString(get("moduleName").ToString());
+}
+
+QByteArray QJsWant::uri() const
+{
+    QByteArray uri = QByteArray::fromStdString(get("uri").ToString());
+    return uri;
+}
+
+QString QJsWant::windowName() const
+{
+    if (!object().Has("parameters"))
+        return defaultWindowName;
+    Napi::Object jsParameters = get("parameters").As<Napi::Object>();
+    Napi::Value ret = jsParameters.Get("windowName");
+    if (ret.IsUndefined() || ret.IsEmpty())
+        return defaultWindowName;
+
+    return QString::fromStdString(ret.ToString());
+}
+
+bool QJsWant::hasWindowName() const
+{
+    if (!object().Has("parameters"))
+        return false;
+    Napi::Object jsParameters = get("parameters").As<Napi::Object>();
+    return jsParameters.Has("windowName");
+}
+
+bool QJsWant::hasProcessIdentifier() const
+{
+    if (!object().Has("parameters"))
+        return false;
+    Napi::Object jsParameters = get("parameters").As<Napi::Object>();
+    return jsParameters.Has("processIdentifier");
+}
+
+QString QJsWant::processIdentifier() const
+{
+    if (!object().Has("parameters"))
+        return QString();
+    Napi::Object jsParameters = get("parameters").As<Napi::Object>();
+    Napi::Value ret = jsParameters.Get("processIdentifier");
+    if (ret.IsUndefined() || ret.IsEmpty())
+        return QString();
+
+    return QString::fromStdString(ret.ToString());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjswant.h b/src/plugins/platforms/openharmony/jsclass/qjswant.h
new file mode 100644
index 00000000000..fa0e8166a98
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjswant.h
@@ -0,0 +1,40 @@
+#ifndef QJSWANT_H
+#define QJSWANT_H
+
+#include <qjsobject.h>
+
+#include <QString>
+#include <QList>
+
+class QJsWant : public QJsObject
+{
+public:
+    QJsWant(Napi::Object jsObject);
+    ~QJsWant();
+
+    bool isSilentStart() const;
+
+    QString bundleName() const;
+
+    QString abilityName() const;
+
+    QString moduleName() const;
+
+    QString windowName() const;
+
+    bool hasWindowName() const;
+
+    bool hasProcessIdentifier() const;
+
+    QString processIdentifier() const;
+
+    QByteArray uri() const;
+
+    QList<QByteArray> launchParams() const;
+
+    void saveParamsToEnv();
+
+    static QString defaultWindowName;
+};
+
+#endif // QJSWANT_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjswindowproxy.cpp b/src/plugins/platforms/openharmony/jsclass/qjswindowproxy.cpp
new file mode 100644
index 00000000000..ac62d4575f2
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjswindowproxy.cpp
@@ -0,0 +1,16 @@
+#include "qjswindowproxy.h"
+
+QT_BEGIN_NAMESPACE
+
+QJsWindowProxy::QJsWindowProxy(Napi::Object windowproxy)
+    : QJsObject(windowproxy)
+{
+
+}
+
+QJsWindowProxy::~QJsWindowProxy()
+{
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjswindowproxy.h b/src/plugins/platforms/openharmony/jsclass/qjswindowproxy.h
new file mode 100644
index 00000000000..6671c0aacf2
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjswindowproxy.h
@@ -0,0 +1,18 @@
+#ifndef QJSWINDOWPROXY_H
+#define QJSWINDOWPROXY_H
+
+#include <QJsObject>
+
+QT_BEGIN_NAMESPACE
+
+class QJsWindowProxy : public QJsObject
+{
+public:
+    QJsWindowProxy(Napi::Object windowproxy);
+    ~QJsWindowProxy();
+
+    virtual Napi::Object mainwindow() = 0;
+};
+
+QT_END_NAMESPACE
+#endif // QJSWINDOWPROXY_H
diff --git a/src/plugins/platforms/openharmony/jsclass/qjswindowstage.cpp b/src/plugins/platforms/openharmony/jsclass/qjswindowstage.cpp
new file mode 100644
index 00000000000..9cd2b221a01
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjswindowstage.cpp
@@ -0,0 +1,49 @@
+#include "qjswindowstage.h"
+#include "qohmain.h"
+#include "qohauxiliary.h"
+#include <private/qopenharmony_p.h>
+#include <private/qjspromise_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QJsWindowStage::QJsWindowStage(Napi::Object jsObject)
+    : QJsWindowProxy(jsObject)
+{
+
+}
+
+QJsWindowStage::~QJsWindowStage()
+{
+
+}
+
+Napi::Object QJsWindowStage::mainwindow()
+{
+    Napi::Value result = call("getMainWindowSync");
+    return result.As<Napi::Object>();
+}
+
+bool QJsWindowStage::isWindowRectAutoSave()
+{
+    if (!QtOh::checkDeviceType(QtOh::Utility::PC)) {
+        qCWarning(openharmonyQPA, "isWindowRectAutoSave This interface is not support on this device");
+        return false;
+    }
+
+    return QtOh::runOnJsUIThreadWithPromise<bool>([this](auto p) {
+        Napi::Value ret = call("isWindowRectAutoSave");
+        if (ret.IsEmpty() || ret.IsNull()) {
+            p->set_value(false);
+            return;
+        }
+
+        QJsPromise promise(ret.As<Napi::Promise>());
+        promise.onThen([this, p](const Napi::CallbackInfo &info) {
+            bool isAutoSave = info[0].ToBoolean();
+            p->set_value(isAutoSave);
+        }).onCatch([this, p](const Napi::CallbackInfo &) {
+            p->set_value(false);
+        });
+    });
+}
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/jsclass/qjswindowstage.h b/src/plugins/platforms/openharmony/jsclass/qjswindowstage.h
new file mode 100644
index 00000000000..194ebbf97c2
--- /dev/null
+++ b/src/plugins/platforms/openharmony/jsclass/qjswindowstage.h
@@ -0,0 +1,20 @@
+#ifndef QJSWINDOWSTAGE_H
+#define QJSWINDOWSTAGE_H
+
+#include "qjswindowproxy.h"
+
+QT_BEGIN_NAMESPACE
+
+class QJsWindowStage : public QJsWindowProxy
+{
+public:
+    QJsWindowStage(Napi::Object jsObject);
+    ~QJsWindowStage();
+
+    Napi::Object mainwindow() override;
+
+    bool isWindowRectAutoSave();
+};
+
+QT_END_NAMESPACE
+#endif // QJSWINDOWSTAGE_H
diff --git a/src/plugins/platforms/openharmony/openharmony.json b/src/plugins/platforms/openharmony/openharmony.json
new file mode 100644
index 00000000000..886625295cd
--- /dev/null
+++ b/src/plugins/platforms/openharmony/openharmony.json
@@ -0,0 +1,3 @@
+{
+    "Keys": [ "openharmony" ]
+}
diff --git a/src/plugins/platforms/openharmony/openharmony.pro b/src/plugins/platforms/openharmony/openharmony.pro
new file mode 100644
index 00000000000..1b79604504f
--- /dev/null
+++ b/src/plugins/platforms/openharmony/openharmony.pro
@@ -0,0 +1,136 @@
+TARGET = qopenharmony
+
+CONFIG += c++latest
+
+greaterThan(OHOS_SDK_VERSION, 14) {
+    LIBS += -lnative_window_manager
+}
+
+QT += \
+    core-private gui-private egl_support-private \
+    eventdispatcher_support-private fontdatabase_support-private accessibility_support-private \
+    theme_support-private
+
+LIBS += -lEGL -lace_napi.z -lohfileuri -lace_ndk.z -lrawfile.z -lnative_window \
+    -ludmf -lpixelmap -lpasteboard -lohinput -lnative_display_manager -lqos -lhitrace_ndk.z \
+    -lnative_drawing -lnative_window_manager -lohinputmethod -lnative_vsync -limage_source -lohresmgr
+
+
+qtConfig(vulkan){
+    QT += vulkan_support-private
+
+    HEADERS += $$PWD/qohplatformvulkaninstance.h
+
+    SOURCES += $$PWD/qohplatformvulkaninstance.cpp
+}
+
+OTHER_FILES += $$PWD/openharmony.json
+
+HEADERS += $$PWD/qohplatformintegration.h \
+    $$PWD/qohplatformwindow.h \
+    $$PWD/qohdesktopwindow.h \
+    $$PWD/qohplatformopenglwindow.h \
+    $$PWD/qohplatformforeignwindow.h \
+    $$PWD/qohplatformscreen.h \
+    $$PWD/qohplatformbackingstore.h \
+    $$PWD/qohxcomponent.h \
+    $$PWD/qohnativewindowmanager.h \
+    $$PWD/qohplatformopenglcontext.h \
+    $$PWD/qoheventdispatcher.h \
+    $$PWD/qohplatformoffscreensurface.h \
+    $$PWD/qohmain.h \
+    $$PWD/qohplatforminputcontext.h \
+    $$PWD/qohplatformtheme.h \
+    $$PWD/qohplatformdialoghelpers.h \
+    $$PWD/qohplatformclipboard.h \
+    $$PWD/qohdrag.h \
+    $$PWD/qohfileenginehandler.h \
+    $$PWD/qohnativewindow.h \
+    $$PWD/qohjsonlistener.h \
+    $$PWD/qohwindownode.h  \
+    $$PWD/qohwindownodeeventhandler.h \
+    $$PWD/qohplatformservices.h \
+    $$PWD/qohplatformcursor.h \
+    $$PWD/qohplatformabilityctrl.h \
+    $$PWD/qohplatformnativeinterface.h \
+    $$PWD/qohevent.h \
+    $$PWD/qohextensionwindow.h \
+    $$PWD/qohnormalwindow.h \
+    $$PWD/qohauxiliary.h \
+    $$PWD/qohsystemtrayicon.h \
+    $$PWD/qohplatformmenu.h \
+    $$PWD/qohobjectholder.h \
+    $$PWD/qohnativenodeapi.h \
+    $$PWD/qoharkui.h \
+    $$PWD/qohwindowcontext.h \
+    $$PWD/qohkeys.h
+
+SOURCES += $$PWD/qohplatformplugin.cpp \
+    $$PWD/qohplatformwindow.cpp \
+    $$PWD/qohdesktopwindow.cpp \
+    $$PWD/qohplatformintegration.cpp \
+    $$PWD/qohplatformopenglwindow.cpp \
+    $$PWD/qohplatformforeignwindow.cpp \
+    $$PWD/qohplatformscreen.cpp \
+    $$PWD/qohplatformbackingstore.cpp \
+    $$PWD/qohplatformopenglcontext.cpp \
+    $$PWD/qohplatformoffscreensurface.cpp \
+    $$PWD/qohmain.cpp \
+    $$PWD/qohxcomponent.cpp \
+    $$PWD/qohnativewindowmanager.cpp \
+    $$PWD/qoheventdispatcher.cpp \
+    $$PWD/qohplatforminputcontext.cpp \
+    $$PWD/qohplatformtheme.cpp \
+    $$PWD/qohplatformdialoghelpers.cpp \
+    $$PWD/qohplatformclipboard.cpp \
+    $$PWD/qohdrag.cpp \
+    $$PWD/qohfileenginehandler.cpp \
+    $$PWD/qohnativewindow.cpp  \
+    $$PWD/qohjsonlistener.cpp \
+    $$PWD/qohwindownode.cpp  \
+    $$PWD/qohwindownodeeventhandler.cpp \
+    $$PWD/qohplatformservices.cpp \
+    $$PWD/qohplatformcursor.cpp \
+    $$PWD/qohplatformabilityctrl.cpp \
+    $$PWD/qohplatformnativeinterface.cpp \
+    $$PWD/qohextensionwindow.cpp \
+    $$PWD/qohnormalwindow.cpp \
+    $$PWD/qohauxiliary.cpp \
+    $$PWD/qohsystemtrayicon.cpp \
+    $$PWD/qohplatformmenu.cpp \
+    $$PWD/qohnativenodeapi.cpp \
+    $$PWD/qoharkui.cpp \
+    $$PWD/qohwindowcontext.cpp \
+    $$PWD/qohkeys.cpp
+
+greaterThan(OHOS_SDK_VERSION, 13) {
+    include(accessibility/accessibility.pri)
+    HEADERS += \
+        $$PWD/qohdisplay.h \
+        $$PWD/qohdisplaymanager.h \
+        $$PWD/qohdisplaylistener.h
+
+    SOURCES += \
+        $$PWD/qohdisplay.cpp \
+        $$PWD/qohdisplaymanager.cpp \
+        $$PWD/qohdisplaylistener.cpp
+}
+
+greaterThan(OHOS_SDK_VERSION, 14) {
+    HEADERS += \
+        $$PWD/qohnativevsync.h
+
+    SOURCES +=  \
+        $$PWD/qohnativevsync.cpp
+}
+
+include(jsclass/jsclass.pri)
+include(inputmethod/inputmethod.pri)
+include(arkui/arkui.pri)
+PLUGIN_TYPE = platforms
+
+PLUGIN_CLASS_NAME = QOpenHarmonyPlatformIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
+
+load(qt_plugin)
+
diff --git a/src/plugins/platforms/openharmony/qoharkui.cpp b/src/plugins/platforms/openharmony/qoharkui.cpp
new file mode 100644
index 00000000000..9433403b43b
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qoharkui.cpp
@@ -0,0 +1,470 @@
+#include "qoharkui.h"
+#include <QtCore/QHash>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtOhArkUI {
+
+static QHash<int32_t, QString> errors = {
+    {ARKUI_ERROR_CODE_NO_ERROR,             "No errors"},
+    {ARKUI_ERROR_CODE_PARAM_INVALID,      "Parameter error"},
+#if OHOS_SDK_VERSION > 14
+    {ARKUI_ERROR_CODE_INTERNAL_ERROR,     "Internal error occurs"},
+#endif
+    {ARKUI_ERROR_CODE_ATTRIBUTE_OR_EVENT_NOT_SUPPORTED, "The component does not support specific properties or events"},
+    {ARKUI_ERROR_CODE_ARKTS_NODE_NOT_SUPPORTED,       "The corresponding operation does not support nodes created by ArkTS"},
+    {ARKUI_ERROR_CODE_ADAPTER_NOT_BOUND,       "The lazy loading adapter is not bound to the component"},
+    {ARKUI_ERROR_CODE_ADAPTER_EXIST, "The adapter already exists"},
+    {ARKUI_ERROR_CODE_CHILD_NODE_EXIST,     "The corresponding node already has a child node and cannot add an adapter"},
+    {ARKUI_ERROR_CODE_NODE_EVENT_PARAM_INDEX_OUT_OF_RANGE,       "The parameter length in the parameter event exceeds the limit"},
+    {ARKUI_ERROR_CODE_NODE_EVENT_PARAM_INVALID,           "The data does not exist in the component event"},
+    {ARKUI_ERROR_CODE_NODE_EVENT_NO_RETURN,       "The component event does not support return values"},
+    {ARKUI_ERROR_CODE_NODE_INDEX_INVALID,   "The index value is invalid"},
+    {ARKUI_ERROR_CODE_GET_INFO_FAILED,   "Failed to query route navigation information"},
+    {ARKUI_ERROR_CODE_BUFFER_SIZE_ERROR,   "The buffer size is not large enough"},
+#if OHOS_SDK_VERSIOIN > 14
+    {ARKUI_ERROR_CODE_NODE_NOT_ON_MAIN_TREE,   "The node is not on main tree"},
+    {ARKUI_ERROR_CODE_FOCUS_NON_FOCUSABLE,   "The node requesting focus is not focusable"},
+    {ARKUI_ERROR_CODE_FOCUS_NON_FOCUSABLE_ANCESTOR,   "The node requesting focus has unfocusable ancestor"},
+    {ARKUI_ERROR_CODE_FOCUS_NON_EXISTENT,   "The node requesting focus does not exists"},
+    {ARKUI_ERROR_CODE_COMPONENT_SNAPSHOT_TIMEOUT,   "The snapshot taking is timeout"},
+#endif
+    {ARKUI_ERROR_CODE_NON_SCROLLABLE_CONTAINER,   "The component is not a scroll container"},
+    {ARKUI_ERROR_CODE_BUFFER_SIZE_NOT_ENOUGH,   "The buffer is not large enough"},
+#if OHOS_SDK_VERSIOIN > 14
+    {ARKUI_ERROR_CODE_NOT_CLONED_POINTER_EVENT,   "The event is not a clone event"},
+    {ARKUI_ERROR_CODE_POST_CLONED_COMPONENT_STATUS_ABNORMAL,   "The component status is abnormal"},
+    {ARKUI_ERROR_CODE_POST_CLONED_NO_COMPONENT_HIT_TO_RESPOND_TO_THE_EVENT,   "No component hit to respond to the event"},
+#endif
+    {ARKUI_ERROR_CODE_INVALID_STYLED_STRING,   "invalid styled string"}
+};
+
+QString ErrorCode::toString(int32_t code)
+{
+    return errors.value(code, "Unknow error");
+}
+
+void ErrorCode::printErrorCode(const QString &message, int32_t code)
+{
+    qWarning() << QString("%1---code is: %2, error string is: %3").arg(message).arg(code).arg(toString(code));
+}
+
+#define MAP_ENUM(ENUM) ENUM, #ENUM
+
+constexpr std::array NodeAttributeTypeMap = {
+    std::pair{MAP_ENUM(NODE_WIDTH)},
+    std::pair{MAP_ENUM(NODE_HEIGHT)},
+    std::pair{MAP_ENUM(NODE_BACKGROUND_COLOR)},
+    std::pair{MAP_ENUM(NODE_BACKGROUND_IMAGE)},
+    std::pair{MAP_ENUM(NODE_PADDING)},
+    std::pair{MAP_ENUM(NODE_ID)},
+    std::pair{MAP_ENUM(NODE_ENABLED)},
+    std::pair{MAP_ENUM(NODE_MARGIN)},
+    std::pair{MAP_ENUM(NODE_TRANSLATE)},
+    std::pair{MAP_ENUM(NODE_SCALE)},
+    std::pair{MAP_ENUM(NODE_ROTATE)},
+    std::pair{MAP_ENUM(NODE_BRIGHTNESS)},
+    std::pair{MAP_ENUM(NODE_SATURATION)},
+    std::pair{MAP_ENUM(NODE_BLUR)},
+    std::pair{MAP_ENUM(NODE_LINEAR_GRADIENT)},
+    std::pair{MAP_ENUM(NODE_ALIGNMENT)},
+    std::pair{MAP_ENUM(NODE_OPACITY)},
+    std::pair{MAP_ENUM(NODE_BORDER_WIDTH)},
+    std::pair{MAP_ENUM(NODE_BORDER_RADIUS)},
+    std::pair{MAP_ENUM(NODE_BORDER_COLOR)},
+    std::pair{MAP_ENUM(NODE_BORDER_STYLE)},
+    std::pair{MAP_ENUM(NODE_Z_INDEX)},
+    std::pair{MAP_ENUM(NODE_VISIBILITY)},
+    std::pair{MAP_ENUM(NODE_CLIP)},
+    std::pair{MAP_ENUM(NODE_CLIP_SHAPE)},
+    std::pair{MAP_ENUM(NODE_TRANSFORM)},
+    std::pair{MAP_ENUM(NODE_HIT_TEST_BEHAVIOR)},
+    std::pair{MAP_ENUM(NODE_POSITION)},
+    std::pair{MAP_ENUM(NODE_SHADOW)},
+    std::pair{MAP_ENUM(NODE_CUSTOM_SHADOW)},
+    std::pair{MAP_ENUM(NODE_BACKGROUND_IMAGE_SIZE)},
+    std::pair{MAP_ENUM(NODE_BACKGROUND_IMAGE_SIZE_WITH_STYLE)},
+    std::pair{MAP_ENUM(NODE_BACKGROUND_BLUR_STYLE)},
+    std::pair{MAP_ENUM(NODE_TRANSFORM_CENTER)},
+    std::pair{MAP_ENUM(NODE_OPACITY_TRANSITION)},
+    std::pair{MAP_ENUM(NODE_ROTATE_TRANSITION)},
+    std::pair{MAP_ENUM(NODE_SCALE_TRANSITION)},
+    std::pair{MAP_ENUM(NODE_TRANSLATE_TRANSITION)},
+    std::pair{MAP_ENUM(NODE_MOVE_TRANSITION)},
+    std::pair{MAP_ENUM(NODE_FOCUSABLE)},
+    std::pair{MAP_ENUM(NODE_DEFAULT_FOCUS)},
+    std::pair{MAP_ENUM(NODE_RESPONSE_REGION)},
+    std::pair{MAP_ENUM(NODE_OVERLAY)},
+    std::pair{MAP_ENUM(NODE_SWEEP_GRADIENT)},
+    std::pair{MAP_ENUM(NODE_RADIAL_GRADIENT)},
+    std::pair{MAP_ENUM(NODE_MASK)},
+    std::pair{MAP_ENUM(NODE_BLEND_MODE)},
+    std::pair{MAP_ENUM(NODE_DIRECTION)},
+    std::pair{MAP_ENUM(NODE_CONSTRAINT_SIZE)},
+    std::pair{MAP_ENUM(NODE_GRAY_SCALE)},
+    std::pair{MAP_ENUM(NODE_INVERT)},
+    std::pair{MAP_ENUM(NODE_SEPIA)},
+    std::pair{MAP_ENUM(NODE_CONTRAST)},
+    std::pair{MAP_ENUM(NODE_FOREGROUND_COLOR)},
+    std::pair{MAP_ENUM(NODE_OFFSET)},
+    std::pair{MAP_ENUM(NODE_MARK_ANCHOR)},
+    std::pair{MAP_ENUM(NODE_BACKGROUND_IMAGE_POSITION)},
+    std::pair{MAP_ENUM(NODE_ALIGN_RULES)},
+    std::pair{MAP_ENUM(NODE_ALIGN_SELF)},
+    std::pair{MAP_ENUM(NODE_FLEX_GROW)},
+    std::pair{MAP_ENUM(NODE_FLEX_SHRINK)},
+    std::pair{MAP_ENUM(NODE_FLEX_BASIS)},
+    std::pair{MAP_ENUM(NODE_ACCESSIBILITY_GROUP)},
+    std::pair{MAP_ENUM(NODE_ACCESSIBILITY_TEXT)},
+    std::pair{MAP_ENUM(NODE_ACCESSIBILITY_MODE)},
+    std::pair{MAP_ENUM(NODE_ACCESSIBILITY_DESCRIPTION)},
+    std::pair{MAP_ENUM(NODE_FOCUS_STATUS)},
+    std::pair{MAP_ENUM(NODE_ASPECT_RATIO)},
+    std::pair{MAP_ENUM(NODE_LAYOUT_WEIGHT)},
+    std::pair{MAP_ENUM(NODE_DISPLAY_PRIORITY)},
+    std::pair{MAP_ENUM(NODE_OUTLINE_WIDTH)},
+    std::pair{MAP_ENUM(NODE_WIDTH_PERCENT)},
+    std::pair{MAP_ENUM(NODE_HEIGHT_PERCENT)},
+    std::pair{MAP_ENUM(NODE_PADDING_PERCENT)},
+    std::pair{MAP_ENUM(NODE_MARGIN_PERCENT)},
+    std::pair{MAP_ENUM(NODE_GEOMETRY_TRANSITION)},
+    std::pair{MAP_ENUM(NODE_RELATIVE_LAYOUT_CHAIN_MODE)},
+    std::pair{MAP_ENUM(NODE_RENDER_FIT)},
+    std::pair{MAP_ENUM(NODE_OUTLINE_COLOR)},
+    std::pair{MAP_ENUM(NODE_SIZE)},
+    std::pair{MAP_ENUM(NODE_RENDER_GROUP)},
+    std::pair{MAP_ENUM(NODE_COLOR_BLEND)},
+    std::pair{MAP_ENUM(NODE_FOREGROUND_BLUR_STYLE)},
+    std::pair{MAP_ENUM(NODE_LAYOUT_RECT)},
+    std::pair{MAP_ENUM(NODE_FOCUS_ON_TOUCH)},
+    std::pair{MAP_ENUM(NODE_BORDER_WIDTH_PERCENT)},
+    std::pair{MAP_ENUM(NODE_BORDER_RADIUS_PERCENT)},
+    std::pair{MAP_ENUM(NODE_ACCESSIBILITY_ID)},
+    std::pair{MAP_ENUM(NODE_ACCESSIBILITY_ACTIONS)},
+    std::pair{MAP_ENUM(NODE_ACCESSIBILITY_ROLE)},
+    std::pair{MAP_ENUM(NODE_ACCESSIBILITY_STATE)},
+    std::pair{MAP_ENUM(NODE_ACCESSIBILITY_VALUE)},
+    std::pair{MAP_ENUM(NODE_EXPAND_SAFE_AREA)},
+    std::pair{MAP_ENUM(NODE_VISIBLE_AREA_CHANGE_RATIO)},
+    std::pair{MAP_ENUM(NODE_TRANSITION)},
+    std::pair{MAP_ENUM(NODE_UNIQUE_ID)},
+    std::pair{MAP_ENUM(NODE_FOCUS_BOX)},
+    std::pair{MAP_ENUM(NODE_CLICK_DISTANCE)},
+    std::pair{MAP_ENUM(NODE_TAB_STOP)},
+#if OHOS_SDK_VERSION > 14
+    std::pair{MAP_ENUM(NODE_BACKDROP_BLUR)},
+#endif
+    std::pair{MAP_ENUM(NODE_TEXT_CONTENT)},
+    std::pair{MAP_ENUM(NODE_FONT_COLOR)},
+    std::pair{MAP_ENUM(NODE_FONT_SIZE)},
+    std::pair{MAP_ENUM(NODE_FONT_STYLE)},
+    std::pair{MAP_ENUM(NODE_FONT_WEIGHT)},
+    std::pair{MAP_ENUM(NODE_TEXT_LINE_HEIGHT)},
+    std::pair{MAP_ENUM(NODE_TEXT_DECORATION)},
+    std::pair{MAP_ENUM(NODE_TEXT_CASE)},
+    std::pair{MAP_ENUM(NODE_TEXT_LETTER_SPACING)},
+    std::pair{MAP_ENUM(NODE_TEXT_MAX_LINES)},
+    std::pair{MAP_ENUM(NODE_TEXT_ALIGN)},
+    std::pair{MAP_ENUM(NODE_TEXT_OVERFLOW)},
+    std::pair{MAP_ENUM(NODE_FONT_FAMILY)},
+    std::pair{MAP_ENUM(NODE_TEXT_COPY_OPTION)},
+    std::pair{MAP_ENUM(NODE_TEXT_BASELINE_OFFSET)},
+    std::pair{MAP_ENUM(NODE_TEXT_TEXT_SHADOW)},
+    std::pair{MAP_ENUM(NODE_TEXT_MIN_FONT_SIZE)},
+    std::pair{MAP_ENUM(NODE_TEXT_MAX_FONT_SIZE)},
+    std::pair{MAP_ENUM(NODE_TEXT_FONT)},
+    std::pair{MAP_ENUM(NODE_TEXT_HEIGHT_ADAPTIVE_POLICY)},
+    std::pair{MAP_ENUM(NODE_TEXT_INDENT)},
+    std::pair{MAP_ENUM(NODE_TEXT_WORD_BREAK)},
+    std::pair{MAP_ENUM(NODE_TEXT_ELLIPSIS_MODE)},
+    std::pair{MAP_ENUM(NODE_TEXT_LINE_SPACING)},
+    std::pair{MAP_ENUM(NODE_FONT_FEATURE)},
+    std::pair{MAP_ENUM(NODE_TEXT_ENABLE_DATA_DETECTOR)},
+    std::pair{MAP_ENUM(NODE_TEXT_ENABLE_DATA_DETECTOR_CONFIG)},
+    std::pair{MAP_ENUM(NODE_TEXT_SELECTED_BACKGROUND_COLOR)},
+    std::pair{MAP_ENUM(NODE_TEXT_CONTENT_WITH_STYLED_STRING)},
+    std::pair{MAP_ENUM(NODE_TEXT_HALF_LEADING)},
+#if OHOS_SDK_VERSION > 14
+    std::pair{MAP_ENUM(NODE_IMMUTABLE_FONT_WEIGHT)},
+#endif
+    std::pair{MAP_ENUM(NODE_SPAN_CONTENT)},
+    std::pair{MAP_ENUM(NODE_SPAN_TEXT_BACKGROUND_STYLE)},
+    std::pair{MAP_ENUM(NODE_SPAN_BASELINE_OFFSET)},
+    std::pair{MAP_ENUM(NODE_IMAGE_SPAN_SRC)},
+    std::pair{MAP_ENUM(NODE_IMAGE_SPAN_VERTICAL_ALIGNMENT)},
+    std::pair{MAP_ENUM(NODE_IMAGE_SPAN_ALT)},
+    std::pair{MAP_ENUM(NODE_IMAGE_SPAN_BASELINE_OFFSET)},
+    std::pair{MAP_ENUM(NODE_IMAGE_SRC)},
+    std::pair{MAP_ENUM(NODE_IMAGE_OBJECT_FIT)},
+    std::pair{MAP_ENUM(NODE_IMAGE_INTERPOLATION)},
+    std::pair{MAP_ENUM(NODE_IMAGE_OBJECT_REPEAT)},
+    std::pair{MAP_ENUM(NODE_IMAGE_COLOR_FILTER)},
+    std::pair{MAP_ENUM(NODE_IMAGE_AUTO_RESIZE)},
+    std::pair{MAP_ENUM(NODE_IMAGE_ALT)},
+    std::pair{MAP_ENUM(NODE_IMAGE_DRAGGABLE)},
+    std::pair{MAP_ENUM(NODE_IMAGE_RENDER_MODE)},
+    std::pair{MAP_ENUM(NODE_IMAGE_FIT_ORIGINAL_SIZE)},
+    std::pair{MAP_ENUM(NODE_IMAGE_FILL_COLOR)},
+    std::pair{MAP_ENUM(NODE_IMAGE_RESIZABLE)},
+    std::pair{MAP_ENUM(NODE_TOGGLE_SELECTED_COLOR)},
+    std::pair{MAP_ENUM(NODE_TOGGLE_SWITCH_POINT_COLOR)},
+    std::pair{MAP_ENUM(NODE_TOGGLE_VALUE)},
+    std::pair{MAP_ENUM(NODE_TOGGLE_UNSELECTED_COLOR)},
+    std::pair{MAP_ENUM(NODE_LOADING_PROGRESS_COLOR)},
+    std::pair{MAP_ENUM(NODE_LOADING_PROGRESS_ENABLE_LOADING)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_PLACEHOLDER)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_TEXT)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_CARET_COLOR)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_CARET_STYLE)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_SHOW_UNDERLINE)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_MAX_LENGTH)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_ENTER_KEY_TYPE)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_PLACEHOLDER_COLOR)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_PLACEHOLDER_FONT)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_ENABLE_KEYBOARD_ON_FOCUS)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_TYPE)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_SELECTED_BACKGROUND_COLOR)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_SHOW_PASSWORD_ICON)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_EDITING)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_CANCEL_BUTTON)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_TEXT_SELECTION)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_UNDERLINE_COLOR)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_ENABLE_AUTO_FILL)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_CONTENT_TYPE)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_PASSWORD_RULES)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_SELECT_ALL)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_INPUT_FILTER)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_STYLE)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_CARET_OFFSET)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_CONTENT_RECT)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_CONTENT_LINE_COUNT)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_SELECTION_MENU_HIDDEN)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_BLUR_ON_SUBMIT)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_CUSTOM_KEYBOARD)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_WORD_BREAK)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_SHOW_KEYBOARD_ON_FOCUS)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_NUMBER_OF_LINES)},
+#if OHOS_SDK_VERSION > 14
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_LETTER_SPACING)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_ENABLE_PREVIEW_TEXT)},
+    std::pair{MAP_ENUM(NODE_TEXT_INPUT_KEYBOARD_APPEARANCE)},
+#endif
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_PLACEHOLDER)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_TEXT)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_MAX_LENGTH)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_PLACEHOLDER_COLOR)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_PLACEHOLDER_FONT)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_CARET_COLOR)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_EDITING)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_TYPE)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_SHOW_COUNTER)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_SELECTION_MENU_HIDDEN)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_BLUR_ON_SUBMIT)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_INPUT_FILTER)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_SELECTED_BACKGROUND_COLOR)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_ENTER_KEY_TYPE)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_ENABLE_KEYBOARD_ON_FOCUS)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_CARET_OFFSET)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_CONTENT_RECT)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_CONTENT_LINE_COUNT)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_TEXT_SELECTION)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_ENABLE_AUTO_FILL)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_CONTENT_TYPE)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_SHOW_KEYBOARD_ON_FOCUS)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_NUMBER_OF_LINES)},
+#if OHOS_SDK_VERSION > 14
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_LETTER_SPACING)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_ENABLE_PREVIEW_TEXT)},
+    std::pair{MAP_ENUM(NODE_TEXT_AREA_KEYBOARD_APPEARANCE)},
+#endif
+    std::pair{MAP_ENUM(NODE_BUTTON_LABEL)},
+    std::pair{MAP_ENUM(NODE_BUTTON_TYPE)},
+    std::pair{MAP_ENUM(NODE_PROGRESS_VALUE)},
+    std::pair{MAP_ENUM(NODE_PROGRESS_TOTAL)},
+    std::pair{MAP_ENUM(NODE_PROGRESS_COLOR)},
+    std::pair{MAP_ENUM(NODE_PROGRESS_TYPE)},
+#if OHOS_SDK_VERSION > 14
+    std::pair{MAP_ENUM(NODE_PROGRESS_LINEAR_STYLE)},
+#endif
+    std::pair{MAP_ENUM(NODE_CHECKBOX_SELECT)},
+    std::pair{MAP_ENUM(NODE_CHECKBOX_SELECT_COLOR)},
+    std::pair{MAP_ENUM(NODE_CHECKBOX_UNSELECT_COLOR)},
+    std::pair{MAP_ENUM(NODE_CHECKBOX_MARK)},
+    std::pair{MAP_ENUM(NODE_CHECKBOX_SHAPE)},
+#if OHOS_SDK_VERSION > 14
+    std::pair{MAP_ENUM(NODE_CHECKBOX_NAME)},
+    std::pair{MAP_ENUM(NODE_CHECKBOX_GROUP)},
+#endif
+    std::pair{MAP_ENUM(NODE_XCOMPONENT_ID)},
+    std::pair{MAP_ENUM(NODE_XCOMPONENT_TYPE)},
+    std::pair{MAP_ENUM(NODE_XCOMPONENT_SURFACE_SIZE)},
+    std::pair{MAP_ENUM(NODE_DATE_PICKER_LUNAR)},
+    std::pair{MAP_ENUM(NODE_DATE_PICKER_START)},
+    std::pair{MAP_ENUM(NODE_DATE_PICKER_END)},
+    std::pair{MAP_ENUM(NODE_DATE_PICKER_SELECTED)},
+    std::pair{MAP_ENUM(NODE_DATE_PICKER_DISAPPEAR_TEXT_STYLE)},
+    std::pair{MAP_ENUM(NODE_DATE_PICKER_TEXT_STYLE)},
+    std::pair{MAP_ENUM(NODE_DATE_PICKER_SELECTED_TEXT_STYLE)},
+    std::pair{MAP_ENUM(NODE_TIME_PICKER_SELECTED)},
+    std::pair{MAP_ENUM(NODE_TIME_PICKER_USE_MILITARY_TIME)},
+    std::pair{MAP_ENUM(NODE_TIME_PICKER_DISAPPEAR_TEXT_STYLE)},
+    std::pair{MAP_ENUM(NODE_TIME_PICKER_TEXT_STYLE)},
+    std::pair{MAP_ENUM(NODE_TIME_PICKER_SELECTED_TEXT_STYLE)},
+    std::pair{MAP_ENUM(NODE_TEXT_PICKER_OPTION_RANGE)},
+    std::pair{MAP_ENUM(NODE_TEXT_PICKER_OPTION_SELECTED)},
+    std::pair{MAP_ENUM(NODE_TEXT_PICKER_OPTION_VALUE)},
+    std::pair{MAP_ENUM(NODE_TEXT_PICKER_DISAPPEAR_TEXT_STYLE)},
+    std::pair{MAP_ENUM(NODE_TEXT_PICKER_TEXT_STYLE)},
+    std::pair{MAP_ENUM(NODE_TEXT_PICKER_SELECTED_TEXT_STYLE)},
+    std::pair{MAP_ENUM(NODE_TEXT_PICKER_SELECTED_INDEX)},
+    std::pair{MAP_ENUM(NODE_TEXT_PICKER_CAN_LOOP)},
+    std::pair{MAP_ENUM(NODE_TEXT_PICKER_DEFAULT_PICKER_ITEM_HEIGHT)},
+    std::pair{MAP_ENUM(NODE_CALENDAR_PICKER_HINT_RADIUS)},
+    std::pair{MAP_ENUM(NODE_CALENDAR_PICKER_SELECTED_DATE)},
+    std::pair{MAP_ENUM(NODE_CALENDAR_PICKER_EDGE_ALIGNMENT)},
+    std::pair{MAP_ENUM(NODE_CALENDAR_PICKER_TEXT_STYLE)},
+    std::pair{MAP_ENUM(NODE_SLIDER_BLOCK_COLOR)},
+    std::pair{MAP_ENUM(NODE_SLIDER_TRACK_COLOR)},
+    std::pair{MAP_ENUM(NODE_SLIDER_SELECTED_COLOR)},
+    std::pair{MAP_ENUM(NODE_SLIDER_SHOW_STEPS)},
+    std::pair{MAP_ENUM(NODE_SLIDER_BLOCK_STYLE)},
+    std::pair{MAP_ENUM(NODE_SLIDER_VALUE)},
+    std::pair{MAP_ENUM(NODE_SLIDER_MIN_VALUE)},
+    std::pair{MAP_ENUM(NODE_SLIDER_MAX_VALUE)},
+    std::pair{MAP_ENUM(NODE_SLIDER_STEP)},
+    std::pair{MAP_ENUM(NODE_SLIDER_DIRECTION)},
+    std::pair{MAP_ENUM(NODE_SLIDER_REVERSE)},
+    std::pair{MAP_ENUM(NODE_SLIDER_STYLE)},
+    std::pair{MAP_ENUM(NODE_SLIDER_TRACK_THICKNESS)},
+    std::pair{MAP_ENUM(NODE_RADIO_CHECKED)},
+    std::pair{MAP_ENUM(NODE_RADIO_STYLE)},
+    std::pair{MAP_ENUM(NODE_RADIO_VALUE)},
+    std::pair{MAP_ENUM(NODE_RADIO_GROUP)},
+    std::pair{MAP_ENUM(NODE_IMAGE_ANIMATOR_IMAGES)},
+    std::pair{MAP_ENUM(NODE_IMAGE_ANIMATOR_STATE)},
+    std::pair{MAP_ENUM(NODE_IMAGE_ANIMATOR_DURATION)},
+    std::pair{MAP_ENUM(NODE_IMAGE_ANIMATOR_REVERSE)},
+    std::pair{MAP_ENUM(NODE_IMAGE_ANIMATOR_FIXED_SIZE)},
+    std::pair{MAP_ENUM(NODE_IMAGE_ANIMATOR_FILL_MODE)},
+    std::pair{MAP_ENUM(NODE_IMAGE_ANIMATOR_ITERATION)},
+#if OHOS_SDK_VERSION > 14
+    std::pair{MAP_ENUM(NODE_CHECKBOX_GROUP_NAME)},
+    std::pair{MAP_ENUM(NODE_CHECKBOX_GROUP_SELECT_ALL)},
+    std::pair{MAP_ENUM(NODE_CHECKBOX_GROUP_SELECTED_COLOR)},
+    std::pair{MAP_ENUM(NODE_CHECKBOX_GROUP_UNSELECTED_COLOR)},
+    std::pair{MAP_ENUM(NODE_CHECKBOX_GROUP_MARK)},
+    std::pair{MAP_ENUM(NODE_CHECKBOX_GROUP_SHAPE)},
+#endif
+    std::pair{MAP_ENUM(NODE_STACK_ALIGN_CONTENT)},
+    std::pair{MAP_ENUM(NODE_SCROLL_BAR_DISPLAY_MODE)},
+    std::pair{MAP_ENUM(NODE_SCROLL_BAR_WIDTH)},
+    std::pair{MAP_ENUM(NODE_SCROLL_BAR_COLOR)},
+    std::pair{MAP_ENUM(NODE_SCROLL_SCROLL_DIRECTION)},
+    std::pair{MAP_ENUM(NODE_SCROLL_EDGE_EFFECT)},
+    std::pair{MAP_ENUM(NODE_SCROLL_ENABLE_SCROLL_INTERACTION)},
+    std::pair{MAP_ENUM(NODE_SCROLL_FRICTION)},
+    std::pair{MAP_ENUM(NODE_SCROLL_SNAP)},
+    std::pair{MAP_ENUM(NODE_SCROLL_NESTED_SCROLL)},
+    std::pair{MAP_ENUM(NODE_SCROLL_OFFSET)},
+    std::pair{MAP_ENUM(NODE_SCROLL_EDGE)},
+    std::pair{MAP_ENUM(NODE_SCROLL_ENABLE_PAGING)},
+    std::pair{MAP_ENUM(NODE_SCROLL_PAGE)},
+    std::pair{MAP_ENUM(NODE_SCROLL_BY)},
+    std::pair{MAP_ENUM(NODE_SCROLL_FLING)},
+    std::pair{MAP_ENUM(NODE_SCROLL_FADING_EDGE)},
+    std::pair{MAP_ENUM(NODE_SCROLL_SIZE)},
+#if OHOS_SDK_VERSION > 14
+    std::pair{MAP_ENUM(NODE_SCROLL_CONTENT_START_OFFSET)},
+    std::pair{MAP_ENUM(NODE_SCROLL_CONTENT_END_OFFSET)},
+    std::pair{MAP_ENUM(NODE_SCROLL_BACK_TO_TOP)},
+#endif
+    std::pair{MAP_ENUM(NODE_LIST_DIRECTION)},
+    std::pair{MAP_ENUM(NODE_LIST_STICKY)},
+#if OHOS_SDK_VERSION > 14
+    std::pair{MAP_ENUM(NODE_LIST_SPACE)},
+#endif
+    std::pair{MAP_ENUM(NODE_LIST_NODE_ADAPTER)},
+    std::pair{MAP_ENUM(NODE_LIST_CACHED_COUNT)},
+    std::pair{MAP_ENUM(NODE_LIST_SCROLL_TO_INDEX)},
+    std::pair{MAP_ENUM(NODE_LIST_ALIGN_LIST_ITEM)},
+    std::pair{MAP_ENUM(NODE_LIST_CHILDREN_MAIN_SIZE)},
+    std::pair{MAP_ENUM(NODE_LIST_INITIAL_INDEX)},
+    std::pair{MAP_ENUM(NODE_LIST_DIVIDER)},
+#if OHOS_SDK_VERSION > 14
+    std::pair{MAP_ENUM(NODE_LIST_SCROLL_TO_INDEX_IN_GROUP)},
+    std::pair{MAP_ENUM(NODE_LIST_LANES)},
+    std::pair{MAP_ENUM(NODE_LIST_SCROLL_SNAP_ALIGN)},
+    std::pair{MAP_ENUM(NODE_LIST_MAINTAIN_VISIBLE_CONTENT_POSITION)},
+#endif
+    std::pair{MAP_ENUM(NODE_SWIPER_LOOP)},
+    std::pair{MAP_ENUM(NODE_SWIPER_AUTO_PLAY)},
+    std::pair{MAP_ENUM(NODE_SWIPER_SHOW_INDICATOR)},
+    std::pair{MAP_ENUM(NODE_SWIPER_INTERVAL)},
+    std::pair{MAP_ENUM(NODE_SWIPER_VERTICAL)},
+    std::pair{MAP_ENUM(NODE_SWIPER_DURATION)},
+    std::pair{MAP_ENUM(NODE_SWIPER_CURVE)},
+    std::pair{MAP_ENUM(NODE_SWIPER_ITEM_SPACE)},
+    std::pair{MAP_ENUM(NODE_SWIPER_INDEX)},
+    std::pair{MAP_ENUM(NODE_SWIPER_DISPLAY_COUNT)},
+    std::pair{MAP_ENUM(NODE_SWIPER_DISABLE_SWIPE)},
+    std::pair{MAP_ENUM(NODE_SWIPER_SHOW_DISPLAY_ARROW)},
+    std::pair{MAP_ENUM(NODE_SWIPER_EDGE_EFFECT_MODE)},
+    std::pair{MAP_ENUM(NODE_SWIPER_NODE_ADAPTER)},
+    std::pair{MAP_ENUM(NODE_SWIPER_CACHED_COUNT)},
+    std::pair{MAP_ENUM(NODE_SWIPER_PREV_MARGIN)},
+    std::pair{MAP_ENUM(NODE_SWIPER_NEXT_MARGIN)},
+    std::pair{MAP_ENUM(NODE_SWIPER_INDICATOR)},
+    std::pair{MAP_ENUM(NODE_SWIPER_NESTED_SCROLL)},
+    std::pair{MAP_ENUM(NODE_SWIPER_SWIPE_TO_INDEX)},
+    std::pair{MAP_ENUM(NODE_SWIPER_INDICATOR_INTERACTIVE)},
+#if OHOS_SDK_VERSION > 14
+    std::pair{MAP_ENUM(NODE_SWIPER_PAGE_FLIP_MODE)},
+#endif
+    std::pair{MAP_ENUM(NODE_LIST_ITEM_SWIPE_ACTION)},
+    std::pair{MAP_ENUM(NODE_LIST_ITEM_GROUP_SET_HEADER)},
+    std::pair{MAP_ENUM(NODE_LIST_ITEM_GROUP_SET_FOOTER)},
+    std::pair{MAP_ENUM(NODE_LIST_ITEM_GROUP_SET_DIVIDER)},
+    std::pair{MAP_ENUM(NODE_LIST_ITEM_GROUP_CHILDREN_MAIN_SIZE)},
+#if OHOS_SDK_VERSION > 14
+    std::pair{MAP_ENUM(NODE_LIST_ITEM_GROUP_NODE_ADAPTER)},
+#endif
+    std::pair{MAP_ENUM(NODE_COLUMN_ALIGN_ITEMS)},
+    std::pair{MAP_ENUM(NODE_COLUMN_JUSTIFY_CONTENT)},
+    std::pair{MAP_ENUM(NODE_ROW_ALIGN_ITEMS)},
+    std::pair{MAP_ENUM(NODE_ROW_JUSTIFY_CONTENT)},
+    std::pair{MAP_ENUM(NODE_FLEX_OPTION)},
+    std::pair{MAP_ENUM(NODE_REFRESH_REFRESHING)},
+    std::pair{MAP_ENUM(NODE_REFRESH_CONTENT)},
+    std::pair{MAP_ENUM(NODE_REFRESH_PULL_DOWN_RATIO)},
+    std::pair{MAP_ENUM(NODE_REFRESH_OFFSET)},
+    std::pair{MAP_ENUM(NODE_REFRESH_PULL_TO_REFRESH)},
+    std::pair{MAP_ENUM(NODE_WATER_FLOW_LAYOUT_DIRECTION)},
+    std::pair{MAP_ENUM(NODE_WATER_FLOW_COLUMN_TEMPLATE)},
+    std::pair{MAP_ENUM(NODE_WATER_FLOW_ROW_TEMPLATE)},
+    std::pair{MAP_ENUM(NODE_WATER_FLOW_COLUMN_GAP)},
+    std::pair{MAP_ENUM(NODE_WATER_FLOW_ROW_GAP)},
+    std::pair{MAP_ENUM(NODE_WATER_FLOW_SECTION_OPTION)},
+    std::pair{MAP_ENUM(NODE_WATER_FLOW_NODE_ADAPTER)},
+    std::pair{MAP_ENUM(NODE_WATER_FLOW_CACHED_COUNT)},
+    std::pair{MAP_ENUM(NODE_WATER_FLOW_FOOTER)},
+    std::pair{MAP_ENUM(NODE_WATER_FLOW_SCROLL_TO_INDEX)},
+    std::pair{MAP_ENUM(NODE_WATER_FLOW_ITEM_CONSTRAINT_SIZE)},
+    std::pair{MAP_ENUM(NODE_RELATIVE_CONTAINER_GUIDE_LINE)},
+    std::pair{MAP_ENUM(NODE_RELATIVE_CONTAINER_BARRIER)},
+    std::pair{MAP_ENUM(NODE_GRID_COLUMN_TEMPLATE)},
+    std::pair{MAP_ENUM(NODE_GRID_ROW_TEMPLATE)},
+    std::pair{MAP_ENUM(NODE_GRID_COLUMN_GAP)},
+    std::pair{MAP_ENUM(NODE_GRID_ROW_GAP)},
+    std::pair{MAP_ENUM(NODE_GRID_NODE_ADAPTER)},
+    std::pair{MAP_ENUM(NODE_GRID_CACHED_COUNT)}
+};
+
+std::string_view nodeAttributeTypeToString(ArkUI_NodeAttributeType type) {
+    auto it = std::find_if(NodeAttributeTypeMap.begin(), NodeAttributeTypeMap.end(),
+                           [type](const auto& pair) { return pair.first == type; });
+    return it != NodeAttributeTypeMap.end() ? it->second : "Unknown";
+}
+
+}
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qoharkui.h b/src/plugins/platforms/openharmony/qoharkui.h
new file mode 100644
index 00000000000..3edcc7248dd
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qoharkui.h
@@ -0,0 +1,31 @@
+#ifndef QOHARKUI_H
+#define QOHARKUI_H
+
+#include <QtCore/qglobal.h>
+#include <arkui/native_type.h>
+#include <arkui/native_node.h>
+#include <string>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtOhArkUI {
+
+namespace ErrorCode {
+
+QString toString(int32_t code);
+
+void printErrorCode(const QString &message, int32_t code);
+
+inline bool checkCode(int32_t code)
+{
+    return code == ARKUI_ERROR_CODE_NO_ERROR;
+}
+
+};
+
+std::string_view nodeAttributeTypeToString(ArkUI_NodeAttributeType type);
+
+};
+QT_END_NAMESPACE
+
+#endif // QOHARKUI_H
diff --git a/src/plugins/platforms/openharmony/qohauxiliary.cpp b/src/plugins/platforms/openharmony/qohauxiliary.cpp
new file mode 100644
index 00000000000..27d266bb816
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohauxiliary.cpp
@@ -0,0 +1,937 @@
+/*******************************************************************
+ *  Copyright(c) 2022-2025 Ltd.
+ *  All right reserved. See LGPL for detailed Information
+ *
+ *  文件名称: qohauxiliary.cpp
+ *  简要描述: 封装了鸿蒙接口调用的辅助函数集
+ *  创建日期: 2025/01/15
+ *  作者: WangHao
+ *  说明:
+ *
+ *  修改日期: 2025年3月12日
+ *  作者: WangHao
+ *  说明: 添加了Udmf数据读取相关处理
+ ******************************************************************/
+#include <QDebug>
+#include <QTimer>
+#include <QImage>
+#include <QMimeData>
+#include <QEventLoop>
+#include <QTextDocument>
+#include <QLoggingCategory>
+
+#include <set>
+#include <span>
+#include <vector>
+#include <typeinfo>
+#include <functional>
+#include <string_view>
+#include <database/udmf/uds.h>
+#include <database/udmf/udmf.h>
+#include <database/udmf/udmf_meta.h>
+#include <database/udmf/udmf_err_code.h>
+#include <filemanagement/file_uri/oh_file_uri.h>
+
+#include "qohauxiliary.h"
+#include "qohplatformscreen.h"
+#include "qohobjectholder.h"
+
+Q_LOGGING_CATEGORY(ohauxiliary, "qt.ohos.auxiliary")
+
+namespace
+{
+static inline QString ohosPixelMap() { return QStringLiteral("pixelMap"); }
+static inline QString textHtmlLiteral() { return QStringLiteral("text/html"); }
+static inline QString textPlainLiteral() { return QStringLiteral("text/plain"); }
+static inline QString textUriListLiteral() { return QStringLiteral("text/uri-list"); }
+static inline QString applicationXColorLiteral() { return QStringLiteral("application/x-color"); }
+static inline QString applicationXQtImageLiteral() { return QStringLiteral("application/x-qt-image"); }
+
+template<typename T, typename Deleter>
+std::unique_ptr<T, Deleter> newUniqueOrFail(T *ptr, Deleter &&deleter)
+{
+    if (ptr == nullptr) {
+        qFatal("%s: got null pointer with deleter of type '%s'",
+                Q_FUNC_INFO, typeid(deleter).name());
+    }
+
+    return std::unique_ptr<T, Deleter>(ptr, deleter);
+}
+
+static QImage::Format pixelMapFormatToQImage(int32_t format)
+{
+    switch (format) {
+    case PIXEL_FORMAT_RGBA_8888:
+        return QImage::Format_RGBA8888;
+    case PIXEL_FORMAT_RGB_888:
+        return QImage::Format_RGB888;
+    case PIXEL_FORMAT_ALPHA_8:
+        return QImage::Format_Alpha8;
+    default:
+        return QImage::Format_RGBA8888;
+    }
+}
+
+/*!
+ * \brief 根据像素格式计算缓冲区大小
+ * \param format 像素格式
+ * \param width 图片宽度
+ * \param height 图片高度
+ * \return 返回计算的结果
+ */
+static int bufferSizeHelper(int32_t format, uint32_t width, uint32_t height)
+{
+    switch (format) {
+    case PIXEL_FORMAT_RGBA_F16:
+    case PIXEL_FORMAT_RGBA_8888:
+    case PIXEL_FORMAT_RGBA_1010102:
+        break;
+    case PIXEL_FORMAT_NV21:
+    case PIXEL_FORMAT_NV12:
+        return (width * height+((width+1)/2) * ((height+1)/2) * 2);
+    default:
+        break;
+    }
+    return (width * height * 4);
+}
+
+/* FIXME 能否优化? */
+static QImage createQImageFromNativePixelMap(QSharedPointer<::OH_UdsPixelMap> pixelMap)
+{
+    if (pixelMap.isNull())
+        return QImage();
+
+    OH_Pixelmap_InitializationOptions *createOpts;
+    int code = OH_PixelmapInitializationOptions_Create(&createOpts);
+    QOhObjectHolder<OH_Pixelmap_InitializationOptions> optsHolder(createOpts, OH_PixelmapInitializationOptions_Release);
+    Q_UNUSED(optsHolder);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary) << Q_FUNC_INFO << "create pixelmap options failed, code:" << code;
+        return QImage();
+    }
+
+    OH_PixelmapInitializationOptions_SetWidth(createOpts, 6);
+    OH_PixelmapInitializationOptions_SetHeight(createOpts, 4);
+    OH_PixelmapInitializationOptions_SetPixelFormat(createOpts, PIXEL_FORMAT_RGBA_8888);
+    OH_PixelmapInitializationOptions_SetAlphaType(createOpts, PIXELMAP_ALPHA_TYPE_OPAQUE);
+
+    /* NOTE 随意设置的值, 因为OH_PixelmapNative 不能为空 */
+    OH_PixelmapNative *pixelNative;
+    code = OH_PixelmapNative_CreateEmptyPixelmap(createOpts, &pixelNative);
+    QOhObjectHolder<OH_PixelmapNative> pixelHolder(pixelNative, OH_PixelmapNative_Release);
+    Q_UNUSED(pixelHolder);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary) << Q_FUNC_INFO << "create pixelmap native implement failed, code: " << code;
+        return QImage();
+    }
+
+    OH_UdsPixelMap_GetPixelMap(pixelMap.get(), pixelNative);
+    if (Q_NULLPTR == pixelNative) {
+        qCWarning(ohauxiliary) << Q_FUNC_INFO << "pixel native ptr is null.";
+        return QImage();
+    }
+    return QtOh::UdmfHelper::createQImageFromPixelmapNative(pixelNative);
+
+}
+
+template <typename T>
+struct QOhUdsMeta {
+    inline static constexpr std::string_view udmfMetaId { "unknown" };
+};
+
+template <>
+inline constexpr std::string_view QOhUdsMeta<::OH_UdsHtml>::udmfMetaId { UDMF_META_HTML };
+
+template <>
+inline constexpr std::string_view QOhUdsMeta<::OH_UdsPlainText>::udmfMetaId { UDMF_META_PLAIN_TEXT };
+
+template <>
+inline constexpr std::string_view QOhUdsMeta<::OH_UdsFileUri>::udmfMetaId { UDMF_META_GENERAL_FILE_URI };
+
+template <>
+inline constexpr std::string_view QOhUdsMeta<::OH_UdsPixelMap>::udmfMetaId { UDMF_META_OPENHARMONY_PIXEL_MAP };
+
+template <typename T>
+class QOhUdsObject
+{
+    OH_UdmfRecord *const m_record { nullptr };
+    std::variant<std::string, QImage> m_var;
+public:
+    class Wrapper
+    {
+        OH_UdmfRecord *const m_record;
+    public:
+        explicit Wrapper(OH_UdmfRecord *const rd) : m_record(rd) { }
+
+        operator QByteArray() const {
+            if constexpr(std::is_same_v<T, ::OH_UdsHtml>) {
+                QSharedPointer<T> html(OH_UdsHtml_Create(), ::OH_UdsHtml_Destroy);
+
+                int code = OH_UdmfRecord_GetHtml(m_record, html.get());
+                if (::Udmf_ErrCode::UDMF_E_OK != code) {
+                    qCWarning(ohauxiliary) << Q_FUNC_INFO << "acquire html content failed, error code:" << code;
+                    return QByteArray();
+                }
+
+                const char* content = OH_UdsHtml_GetContent(html.get());
+                QString contentStr(content);
+                if(contentStr.isEmpty()) {
+                    qCWarning(ohauxiliary) << Q_FUNC_INFO << "get html content failed." << content;
+                    content = OH_UdsHtml_GetPlainContent(html.get());
+                    QString contentStr2(content);
+                    if (contentStr2.isEmpty()) {
+                        qCWarning(ohauxiliary) << Q_FUNC_INFO << "get html plain content failed." << content;
+                        return QByteArray();
+                    }
+                }
+                qCWarning(ohauxiliary) << "read html data, lenght:" << strlen(content);
+                return QByteArray(content);
+
+            } else if constexpr(std::is_same_v<T, ::OH_UdsPlainText>) {
+                QSharedPointer<T> plainText(OH_UdsPlainText_Create(), ::OH_UdsPlainText_Destroy);
+
+                int code = OH_UdmfRecord_GetPlainText(m_record, plainText.get());
+                if (::Udmf_ErrCode::UDMF_E_OK != code) {
+                    qCWarning(ohauxiliary) << Q_FUNC_INFO << "acquire plain text failed, error code:" << code;
+                    return QByteArray();
+                }
+
+                const char* content = OH_UdsPlainText_GetContent(plainText.get());
+                return QByteArray(content);
+            } else if constexpr(std::is_same_v<T, ::OH_UdsFileUri>) {
+                QSharedPointer<T> fileUri(OH_UdsFileUri_Create(), ::OH_UdsFileUri_Destroy);
+                int code = OH_UdmfRecord_GetFileUri(m_record, fileUri.get());
+                if (::Udmf_ErrCode::UDMF_E_OK != code) {
+                    qCWarning(ohauxiliary) << Q_FUNC_INFO << "get file uri failed, error code:" << code;
+                    return QByteArray();
+                }
+
+                QByteArray url;
+                const char *content = OH_UdsFileUri_GetFileUri(fileUri.get());
+                if (Q_NULLPTR != content) {
+                    char *data = nullptr;
+                    FileManagement_ErrCode errCode = OH_FileUri_GetPathFromUri(content, strlen(content), &data);
+                    if (ERR_OK == errCode && nullptr != data) {
+                        url = QByteArray(data);
+                        free(data);
+                    }
+                }
+                return url;
+            } else {
+                return QByteArray();
+            }
+
+            return QByteArray();
+        };
+
+        QSharedPointer<T> get() const {
+            if constexpr(std::is_same_v<T, ::OH_UdsPixelMap>) {
+                QSharedPointer<T> pixelMap(OH_UdsPixelMap_Create(), ::OH_UdsPixelMap_Destroy);
+
+                int code = OH_UdmfRecord_GetPixelMap(m_record, pixelMap.get());
+                if (::Udmf_ErrCode::UDMF_E_OK != code) {
+                    qCWarning(ohauxiliary) << Q_FUNC_INFO << "create pixel map failed, error code:" << code;
+                    return QSharedPointer<T>(nullptr);
+                }
+
+                return pixelMap;
+            } else {
+                return QSharedPointer<T>(nullptr);
+            }
+        }
+    };
+
+    explicit QOhUdsObject(const QImage &image) : m_var(image) {}
+    QOhUdsObject(std::string str) : m_var(str) {}
+    QOhUdsObject(::OH_UdmfRecord *const record) : m_record(record){}
+
+    Wrapper getContent() const {
+        return Wrapper(m_record);
+    }
+
+    T* data() {
+        if constexpr(std::is_same_v<T, ::OH_UdsHtml>) {
+            std::unique_ptr<::OH_UdsHtml, void(*)(OH_UdsHtml*)>
+                    htmlUds(newUniqueOrFail(::OH_UdsHtml_Create(), ::OH_UdsHtml_Destroy));
+
+            int code = ::OH_UdsHtml_SetContent(htmlUds.get(), std::get<std::string>(m_var).c_str());
+            if (Udmf_ErrCode::UDMF_E_OK != code) {
+                qCWarning(ohauxiliary) << Q_FUNC_INFO << "OH_UdsHtml_SetContent failed, error code:" << code;
+                return nullptr;
+            }
+            return htmlUds.release();
+        } else if constexpr(std::is_same_v<T, ::OH_UdsPlainText>) {
+            std::unique_ptr<::OH_UdsPlainText, void(*)(OH_UdsPlainText*)>
+                    textUds(newUniqueOrFail(::OH_UdsPlainText_Create(), ::OH_UdsPlainText_Destroy));
+
+            int code = OH_UdsPlainText_SetContent(textUds.get(), std::get<std::string>(m_var).c_str());
+            if (UDMF_E_OK != code) {
+                qCWarning(ohauxiliary) << Q_FUNC_INFO << "OH_UdsPlainText_SetContent failed, error code:" << code;
+                return nullptr;
+            }
+            return textUds.release();
+        } else if constexpr(std::is_same_v<T, ::OH_UdsFileUri>) {
+            std::unique_ptr<::OH_UdsFileUri, void(*)(::OH_UdsFileUri*)>
+                    fileUri(newUniqueOrFail(::OH_UdsFileUri_Create(), ::OH_UdsFileUri_Destroy));
+            int code = ::OH_UdsFileUri_SetFileType(fileUri.get(), UDMF_META_GENERAL_FILE);
+            if (Udmf_ErrCode::UDMF_E_OK != code) {
+                qCWarning(ohauxiliary, "%s set file type failed, code: %d", Q_FUNC_INFO, code);
+            }
+
+            code = ::OH_UdsFileUri_SetFileUri(fileUri.get(), std::get<std::string>(m_var).c_str());
+            if (Udmf_ErrCode::UDMF_E_OK != code) {
+                qCWarning(ohauxiliary, "%s set file uri failed, code: %d", Q_FUNC_INFO, code);
+                return nullptr;
+            }
+            return fileUri.release();
+        } else if constexpr(std::is_same_v<T, ::OH_UdsPixelMap>) {
+            std::unique_ptr<::OH_UdsPixelMap, void(*)(OH_UdsPixelMap*)>
+                    pixelMapUds(newUniqueOrFail(::OH_UdsPixelMap_Create(), ::OH_UdsPixelMap_Destroy));
+
+
+            int code = OH_UdsPixelMap_SetPixelMap(pixelMapUds.get(), QtOh::UdmfHelper::createNativePixelMapFromQImage(std::get<QImage>(m_var)));
+            if (::Udmf_ErrCode::UDMF_E_OK != code) {
+                qCWarning(ohauxiliary, "%s set pixelmap data failed, code: %d", Q_FUNC_INFO, code);
+                return nullptr;
+            }
+
+            return pixelMapUds.release();
+        } else {
+            return nullptr;
+        }
+
+    }
+};
+
+class QOhUdmfRecord
+{
+    friend class QOhUdmfData;
+    Q_DISABLE_COPY(QOhUdmfRecord)
+
+    std::unique_ptr<::OH_UdmfRecord, void(*)(::OH_UdmfRecord *)> m_primitive;
+
+public:
+    QOhUdmfRecord();
+    QOhUdmfRecord(QOhUdmfRecord &&) = default;
+    QOhUdmfRecord &operator=(QOhUdmfRecord &&) = default;
+
+    std::vector<std::string> getTypes();
+
+    template <typename T>
+    void addUdsObj(QOhUdsObject<T> udsObj) {
+        if constexpr(std::is_same_v<T, ::OH_UdsHtml>) {
+            T *uds = udsObj.data();
+            if (nullptr != uds) {
+                int code = OH_UdmfRecord_AddHtml(m_primitive.get(), uds);
+                if (Udmf_ErrCode::UDMF_E_OK != code) {
+                    qCWarning(ohauxiliary) << Q_FUNC_INFO << "OH_UdmfRecord_AddHtml failed, error code:" << code;
+                }
+            }
+        } else if constexpr(std::is_same_v<T, ::OH_UdsPlainText>) {
+            T *uds = udsObj.data();
+            if (nullptr != uds) {
+                int code = OH_UdmfRecord_AddPlainText(m_primitive.get(), uds);
+                if (Udmf_ErrCode::UDMF_E_OK != code) {
+                    qCWarning(ohauxiliary) << Q_FUNC_INFO << "OH_UdmfRecord_AddPlainText failed, error code:" << code;
+                }
+            }
+        } else if constexpr(std::is_same_v<T, ::OH_UdsFileUri>) {
+            T *uds = udsObj.data();
+            if (nullptr != uds) {
+                int code = OH_UdmfRecord_AddFileUri(m_primitive.get(), uds);
+                if (Udmf_ErrCode::UDMF_E_OK != code) {
+                    qCWarning(ohauxiliary) << Q_FUNC_INFO << "OH_UdmfRecord_AddFileUri failed, error code:" << code;
+                }
+            }
+        } else if constexpr(std::is_same_v<T, ::OH_UdsPixelMap>) {
+            T *uds = udsObj.data();
+            if (nullptr != uds) {
+                int code = OH_UdmfRecord_AddPixelMap(m_primitive.get(), uds);
+                if (Udmf_ErrCode::UDMF_E_OK != code) {
+                    qCWarning(ohauxiliary) << Q_FUNC_INFO << "OH_UdmfRecord_AddPixelMap failed, error code:" << code;
+                }
+            }
+        }
+    }
+
+    template <typename T>
+    QOhUdsObject<T> getUdsObj() {
+        return QOhUdsObject<T>(m_primitive.get());
+    }
+
+    std::optional<QByteArray> tryGetGeneralEntry(std::string_view typeId);
+    void addGeneralEntry(const std::string_view &typeId, uchar *buff, uint size);
+
+private:
+    ::OH_UdmfRecord *release();
+    static QOhUdmfRecord makeAsView(::OH_UdmfRecord *primitive);
+    QOhUdmfRecord(std::unique_ptr<::OH_UdmfRecord, void(*)(::OH_UdmfRecord *)> &&primitive);
+};
+
+QOhUdmfRecord::QOhUdmfRecord()
+    : QOhUdmfRecord(newUniqueOrFail(OH_UdmfRecord_Create(), OH_UdmfRecord_Destroy))
+{
+
+}
+
+std::vector<std::string> QOhUdmfRecord::getTypes()
+{
+    quint32 count(0);
+    std::vector<std::string> typelist{};
+    char **list = OH_UdmfRecord_GetTypes(m_primitive.get(), &count);
+    if (nullptr == list)
+        return typelist;
+
+    std::span<char *> types(list, count);
+    for (auto type : types)
+        typelist.emplace_back(type);
+
+    //delete [] list; //FIXME
+    return typelist;
+}
+
+std::optional<QByteArray> QOhUdmfRecord::tryGetGeneralEntry(std::string_view typeId)
+{
+    auto existsTypes = getTypes();
+    auto it = std::find(std::begin(existsTypes), std::end(existsTypes), typeId);
+    if (it == std::end(existsTypes))
+        return std::nullopt;
+
+    unsigned int count { 0 };
+    unsigned char *entry { nullptr };
+
+    int code = OH_UdmfRecord_GetGeneralEntry(m_primitive.get(), typeId.data(), &entry, &count);
+    if (Udmf_ErrCode::UDMF_E_OK != code) {
+        qCWarning(ohauxiliary,
+                  "%s OH_UdmfRecord_GetGeneralEntry result error, type: %s erro code: %d",
+                  Q_FUNC_INFO, typeId.data(), code);
+
+        return std::nullopt;
+    }
+
+    return QByteArray(reinterpret_cast<char*>(entry), count);
+}
+
+void QOhUdmfRecord::addGeneralEntry(const std::string_view &typeId, uchar *buff, uint size)
+{
+    int code = OH_UdmfRecord_AddGeneralEntry(m_primitive.get(), typeId.data(), buff, size);
+    if (Udmf_ErrCode::UDMF_E_OK != code) {
+        qCWarning(ohauxiliary,
+                  "%s OH_UdmfRecord_AddGeneralEntry result error, type: %s erro code: %d",
+                  Q_FUNC_INFO, typeId.data(), code);
+    }
+}
+
+QOhUdmfRecord QOhUdmfRecord::makeAsView(OH_UdmfRecord *primitive)
+{
+    return QOhUdmfRecord(
+            std::unique_ptr<::OH_UdmfRecord, void (*)(::OH_UdmfRecord *)>(
+                    primitive,
+                    [](::OH_UdmfRecord *) {
+                    }));
+}
+
+QOhUdmfRecord::QOhUdmfRecord(std::unique_ptr<OH_UdmfRecord, void (*)(::OH_UdmfRecord *)> &&primitive)
+    : m_primitive(std::move(primitive))
+{
+
+}
+
+OH_UdmfRecord *QOhUdmfRecord::release()
+{
+    return m_primitive.release();
+}
+
+class QOhUdmfData
+{
+    Q_DISABLE_COPY(QOhUdmfData)
+    std::unique_ptr<::OH_UdmfData, void(*)(::OH_UdmfData *)> m_primitive;
+
+public:
+    static QOhUdmfData takeOwnership(::OH_UdmfData *nativePtr);
+
+    QOhUdmfData();
+    QOhUdmfData(QOhUdmfData &&) = default;
+    QOhUdmfData &operator=(QOhUdmfData &&) = default;
+
+    std::vector<std::string> getTypes() const;
+
+    void addRecord(QOhUdmfRecord &&record);
+    std::vector<QOhUdmfRecord> getRecords();
+
+    ::OH_UdmfData *release();
+    ::OH_UdmfData *primitive();
+
+private:
+    QOhUdmfData(::OH_UdmfData *primitive);
+};
+
+QOhUdmfData QOhUdmfData::takeOwnership(OH_UdmfData *primitive)
+{
+    return QOhUdmfData(primitive);
+}
+
+QOhUdmfData::QOhUdmfData()
+    : QOhUdmfData(::OH_UdmfData_Create())
+{
+
+}
+
+std::vector<std::string> QOhUdmfData::getTypes() const
+{
+    char **types = nullptr;
+    unsigned int count = 0;
+    types = OH_UdmfData_GetTypes(m_primitive.get(), &count);
+    if (nullptr != types)
+        return {types, types + count};
+
+    return {};
+}
+
+void QOhUdmfData::addRecord(QOhUdmfRecord &&record)
+{
+    int code = ::OH_UdmfData_AddRecord(m_primitive.get(), std::move(record).release());
+    if (Udmf_ErrCode::UDMF_E_OK != code) {
+        qCWarning(ohauxiliary) << "add ohdmf record failed, code:" << code;
+    }
+}
+
+std::vector<QOhUdmfRecord> QOhUdmfData::getRecords()
+{
+    quint32 rdLength(0);
+    OH_UdmfRecord** rds = OH_UdmfData_GetRecords(m_primitive.get(), &rdLength);
+    // qCInfo(ohauxiliary) << Q_FUNC_INFO << "get data count:" << rdLength;
+
+    std::vector<QOhUdmfRecord> records;
+    for (quint32 i = 0; i < rdLength; ++i)
+        records.emplace_back(QOhUdmfRecord::makeAsView(rds[i]));
+
+    return records;
+}
+
+QOhUdmfData::QOhUdmfData(OH_UdmfData *primitive)
+    :m_primitive(newUniqueOrFail(primitive, ::OH_UdmfData_Destroy))
+{
+
+}
+
+OH_UdmfData *QOhUdmfData::primitive()
+{
+    return m_primitive.get();
+}
+
+OH_UdmfData *QOhUdmfData::release()
+{
+    return m_primitive.release();
+}
+
+template <typename T>
+using QOhConsumer = std::function<void(const T&)>;
+
+template <typename T>
+void processRecordsByType(std::span<QOhUdmfRecord> records,
+                          const QOhConsumer<QOhUdsObject<T>> &func)
+{
+    for (auto &record : records) {
+        for (auto &typeId : record.getTypes()) {
+            if (QOhUdsMeta<T>::udmfMetaId == std::string_view(typeId))
+                func(record.getUdsObj<T>());
+        }
+    }
+}
+
+bool hasQMimeDataPeerType(std::string_view type)
+{
+    static std::set<std::string_view> types {
+        QOhUdsMeta<::OH_UdsHtml>::udmfMetaId,
+        QOhUdsMeta<::OH_UdsFileUri>::udmfMetaId,
+        QOhUdsMeta<::OH_UdsPixelMap>::udmfMetaId,
+        QOhUdsMeta<::OH_UdsPlainText>::udmfMetaId
+    };
+
+    return types.find(type) != types.end();
+}
+
+bool isUdmfMetaFileType(std::string_view type)
+{
+    static std::set<std::string_view> types {
+        UDMF_META_GENERAL_FILE,
+        UDMF_META_AUDIO,
+        UDMF_META_FOLDER,
+        UDMF_META_IMAGE,
+        UDMF_META_VIDEO,
+    };
+
+    return types.find(type) != types.end();
+}
+
+void extractFileUrisToMimeData(std::span<QOhUdmfRecord> records, QMimeData * const mimeData)
+{
+    QList<QUrl> urls;
+    processRecordsByType<::OH_UdsFileUri>(records, [&urls](auto udsObj) {
+        urls.append(QUrl::fromLocalFile(QString::fromLocal8Bit(udsObj.getContent())));
+    });
+
+    if (!urls.isEmpty())
+        mimeData->setUrls(urls);
+}
+
+void extractGeneralEntriesToMimeData(std::span<QOhUdmfRecord> records, QMimeData * const mimeData)
+{
+    for (auto &record : records) {
+        for (auto typeId : record.getTypes()) {
+            if (!hasQMimeDataPeerType(typeId) && !isUdmfMetaFileType(typeId)) {
+                auto data = record.tryGetGeneralEntry(typeId);
+                if (!data.has_value())
+                    continue;
+
+                mimeData->setData(QString::fromStdString(typeId),
+                                  data.value());
+            }
+        }
+    }
+}
+
+}
+
+namespace QtOh {
+
+QImage UdmfHelper::createQImageFromPixelmapNative(OH_PixelmapNative *pixelNative)
+{
+    OH_Pixelmap_ImageInfo *imageInfo(Q_NULLPTR);
+    int code = OH_PixelmapImageInfo_Create(&imageInfo);
+    QOhObjectHolder<OH_Pixelmap_ImageInfo> imageInfoHolder(imageInfo, OH_PixelmapImageInfo_Release);
+    Q_UNUSED(imageInfoHolder);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary) << Q_FUNC_INFO << "create pixel image info, error code:" << code;
+        return QImage();
+    }
+
+    code = OH_PixelmapNative_GetImageInfo(pixelNative, imageInfo);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary) << Q_FUNC_INFO << "get image info failed, error code:" << code;
+        return QImage();
+    }
+
+    /* 获取图片的宽,高,pixel格式,透明度等信息 */
+    uint32_t width, height, rowStride;
+    int32_t pixelFormat, alphaType;
+
+    code = OH_PixelmapImageInfo_GetWidth(imageInfo, &width);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary) << Q_FUNC_INFO << "get image info width failed, code:" << code;
+        return QImage();
+    }
+    code = OH_PixelmapImageInfo_GetHeight(imageInfo, &height);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary) << Q_FUNC_INFO << "get image info height failed, code:" << code;
+        return QImage();
+    }
+
+    code = OH_PixelmapImageInfo_GetRowStride(imageInfo, &rowStride);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary) << Q_FUNC_INFO << "get image info rowStride failed, code:" << code;
+        return QImage();
+    }
+    code = OH_PixelmapImageInfo_GetAlphaType(imageInfo, &alphaType);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary) << Q_FUNC_INFO << "get image info alphaType failed, code:" << code;
+        return QImage();
+    }
+
+    code = OH_PixelmapImageInfo_GetPixelFormat(imageInfo, &pixelFormat);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary) << Q_FUNC_INFO << "get image info pixelFormat failed, code:" << code;
+        return QImage();
+    }
+
+    auto dest = new QVector<uint8_t>(bufferSizeHelper(pixelFormat, width, height));
+
+    size_t size = dest->size();
+    code = OH_PixelmapNative_ReadPixels(pixelNative, dest->data(), &size);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary) << Q_FUNC_INFO << "read pixels failed, error code:" << code;
+        return QImage();
+    }
+
+    QImage image(dest->data(), int(width), int(height),
+                 pixelMapFormatToQImage(pixelFormat), [](void *info){
+                     delete reinterpret_cast<QVector<uint8_t>*>(info);
+                 }, reinterpret_cast<void*>(dest));
+
+    if(PIXEL_FORMAT_BGRA_8888 == pixelFormat){
+        image = image.rgbSwapped();
+    }
+
+    return image;
+}
+
+/*!
+ * \brief 将QImage转为鸿蒙像素图数据
+ * \param image QImage参数
+ * \return 返回OH_PixelmapNative指针
+ * 调用者负责使用OH_PixelmapNative_Release清理数据
+ */
+OH_PixelmapNative *UdmfHelper::createNativePixelMapFromQImage(const QImage &image)
+{
+    if (image.isNull())
+        return nullptr;
+    OH_Pixelmap_InitializationOptions *createOptionNative(nullptr);
+    int code = OH_PixelmapInitializationOptions_Create(&createOptionNative);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary, "%s create pixelmap options failed, code: %d", Q_FUNC_INFO, code);
+    }
+
+    std::unique_ptr<OH_Pixelmap_InitializationOptions,
+                    Image_ErrorCode(*)(OH_Pixelmap_InitializationOptions*)>
+            createOpts(newUniqueOrFail(createOptionNative, ::OH_PixelmapInitializationOptions_Release));
+
+    auto qImageFormatToPixelMap = [](QImage::Format format, bool &premultiplied)->int32_t{
+        switch (format) {
+        case QImage::Format_Alpha8:
+            return (premultiplied = false, PIXEL_FORMAT_ALPHA_8);
+        case QImage::Format_RGB888:
+            return (premultiplied = false, PIXEL_FORMAT_RGB_888);
+        case QImage::Format_RGBA8888:
+            return (premultiplied = false, PIXEL_FORMAT_RGBA_8888);
+        case QImage::Format_RGBA8888_Premultiplied:
+            return (premultiplied = true, PIXEL_FORMAT_RGBA_8888);
+        default:
+            break;
+        }
+        return PIXEL_FORMAT_UNKNOWN;
+    };
+
+    auto alphaTypeFunc = [](const QImage &image, bool premultiplied)->int32_t {
+        if (!image.hasAlphaChannel()) {
+            return PIXELMAP_ALPHA_TYPE_OPAQUE;
+        } else if (image.hasAlphaChannel() && premultiplied) {
+            return PIXELMAP_ALPHA_TYPE_PREMULTIPLIED;
+        } else {
+            return PIXELMAP_ALPHA_TYPE_UNKNOWN;
+        }
+    };
+
+    bool ispre = false;
+    int32_t format = PIXEL_FORMAT_RGBA_8888;
+    format = qImageFormatToPixelMap(image.format(), ispre);
+    int32_t alphaType = alphaTypeFunc(image, ispre);
+
+    /* FIXME 鸿蒙不支持的格式需要转换
+     * 当前统一转换为QImage::Format_RGBA8888
+     */
+    QImage ohImage = image;
+    if (PIXEL_FORMAT_UNKNOWN == format)
+        ohImage = ohImage.convertToFormat(QImage::Format_RGBA8888);
+
+    code = OH_PixelmapInitializationOptions_SetWidth(createOpts.get(), ohImage.width());
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary, "%s set pixelmap width failed, code: %d", Q_FUNC_INFO, code);
+        return nullptr;
+    }
+
+    code = OH_PixelmapInitializationOptions_SetHeight(createOpts.get(), ohImage.height());
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary, "%s set pixelmap height failed, code: %d", Q_FUNC_INFO, code);
+        return nullptr;
+    }
+
+    code = OH_PixelmapInitializationOptions_SetPixelFormat(createOpts.get(), format);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary, "%s set pixelmap format failed, code: %d", Q_FUNC_INFO, code);
+        return nullptr;
+    }
+
+    code = OH_PixelmapInitializationOptions_SetAlphaType(createOpts.get(), alphaType);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary, "%s set pixelmap alpha type failed, code: %d", Q_FUNC_INFO, code);
+        return nullptr;
+    }
+
+    /* 创建Pixelmap实例 */
+    OH_PixelmapNative *pixelNative(nullptr);
+    code = OH_PixelmapNative_CreateEmptyPixelmap(createOpts.get(), &pixelNative);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary, "%s create pixelmap native implement failed, code: %d", Q_FUNC_INFO, code);
+        return nullptr;
+    }
+
+    std::unique_ptr<OH_PixelmapNative, Image_ErrorCode(*)(OH_PixelmapNative*)> pixelMapNative
+            (newUniqueOrFail(pixelNative, ::OH_PixelmapNative_Release));
+
+
+    qsizetype size = ohImage.sizeInBytes();
+    code = OH_PixelmapNative_WritePixels(pixelMapNative.get(), const_cast<uchar*>(ohImage.bits()), size);
+    if (Image_ErrorCode::IMAGE_SUCCESS != code) {
+        qCWarning(ohauxiliary, "%s OH_PixelmapNative_WritePixels result failed, code: %d", Q_FUNC_INFO, code);
+        return nullptr;
+    }
+
+    return pixelMapNative.release();
+}
+
+/*!
+ * \brief 读取OH_UdmfData中的数据到QMimeData.
+ * 传入的OH_UdmfData参数,函数内部使用智能指针管理并负责清理数据.
+ * \param udmfData OH_UdmfData数据
+ * \param mimeData QMimeData指针
+ */
+void UdmfHelper::acquireDatasFromUdmfToMime(::OH_UdmfData *const udmfData, QMimeData * const mimeData)
+{
+    if (!udmfData || !mimeData)
+        return;
+
+    QOhUdmfData ohUdmfData = QOhUdmfData::takeOwnership(udmfData);
+    auto records = ohUdmfData.getRecords();
+    if (records.empty())
+        return;
+
+    /* html */
+    processRecordsByType<::OH_UdsHtml>(std::span<QOhUdmfRecord>(records.data(), 1), [mimeData](auto udsObj){
+        mimeData->setHtml(QString::fromUtf8(udsObj.getContent()));
+    });
+
+    /* 文本 */
+    processRecordsByType<::OH_UdsPlainText>(std::span<QOhUdmfRecord>(records.data(), 1), [mimeData](auto udsObj){
+        mimeData->setText(QString::fromUtf8(udsObj.getContent()));
+    });
+
+    /* PixelMap */
+    processRecordsByType<::OH_UdsPixelMap>(std::span<QOhUdmfRecord>(records.data(), 1), [mimeData](auto udsObj){
+        mimeData->setImageData(createQImageFromNativePixelMap(udsObj.getContent().get()));
+    });
+
+    /* fileuri */
+    extractFileUrisToMimeData(std::span<QOhUdmfRecord>(records.data(), records.size()), mimeData);
+
+    /* 自定义 */
+    extractGeneralEntriesToMimeData(std::span<QOhUdmfRecord>(records.data(), 1), mimeData);
+}
+
+/*!
+ * \brief 返回的OH_UdmfData,在向系统接口添加该OH_UdmfData失败时
+ * 需要调用方负责OH_UdmfData_Destroy
+ */
+::OH_UdmfData *UdmfHelper::makeUdmfDataFromMime(QMimeData * const mimeData, std::optional<bool> shareOnlyApp)
+{
+    std::vector<std::function<void(QOhUdmfRecord &)>> addUdsFuncs;
+
+    for (auto format : mimeData->formats()) {
+        if (format == textHtmlLiteral()) {
+            const QString &html = mimeData->html();
+            addUdsFuncs.emplace_back(
+                    [html](QOhUdmfRecord &record) {
+                        record.addUdsObj(QOhUdsObject<::OH_UdsHtml>(html.toStdString()));
+                    });
+        } else if (format == textPlainLiteral()) {
+            const QString text = mimeData->text();
+            addUdsFuncs.emplace_back(
+                    [text](QOhUdmfRecord &record) {
+                        record.addUdsObj(QOhUdsObject<::OH_UdsPlainText>(text.toStdString()));
+                    });
+        } else if (format == textUriListLiteral()) {
+            auto urls = mimeData->urls();
+            auto url = urls.first().toString();
+            addUdsFuncs.emplace_back(
+                    [url](QOhUdmfRecord &record) {
+                        record.addUdsObj(QOhUdsObject<::OH_UdsFileUri>(url.toStdString()));
+                    });
+
+        } else if (format == applicationXQtImageLiteral()) {
+            auto image = qvariant_cast<QImage>(mimeData->imageData());
+            addUdsFuncs.emplace_back(
+                    [image](QOhUdmfRecord &record) {
+                        record.addUdsObj(QOhUdsObject<::OH_UdsPixelMap>(image));
+                    });
+        } else {
+            auto dataBytes = mimeData->data(format);
+            addUdsFuncs.emplace_back(
+                    [format, dataBytes](QOhUdmfRecord &record) mutable {
+                        record.addGeneralEntry(
+                                format.toStdString(),
+                                reinterpret_cast<uchar *>(dataBytes.data()), dataBytes.length());
+                    });
+        }
+    }
+
+    std::vector<std::function<QOhUdmfRecord()>> records;
+    if (!addUdsFuncs.empty()) {
+        records.emplace_back(
+                [addUdsFuncs = std::move(addUdsFuncs)]() {
+                    QOhUdmfRecord record;
+                    for (const auto &addUds : addUdsFuncs) {
+                        addUds(record);
+                    }
+                    return record;
+                });
+    }
+
+    auto urls = mimeData->urls();
+    for (int i = 1; i < urls.size(); ++i) {
+        auto url = urls.at(i).toString();
+        records.emplace_back(
+                [url]() {
+                    QOhUdmfRecord uriRecord;
+                    uriRecord.addUdsObj(QOhUdsObject<::OH_UdsFileUri>(url.toStdString()));
+                    return uriRecord;
+                });
+    }
+
+    QOhUdmfData ohUdmfData;
+    if (shareOnlyApp.has_value()) {
+        ::OH_UdmfProperty* property = ::OH_UdmfProperty_Create(ohUdmfData.primitive());
+        if (nullptr == property) {
+            qCWarning(ohauxiliary, "%s create OH_UdmfProperty_Create failed.", Q_FUNC_INFO);
+            return ohUdmfData.release();
+        }
+
+        int ret = OH_UdmfProperty_SetShareOption(property, shareOnlyApp.value() ?
+                                                         ::Udmf_ShareOption::SHARE_OPTIONS_IN_APP :
+                                                         ::Udmf_ShareOption::SHARE_OPTIONS_CROSS_APP);
+
+        if (::Udmf_ErrCode::UDMF_E_OK != ret) {
+            ::OH_UdmfProperty_Destroy(property);
+            return ohUdmfData.release();
+        }
+
+    }
+
+    for (const auto &record : records) {
+        ohUdmfData.addRecord(record());
+    }
+
+    return ohUdmfData.release();
+}
+
+bool wait(QEventLoop *loop, int ms)
+{
+    QTimer timer;
+    timer.setSingleShot(true);
+    QObject::connect(&timer, &QTimer::timeout, loop, std::bind(&QEventLoop::exit, loop, -1));
+    timer.start(ms);
+    return loop->exec() == -1;
+}
+
+bool isEnvironmentVariableIsTrue(const char *env, bool defaultValue)
+{
+    if (!qEnvironmentVariableIsSet(env))
+        return defaultValue;
+    QByteArray value = qgetenv(env);
+    if (value.isEmpty())
+        return false;
+    if (value == "true" || value.toInt() != 0)
+        return true;
+    return false;
+}
+
+qreal densityPixels(QPlatformScreen *screen)
+{
+    if (screen == nullptr)
+        return 1.0;
+    if (QOhPlatformScreen *ps = dynamic_cast<QOhPlatformScreen *>(screen)) {
+        return ps->densityPixels();
+    }
+    return screen->devicePixelRatio();
+}
+
+}
diff --git a/src/plugins/platforms/openharmony/qohauxiliary.h b/src/plugins/platforms/openharmony/qohauxiliary.h
new file mode 100644
index 00000000000..234e369f0c6
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohauxiliary.h
@@ -0,0 +1,217 @@
+/*******************************************************************
+ *  Copyright(c) 2022-2025 Ltd.
+ *  All right reserved. See LGPL for detailed Information
+ *
+ *  文件名称: qohauxiliary.h
+ *  简要描述: 封装了鸿蒙接口调用的辅助函数集
+ *  创建日期: 2025/01/15
+ *  作者: WangHao
+ *  说明:
+ *
+ *  修改日期: 2025年3月12日
+ *  作者: WangHao
+ *  说明: 添加了Udmf数据读取相关处理
+ ******************************************************************/
+#ifndef QOHAUXILIARY_H
+#define QOHAUXILIARY_H
+
+#include <QString>
+#include <optional>
+#include <QByteArray>
+#include <QRect>
+#include <QSharedPointer>
+#include <QJsObject>
+#include <QThread>
+#include <QGuiApplication>
+#include <qpa/qplatformscreen.h>
+#include <qohutility.h>
+#include "qjssettings.h"
+
+class QMimeData;
+class QEventLoop;
+struct OH_UdmfData;
+struct OH_UdmfRecord;
+struct OH_PixelmapNative;
+class QOhPlatformClipboard;
+QT_BEGIN_NAMESPACE
+namespace QtOh {
+
+/* 系统窗口状态 */
+enum class WindowStatusType {
+    UNDEFINED	 = 0,	/* 表示APP未定义窗口模式 */
+    FULL_SCREEN	 = 1,	/* 表示APP全屏模式 */
+    MAXIMIZE	 = 2,	/* 表示APP窗口最大化模式 */
+    MINIMIZE	 = 3,	/* 表示APP窗口最小化模式 */
+    FLOATING	 = 4,	/* 表示APP自由悬浮形式窗口模式 */
+    SPLIT_SCREEN = 5,	/* 表示APP分屏模式 */
+    SURFACE_SHOW = 6
+};
+
+/* harmony os state */
+enum class WindowState {
+    WINDOW_SHOWN = 1,
+    WINDOW_ACTIVE = 2,
+    WINDOW_INACTIVE = 3,
+    WINDOW_HIDDEN = 4,
+    WINDOW_DESTROYED = 7
+};
+
+class UdmfHelper
+{
+    friend QOhPlatformClipboard;
+
+public:
+    static QImage createQImageFromPixelmapNative(OH_PixelmapNative *pixelmapNative);
+    static OH_PixelmapNative* createNativePixelMapFromQImage(const QImage &image);
+    static void acquireDatasFromUdmfToMime(::OH_UdmfData *const udmfData, QMimeData * const mimeData);
+    static ::OH_UdmfData * makeUdmfDataFromMime(QMimeData * const mimeData, std::optional<bool> shareOnlyApp = std::nullopt);
+};
+
+inline std::shared_ptr<void> makeDestroyNotifier(std::function<void()> callOnDestroy)
+{
+    class DestroyNotifier
+    {
+    public:
+        explicit DestroyNotifier(std::function<void()> callOnDestroy)
+            : callOnDestroy(std::move(callOnDestroy))
+        {
+        }
+
+        DestroyNotifier(const DestroyNotifier &) = delete;
+        DestroyNotifier(DestroyNotifier &&) = delete;
+        DestroyNotifier &operator=(const DestroyNotifier &) = delete;
+        DestroyNotifier &operator=(DestroyNotifier &&) = delete;
+
+        ~DestroyNotifier()
+        {
+            callOnDestroy();
+        };
+
+    private:
+        std::function<void()> callOnDestroy;
+    };
+
+    return std::make_shared<DestroyNotifier>(std::move(callOnDestroy));
+}
+
+inline QRect jsRect2QRect(const Napi::Object &rect)
+{
+    return QRect(rect.Get("left").ToNumber(), rect.Get("top").ToNumber(),
+                 rect.Get("width").ToNumber(), rect.Get("height").ToNumber());
+}
+
+/*!
+ * \brief 等待函数,超时返回true
+ */
+bool wait(QEventLoop *loop, int ms);
+
+template <typename Function, typename... Args>
+void runOnQtMainThread(Function&& function, Args&&... args)
+{
+    if (QCoreApplication::instance() == nullptr)
+        return;
+
+    auto callable = [function, ...args = std::forward<Args>(args)]() mutable {
+        std::invoke(std::forward<Function>(function), std::forward<Args>(args)...);
+    };
+
+    if (QThread::currentThread() == QCoreApplication::instance()->thread()) {
+        callable();
+    } else {
+        QMetaObject::invokeMethod(QCoreApplication::instance(), callable, Qt::QueuedConnection);
+    }
+}
+
+template <typename Function, typename... Args>
+auto runOnQtMainThreadWithResult(Function&& function, Args&&... args)
+    -> decltype(std::invoke(std::forward<Function>(function), std::forward<Args>(args)...))
+{
+    using ReturnType = decltype(std::invoke(std::forward<Function>(function), std::forward<Args>(args)...));
+    auto promise = std::make_shared<std::promise<ReturnType>>();
+    auto future = promise->get_future();
+
+    auto callable = [promise, function, ...args = std::forward<Args>(args)]() mutable {
+        if constexpr (std::is_void_v<ReturnType>) {
+            std::invoke(std::forward<Function>(function), std::forward<Args>(args)...);
+            promise->set_value();
+        } else {
+            promise->set_value(std::invoke(std::forward<Function>(function), std::forward<Args>(args)...));
+        }
+    };
+
+    if (QThread::currentThread() == QCoreApplication::instance()->thread()) {
+        callable();
+    } else {
+        QMetaObject::invokeMethod(QCoreApplication::instance(), callable, Qt::QueuedConnection);
+    }
+
+    return future.get();
+}
+
+template <typename Function, typename... Args>
+void runOnQtMainThreadAndWait(Function&& function, Args&&... args)
+{
+    auto promise = std::make_shared<std::promise<void>>();
+    auto future = promise->get_future();
+
+    auto callable = [promise, function, ...args = std::forward<Args>(args)]() mutable {
+        std::invoke(std::forward<Function>(function), std::forward<Args>(args)...);
+        promise->set_value();
+    };
+
+    if (QThread::currentThread() == QCoreApplication::instance()->thread()) {
+        callable();
+    } else {
+        QMetaObject::invokeMethod(QCoreApplication::instance(), callable, Qt::QueuedConnection);
+    }
+
+    return future.get();
+}
+
+inline void runOnQtMainThreadLater(const std::function<void ()> &f)
+{
+    if (QCoreApplication::instance() == nullptr || !f)
+        return;
+    QMetaObject::invokeMethod(QCoreApplication::instance(), f, Qt::QueuedConnection);
+}
+
+inline bool isFreeWindowEnable()
+{
+    return QJsSettings::instance()->isFreeWindowEnable();
+}
+
+inline bool isTabletDevice()
+{
+    return (QtOh::Utility::type() == QtOh::Utility::Tablet);
+}
+
+inline bool isPhoneDevice()
+{
+    return (QtOh::Utility::type() == QtOh::Utility::Phone);
+}
+
+inline bool isSupportFreeWindow()
+{
+    return (QtOh::Utility::type() == QtOh::Utility::PC ||
+            ((QtOh::isTabletDevice() || QtOh::isPhoneDevice()) && QtOh::isFreeWindowEnable()));
+}
+
+inline bool checkDeviceType(const QtOh::Utility::DeviceTypes deviceTypes)
+{
+    return QtOh::Utility::type() & deviceTypes;
+}
+
+inline bool isOpenHarmonyDevice()
+{
+    return QtOh::Utility::distributionOSName() == QStringLiteral("OpenHarmony");
+}
+
+qreal densityPixels(QPlatformScreen *screen);
+
+// 如果环境变量没有设置返回defaultValue
+bool isEnvironmentVariableIsTrue(const char *env, bool defaultValue = true);
+
+}
+
+QT_END_NAMESPACE
+#endif // QOHAUXILIARY_H
diff --git a/src/plugins/platforms/openharmony/qohcompatibility.cpp b/src/plugins/platforms/openharmony/qohcompatibility.cpp
new file mode 100644
index 00000000000..06ac3a56c7a
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohcompatibility.cpp
@@ -0,0 +1,20 @@
+#include "qohcompatibility.h"
+#include <qopenharmony.h>
+
+#include <QHash>
+#include <QPair>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+void QOhCompatibility::init()
+{
+    auto v = QtOh::apiVersion();
+    if (v < OHOS_SDK_VERSION) {
+        qWarning() << "OS api version is less than build api version:"
+                   << QString("the os version is %1 and build version is %2").arg(v).arg(OHOS_SDK_VERSION);
+    }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/openharmony/qohcompatibility.h b/src/plugins/platforms/openharmony/qohcompatibility.h
new file mode 100644
index 00000000000..9ee50ff8d5b
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohcompatibility.h
@@ -0,0 +1,299 @@
+#ifndef QOHCOMPATIBILITY_H
+#define QOHCOMPATIBILITY_H
+
+#include <QString>
+#include <QDebug>
+#include <QStringList>
+#include <dlfcn.h>
+#if OHOS_SDK_VERSION > 13
+#include <window_manager/oh_display_capture.h>
+#include <arkui/native_key_event.h>
+#else
+typedef enum {
+    /** Unknown type **/
+    ARKUI_KEY_EVENT_UNKNOWN = -1,
+    /** Pressing of a key **/
+    ARKUI_KEY_EVENT_DOWN = 0,
+    /** Release of a key **/
+    ARKUI_KEY_EVENT_UP = 1,
+    /** Long press of a key **/
+    ARKUI_KEY_EVENT_LONG_PRESS = 2,
+    /** Click of a key **/
+    ARKUI_KEY_EVENT_CLICK = 3,
+} ArkUI_KeyEventType;
+#endif
+
+#if OHOS_SDK_VERSION >= 15
+#else
+typedef bool (*OH_NativeWindowManager_MouseEventFilter)(Input_MouseEvent* mouseEvent);
+typedef bool (*OH_NativeWindowManager_TouchEventFilter)(Input_TouchEvent* touchEvent);
+#endif
+
+#include <database/pasteboard/oh_pasteboard.h>
+#include <arkui/native_node.h>
+#include <window_manager/oh_window_comm.h>
+#include <window_manager/oh_window_event_filter.h>
+struct ArkUI_UIInputEvent;
+
+QT_BEGIN_NAMESPACE
+
+namespace QOhCompatibility {
+
+inline QStringList& openedLibraries() {
+    static QStringList libs;
+    return libs;
+}
+
+template<typename FuncPtr>
+FuncPtr locationOhosFunction(const QString &name, const QString &lib)
+{
+    if (!openedLibraries().contains(lib)) {
+        auto handle = dlopen(lib.toUtf8().constData(), RTLD_LAZY | RTLD_GLOBAL);
+        if (handle) {
+            openedLibraries() << lib;
+        } else {
+            return nullptr;
+        }
+    }
+    FuncPtr m_function = reinterpret_cast<FuncPtr>(dlsym(RTLD_DEFAULT, name.toUtf8().constData()));
+    if (!m_function) {
+        qWarning() << "Failed to resolve:" << name << ", error:" << dlerror();
+    }
+    return m_function;
+}
+
+template<typename Signature>
+class OhosFunction;
+
+template<typename RetType, typename... Args>
+class OhosFunction<RetType(Args...)> {
+private:
+    using FuncPtr = RetType(*)(Args...);
+    FuncPtr m_function;
+    RetType m_fallbackValue;
+
+public:
+    OhosFunction(const QString &name, const QString &lib, RetType fallback = RetType())
+        : m_fallbackValue(fallback)
+    {
+        m_function = locationOhosFunction<FuncPtr>(name, lib);
+    }
+
+    RetType operator()(const Args&... args) const
+    {
+        if (m_function) {
+            return m_function(args...);
+        }
+        return m_fallbackValue;
+    }
+};
+
+template<typename... Args>
+class OhosFunction<void(Args...)> {
+private:
+    using FuncPtr = void(*)(Args...);
+    FuncPtr m_function;
+
+public:
+    OhosFunction(const QString &name, const QString &lib)
+    {
+        m_function = locationOhosFunction<FuncPtr>(name, lib);
+    }
+
+    void operator()(const Args&... args) const
+    {
+        if (m_function) {
+            m_function(args...);
+        }
+    }
+};
+
+void init();
+
+inline int32_t OH_ArkUI_AxisEvent_GetAxisAction(ArkUI_UIInputEvent * event)
+{
+    static OhosFunction<int32_t(ArkUI_UIInputEvent *)> S_OH_ArkUI_AxisEvent_GetAxisAction("OH_ArkUI_AxisEvent_GetAxisAction",
+        "libace_ndk.z.so", -1);
+    return S_OH_ArkUI_AxisEvent_GetAxisAction(event);
+}
+
+inline NativeDisplayManager_ErrorCode OH_NativeDisplayManager_CaptureScreenPixelmap(uint32_t id, OH_PixelmapNative **out)
+{
+    static OhosFunction<NativeDisplayManager_ErrorCode(uint32_t, OH_PixelmapNative **)> S_OH_NativeDisplayManager_CaptureScreenPixelmap("OH_NativeDisplayManager_CaptureScreenPixelmap",
+                                                                                          "libnative_display_manager.so", DISPLAY_MANAGER_ERROR_DEVICE_NOT_SUPPORTED);
+    return S_OH_NativeDisplayManager_CaptureScreenPixelmap(id, out);
+}
+
+inline int32_t OH_ArkUI_AxisEvent_GetScrollStep(ArkUI_UIInputEvent *event)
+{
+    static OhosFunction<int32_t(ArkUI_UIInputEvent *)> S_OH_ArkUI_AxisEvent_GetScrollStep("OH_ArkUI_AxisEvent_GetScrollStep",
+                                                                                          "libace_ndk.z.so", 1);
+    return S_OH_ArkUI_AxisEvent_GetScrollStep(event);
+}
+
+inline OH_UdmfData* OH_Pasteboard_GetDataWithProgress(OH_Pasteboard* pasteboard, Pasteboard_GetDataParams* params,
+                                               int* status)
+{
+    static OhosFunction<OH_UdmfData *(OH_Pasteboard*, Pasteboard_GetDataParams*,
+                                      int*)> S_OH_Pasteboard_GetDataWithProgress("OH_Pasteboard_GetDataWithProgress",
+                                                "libpasteboard.so", nullptr);
+    return S_OH_Pasteboard_GetDataWithProgress(pasteboard, params, status);
+}
+
+inline void OH_Pasteboard_GetDataParams_SetProgressIndicator(Pasteboard_GetDataParams* params,
+                                                      Pasteboard_ProgressIndicator progressIndicator)
+{
+    static OhosFunction<void(Pasteboard_GetDataParams*, Pasteboard_ProgressIndicator)> S_OH_Pasteboard_GetDataParams_SetProgressIndicator("OH_Pasteboard_GetDataParams_SetProgressIndicator",
+                                                                                                                                           "libpasteboard.so");
+    S_OH_Pasteboard_GetDataParams_SetProgressIndicator(params, progressIndicator);
+}
+
+inline void OH_Pasteboard_GetDataParams_SetProgressListener(Pasteboard_GetDataParams* params,
+                                                     const OH_Pasteboard_ProgressListener listener)
+{
+    static OhosFunction<void(Pasteboard_GetDataParams*, const OH_Pasteboard_ProgressListener)> S_OH_Pasteboard_GetDataParams_SetProgressListener("OH_Pasteboard_GetDataParams_SetProgressListener",
+                                                                                                                                                  "libpasteboard.so");
+    S_OH_Pasteboard_GetDataParams_SetProgressListener(params, listener);
+}
+
+inline int OH_Pasteboard_ProgressInfo_GetProgress(Pasteboard_ProgressInfo* progressInfo)
+{
+    static OhosFunction<int(Pasteboard_ProgressInfo*)> S_OH_Pasteboard_ProgressInfo_GetProgress("OH_Pasteboard_ProgressInfo_GetProgress",
+                                                                                                  "libpasteboard.so", 0);
+    return S_OH_Pasteboard_ProgressInfo_GetProgress(progressInfo);
+}
+
+inline Pasteboard_GetDataParams *OH_Pasteboard_GetDataParams_Create()
+{
+    static OhosFunction<Pasteboard_GetDataParams *()> S_OH_Pasteboard_GetDataParams_Create("OH_Pasteboard_GetDataParams_Create",
+                                                                                                 "libpasteboard.so", nullptr);
+    return S_OH_Pasteboard_GetDataParams_Create();
+}
+
+inline void OH_Pasteboard_ProgressCancel(Pasteboard_GetDataParams* params)
+{
+    static OhosFunction<void(Pasteboard_GetDataParams*)> S_OH_Pasteboard_ProgressCancel("OH_Pasteboard_ProgressCancel",
+                                                                                         "libpasteboard.so");
+    S_OH_Pasteboard_ProgressCancel(params);
+}
+
+inline int32_t OH_ArkUI_NodeUtils_GetNodeType(ArkUI_NodeHandle node)
+{
+    static OhosFunction<int32_t(ArkUI_NodeHandle)> S_OH_ArkUI_NodeUtils_GetNodeType("OH_ArkUI_NodeUtils_GetNodeType",
+                                                                                           "libace_ndk.z.so", 0);
+    return S_OH_ArkUI_NodeUtils_GetNodeType(node);
+}
+
+inline int32_t OH_ArkUI_UIInputEvent_GetTargetDisplayId(const ArkUI_UIInputEvent* event)
+{
+    static OhosFunction<int32_t(const ArkUI_UIInputEvent*)> S_OH_ArkUI_UIInputEvent_GetTargetDisplayId("OH_ArkUI_UIInputEvent_GetTargetDisplayId",
+                                                                                    "libace_ndk.z.so", 0);
+    return S_OH_ArkUI_UIInputEvent_GetTargetDisplayId(event);
+}
+
+inline int32_t OH_ArkUI_UIInputEvent_GetModifierKeyStates(const ArkUI_UIInputEvent* event, uint64_t* keys)
+{
+    static OhosFunction<int32_t(const ArkUI_UIInputEvent*, uint64_t*)> S_OH_ArkUI_UIInputEvent_GetModifierKeyStates("OH_ArkUI_UIInputEvent_GetModifierKeyStates",
+                                                                                                        "libace_ndk.z.so", 0);
+    return S_OH_ArkUI_UIInputEvent_GetModifierKeyStates(event, keys);
+}
+
+inline ArkUI_KeyEventType OH_ArkUI_KeyEvent_GetType(const ArkUI_UIInputEvent* event)
+{
+    static OhosFunction<ArkUI_KeyEventType(const ArkUI_UIInputEvent*)> S_OH_ArkUI_KeyEvent_GetType("OH_ArkUI_KeyEvent_GetType",
+                                                                                         "libace_ndk.z.so", ARKUI_KEY_EVENT_UNKNOWN);
+    return S_OH_ArkUI_KeyEvent_GetType(event);
+}
+
+inline int32_t OH_ArkUI_KeyEvent_GetKeyCode(const ArkUI_UIInputEvent* event)
+{
+    static OhosFunction<int32_t(const ArkUI_UIInputEvent*)> S_OH_ArkUI_KeyEvent_GetKeyCode("OH_ArkUI_KeyEvent_GetKeyCode",
+                                                                                            "libace_ndk.z.so", 0);
+    return S_OH_ArkUI_KeyEvent_GetKeyCode(event);
+}
+
+inline const char *OH_ArkUI_KeyEvent_GetKeyText(const ArkUI_UIInputEvent* event)
+{
+    static OhosFunction<const char *(const ArkUI_UIInputEvent*)> S_OH_ArkUI_KeyEvent_GetKeyText("OH_ArkUI_KeyEvent_GetKeyText",
+                                                                                            "libace_ndk.z.so", nullptr);
+    return S_OH_ArkUI_KeyEvent_GetKeyText(event);
+}
+
+inline int32_t OH_ArkUI_UIInputEvent_GetDeviceId(const ArkUI_UIInputEvent* event)
+{
+    static OhosFunction<int32_t(const ArkUI_UIInputEvent*)> S_OH_ArkUI_UIInputEvent_GetDeviceId("OH_ArkUI_UIInputEvent_GetDeviceId",
+                                                                                                 "libace_ndk.z.so", 0);
+    return S_OH_ArkUI_UIInputEvent_GetDeviceId(event);
+}
+
+inline int32_t OH_ArkUI_PointerEvent_GetChangedPointerId(const ArkUI_UIInputEvent* event, uint32_t* pointerIndex)
+{
+    static OhosFunction<int32_t(const ArkUI_UIInputEvent*, uint32_t*)> S_OH_ArkUI_PointerEvent_GetChangedPointerId("OH_ArkUI_PointerEvent_GetChangedPointerId",
+                                                                                                 "libace_ndk.z.so", 0);
+    return S_OH_ArkUI_PointerEvent_GetChangedPointerId(event, pointerIndex);
+}
+
+inline WindowManager_ErrorCode OH_NativeWindowManager_UnregisterMouseEventFilter(int32_t windowId)
+{
+    static OhosFunction<WindowManager_ErrorCode(int32_t)> S_OH_NativeWindowManager_UnregisterMouseEventFilter("OH_NativeWindowManager_UnregisterMouseEventFilter",
+                                                                                                                     "libnative_window_manager.so", OK);
+    return S_OH_NativeWindowManager_UnregisterMouseEventFilter(windowId);
+}
+
+inline WindowManager_ErrorCode OH_NativeWindowManager_RegisterMouseEventFilter(int32_t windowId,
+                                                                               OH_NativeWindowManager_MouseEventFilter mouseEventFilter)
+{
+    static OhosFunction<WindowManager_ErrorCode(int32_t, OH_NativeWindowManager_MouseEventFilter)> S_OH_NativeWindowManager_RegisterMouseEventFilter("OH_NativeWindowManager_RegisterMouseEventFilter",
+                                                                                                              "libnative_window_manager.so", OK);
+    return S_OH_NativeWindowManager_RegisterMouseEventFilter(windowId, mouseEventFilter);
+}
+
+inline WindowManager_ErrorCode OH_NativeWindowManager_RegisterTouchEventFilter(int32_t windowId,
+                                                                               OH_NativeWindowManager_TouchEventFilter touchEventFilter)
+{
+    static OhosFunction<WindowManager_ErrorCode(int32_t, OH_NativeWindowManager_TouchEventFilter)> S_OH_NativeWindowManager_RegisterTouchEventFilter("OH_NativeWindowManager_RegisterTouchEventFilter",
+                                                                                                                                                     "libnative_window_manager.so", OK);
+    return S_OH_NativeWindowManager_RegisterTouchEventFilter(windowId, touchEventFilter);
+}
+
+inline int32_t OH_Input_GetMouseEventWindowId(const struct Input_MouseEvent* mouseEvent)
+{
+    static OhosFunction<int32_t(const struct Input_MouseEvent*)> S_OH_Input_GetMouseEventWindowId("OH_Input_GetMouseEventWindowId",
+                                                                                                   "liboh_input.so", 0);
+    return S_OH_Input_GetMouseEventWindowId(mouseEvent);
+}
+
+inline int32_t OH_Input_GetMouseEventDisplayId(const struct Input_MouseEvent* mouseEvent)
+{
+    static OhosFunction<int32_t(const struct Input_MouseEvent*)> S_OH_Input_GetMouseEventDisplayId("OH_Input_GetMouseEventDisplayId",
+                                                                                                   "liboh_input.so", 0);
+    return S_OH_Input_GetMouseEventDisplayId(mouseEvent);
+}
+
+inline int32_t OH_Input_GetTouchEventWindowId(const struct Input_TouchEvent* touchEvent)
+{
+    static OhosFunction<int32_t(const struct Input_TouchEvent*)> S_OH_Input_GetTouchEventWindowId("OH_Input_GetTouchEventWindowId",
+                                                                                                    "liboh_input.so", 0);
+    return S_OH_Input_GetTouchEventWindowId(touchEvent);
+}
+
+inline int32_t OH_Input_GetTouchEventDisplayId(const struct Input_TouchEvent* touchEvent)
+{
+    static OhosFunction<int32_t(const struct Input_TouchEvent*)> S_OH_Input_GetTouchEventDisplayId("OH_Input_GetTouchEventDisplayId",
+                                                                                                   "liboh_input.so", 0);
+    return S_OH_Input_GetTouchEventDisplayId(touchEvent);
+}
+
+inline NativeDisplayManager_ErrorCode OH_NativeDisplayManager_CreateDisplayById(uint32_t displayId,
+                                                                                NativeDisplayManager_DisplayInfo **displayInfo)
+{
+    static OhosFunction<NativeDisplayManager_ErrorCode(uint32_t, NativeDisplayManager_DisplayInfo **)> S_OH_NativeDisplayManager_CreateDisplayById("OH_NativeDisplayManager_CreateDisplayById",
+                                                                                                    "libnative_display_manager.so", DISPLAY_MANAGER_ERROR_NOT_SYSTEM_APP);
+    return S_OH_NativeDisplayManager_CreateDisplayById(displayId, displayInfo);
+}
+
+} // QOhCompatibility
+
+QT_END_NAMESPACE
+
+#endif // QOHCOMPATIBILITY_H
diff --git a/src/plugins/platforms/openharmony/qohdesktopwindow.cpp b/src/plugins/platforms/openharmony/qohdesktopwindow.cpp
new file mode 100644
index 00000000000..a54dbf79cb5
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohdesktopwindow.cpp
@@ -0,0 +1,18 @@
+#include "qohdesktopwindow.h"
+
+QT_BEGIN_NAMESPACE
+
+QOhDesktopWindow::QOhDesktopWindow(QWindow *window)
+    : QPlatformWindow(window)
+{
+
+}
+
+WId QOhDesktopWindow::winId() const
+{
+    static int index = 1;
+    return WId(index++);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohdesktopwindow.h b/src/plugins/platforms/openharmony/qohdesktopwindow.h
new file mode 100644
index 00000000000..78166a0f7a0
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohdesktopwindow.h
@@ -0,0 +1,17 @@
+#ifndef QOHDESKTOPWINDOW_H
+#define QOHDESKTOPWINDOW_H
+
+#include <qpa/qplatformwindow.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOhDesktopWindow : public QPlatformWindow
+{
+public:
+    explicit QOhDesktopWindow(QWindow *window);
+
+    WId winId() const override;
+};
+
+QT_END_NAMESPACE
+#endif // QOHDESKTOPWINDOW_H
diff --git a/src/plugins/platforms/openharmony/qohdisplay.cpp b/src/plugins/platforms/openharmony/qohdisplay.cpp
new file mode 100644
index 00000000000..a8167812436
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohdisplay.cpp
@@ -0,0 +1,395 @@
+#include <QDebug>
+#include <QTimer>
+#include <QJsModule>
+#include <qohutility.h>
+#include <private/qopenharmony_p.h>
+#include <private/qjspromise_p.h>
+#include <window_manager/oh_display_manager.h>
+
+#include "qohdisplay.h"
+#include "qohauxiliary.h"
+#include "qohjsonlistener.h"
+#include "qohdisplaylistener.h"
+
+QT_BEGIN_NAMESPACE
+
+#if OHOS_SDK_VERSION >= 20
+QOhDisplay::QOhDisplay(uint32_t id, QObject *parent)
+    : QObject(parent)
+    , m_availableRect()
+    , m_screen(nullptr)
+    , m_info(nullptr)
+    , m_pos(QPoint(0, 0))
+{
+    NativeDisplayManager_ErrorCode code = OH_NativeDisplayManager_CreateDisplayById(id, &m_info);
+    if (code != DISPLAY_MANAGER_OK || m_info == nullptr) {
+        m_info = nullptr;
+        qWarning() << "create display by id failed: " << code;
+        return;
+    }
+
+    /* FIXME wanghao 如果是折叠态需要加上中轴宽度到B面 */
+    if (m_info->id == 0 && m_info->width == 2472 && m_info->height == 1608) {
+        m_info->height += 80;
+    }
+
+    m_oldScaledDensity = scaledDensity();
+    m_pos = getPosition();
+    m_availableRect = this->getAvailableArea();
+}
+#else
+QOhDisplay::QOhDisplay(uint32_t id, const QPoint &pos, QObject *parent)
+    : QObject(parent)
+    , m_availableRect()
+    , m_screen(nullptr)
+    , m_info(nullptr)
+    , m_pos(pos)
+    , m_display(nullptr)
+    , m_availableAreaChangeListener(nullptr)
+{
+    NativeDisplayManager_ErrorCode code = OH_NativeDisplayManager_CreateDisplayById(id, &m_info);
+    if (code != DISPLAY_MANAGER_OK || m_info == nullptr) {
+        qWarning() << "create display by id failed: " << code;
+        return;
+    }
+
+    /* FIXME wanghao 如果是折叠态需要加上中轴宽度到B面 */
+    if (m_info->id == 0 && m_info->width == 2472 && m_info->height == 1608) {
+        m_info->height += 80;
+    }
+
+    m_oldScaledDensity = scaledDensity();
+
+    // C接口没有监听可用区域变化的接口,使用js对象
+    QtOh::runOnJsUIThreadAndWait([this, id]() {
+        QJsModule display("@ohos.display");
+        Napi::Value value = display.call("getDisplayByIdSync", { Napi::Number::New(display.env(), id) });
+        if (value.IsObject()) {
+            m_display.reset(new QJsObject(value.As<Napi::Object>()));
+        } else {
+            qCritical("cannot get display by %d", id);
+            return;
+        }
+
+        m_availableAreaChangeListener = new QOhJsOnListener(m_display.data(), "availableAreaChange", [this](const Napi::CallbackInfo& info) {
+            Napi::Object rect = info[0].As<Napi::Object>();
+            QRect qtRect = QtOh::jsRect2QRect(rect);
+
+            m_availableRect = qtRect;
+            emit this->availableGeometryChanged();
+        });
+        m_availableAreaChangeListener->on();
+    });
+    m_availableRect = this->getAvailableArea();
+}
+
+#endif
+QOhDisplay::~QOhDisplay()
+{
+#if OHOS_SDK_VERSION < 20
+    if (m_availableAreaChangeListener) {
+        m_availableAreaChangeListener->off();
+        delete m_availableAreaChangeListener;
+    }
+#endif
+
+    if (m_info != nullptr)
+        OH_NativeDisplayManager_DestroyDisplay(m_info);
+}
+
+void QOhDisplay::setScreen(QPlatformScreen *screen)
+{
+    m_screen = screen;
+}
+
+QPlatformScreen *QOhDisplay::screen() const
+{
+    return m_screen;
+}
+
+QPoint QOhDisplay::position() const
+{
+    return m_pos;
+}
+
+void QOhDisplay::setPosition(const QPoint &p)
+{
+    m_pos = p;
+}
+
+void QOhDisplay::setPrimary()
+{
+    m_isPrimary = true;
+}
+
+bool QOhDisplay::isPrimary() const
+{
+    return m_isPrimary;
+}
+
+bool QOhDisplay::isValid() const
+{
+    return m_info != nullptr;
+}
+
+uint32_t QOhDisplay::id() const
+{
+    if (m_info == nullptr)
+        return 0;
+    return m_info->id;
+}
+
+QString QOhDisplay::name() const
+{
+    if (nullptr == m_info)
+        return QString();
+
+    return QString::fromLocal8Bit(m_info->name);
+}
+
+Qt::ScreenOrientation QOhDisplay::orientation() const
+{
+    if (m_info == nullptr)
+        return Qt::LandscapeOrientation;
+    switch (m_info->orientation) {
+    case DISPLAY_MANAGER_PORTRAIT:
+        return Qt::PortraitOrientation;
+        break;
+    case DISPLAY_MANAGER_LANDSCAPE:
+        return Qt::LandscapeOrientation;
+        break;
+    case DISPLAY_MANAGER_PORTRAIT_INVERTED:
+        return Qt::InvertedPortraitOrientation;
+        break;
+    case DISPLAY_MANAGER_LANDSCAPE_INVERTED:
+        return Qt::InvertedLandscapeOrientation;
+        break;
+    default:
+        return Qt::LandscapeOrientation;
+    }
+}
+
+QSize QOhDisplay::size() const
+{
+    if (m_info == nullptr)
+        return QSize();
+    return QSize(m_info->width, m_info->height);
+}
+
+QRect QOhDisplay::geometry() const
+{
+    if (m_info == nullptr)
+        return QRect();
+    return QRect(m_pos, QSize(m_info->width, m_info->height));
+}
+
+QRect QOhDisplay::availableGeometry() const
+{
+    return m_availableRect.translated(m_pos);
+}
+
+QSize QOhDisplay::physicalSize() const
+{
+    if (m_info == nullptr)
+        return QSize();
+    return QSize(m_info->physicalWidth, m_info->physicalHeight);
+}
+
+qreal QOhDisplay::densityPixels() const
+{
+    if (m_info == nullptr)
+        return 0;
+    return m_info->densityPixels;
+}
+
+qreal QOhDisplay::scaledDensity() const
+{
+    if (m_info == nullptr)
+        return 0;
+    return m_info->scaledDensity;
+}
+
+qreal QOhDisplay::oldScaledDensity() const
+{
+    return m_oldScaledDensity;
+}
+
+qreal QOhDisplay::pixelDensity() const
+{
+    if (m_info == nullptr)
+        return 0;
+    return m_info->densityDPI / 160; // 96?
+}
+
+qreal QOhDisplay::densityDPI() const
+{
+    if (m_info == nullptr)
+        return 0;
+    return m_info->densityDPI;
+}
+
+qreal QOhDisplay::xDPI() const
+{
+    if (m_info == nullptr)
+        return 0;
+    return m_info->xDPI;
+}
+
+qreal QOhDisplay::yDPI() const
+{
+    if (m_info == nullptr)
+        return 0;
+    return m_info->yDPI;
+}
+
+int QOhDisplay::refreshRate() const
+{
+    if (m_info == nullptr)
+        return 0;
+    return m_info->refreshRate;
+}
+
+#if OHOS_SDK_VERSION >= 20
+void QOhDisplay::reObtainInfo(uint32_t id)
+{
+    Qt::ScreenOrientation old_orientation = orientation();
+
+    QRect old_geometry = geometry();
+    QSize old_physicalSize = physicalSize();
+    qreal old_scaledDensity = scaledDensity();
+    int old_refreshRate = refreshRate();
+
+    if (m_info != nullptr) {
+        OH_NativeDisplayManager_DestroyDisplay(m_info);
+        m_info = nullptr;
+    }
+
+    NativeDisplayManager_ErrorCode code = OH_NativeDisplayManager_CreateDisplayById(id, &m_info);
+    if (code != DISPLAY_MANAGER_OK || m_info == nullptr) {
+        qWarning() << "create display by id failed: " << code;
+    }
+    m_pos = getPosition();
+
+    if (old_orientation != orientation())
+        emit orientationChanged();
+
+    if (old_refreshRate != refreshRate())
+        emit refreshRateChanged();
+
+    if (physicalSize() != old_physicalSize)
+        emit physicalSizeChanged();
+
+    if (old_geometry != geometry())
+        emit geometryChanged();
+
+    if (!qFuzzyCompare(old_scaledDensity, scaledDensity())) {
+        m_oldScaledDensity = old_scaledDensity;
+        emit scaledDensityChanged();
+    }
+}
+
+QPoint QOhDisplay::getPosition() const
+{
+    if (m_info == nullptr)
+        return QPoint();
+    NativeDisplayManager_SourceMode mode = DISPLAY_SOURCE_MODE_NONE;
+    auto code = OH_NativeDisplayManager_GetDisplaySourceMode(m_info->id, &mode);
+    if (code == DISPLAY_MANAGER_OK) {
+        if ((mode == DISPLAY_SOURCE_MODE_MAIN)
+            || (mode == DISPLAY_SOURCE_MODE_EXTEND)) {
+            int x = 0;
+            int y = 0;
+            OH_NativeDisplayManager_GetDisplayPosition(m_info->id, &x, &y);
+            return QPoint(x, y);
+        }
+    }
+    return QPoint();
+}
+void QOhDisplay::checkAvailableGeometry()
+{
+    QRect old = m_availableRect;
+    m_availableRect = getAvailableArea();
+    if (old != m_availableRect)
+        emit this->availableGeometryChanged();
+}
+#else
+void QOhDisplay::reObtainInfo(uint32_t id, const QPoint &pos)
+{
+    Qt::ScreenOrientation old_orientation = orientation();
+    QRect old_geometry = geometry();
+    QSize old_physicalSize = physicalSize();
+    qreal old_scaledDensity = scaledDensity();
+    int old_refreshRate = refreshRate();
+
+    if (m_info != nullptr) {
+        OH_NativeDisplayManager_DestroyDisplay(m_info);
+        m_info = nullptr;
+    }
+
+    NativeDisplayManager_ErrorCode code = OH_NativeDisplayManager_CreateDisplayById(id, &m_info);
+    if (code != DISPLAY_MANAGER_OK || m_info == nullptr) {
+        qWarning() << "create display by id failed: " << code;
+    }
+    if (m_pos != pos) {
+        m_pos = pos;
+    }
+
+    if (old_orientation != orientation())
+        emit orientationChanged();
+
+    if (old_refreshRate != refreshRate())
+        emit refreshRateChanged();
+
+    if (physicalSize() != old_physicalSize)
+        emit physicalSizeChanged();
+
+    if (old_geometry != geometry())
+        emit geometryChanged();
+
+    if (!qFuzzyCompare(old_scaledDensity, scaledDensity())) {
+        m_oldScaledDensity = old_scaledDensity;
+        emit scaledDensityChanged();
+    }
+}
+#endif
+
+QRect QOhDisplay::getAvailableArea() const
+{
+    QRect area;
+    const QtOh::Utility::DeviceType deviceType = QtOh::Utility::type();
+    if (deviceType == QtOh::Utility::PC || deviceType == QtOh::Utility::Tablet) {
+#if OHOS_SDK_VERSION >= 20
+        NativeDisplayManager_Rect *rawRect = nullptr;
+        NativeDisplayManager_ErrorCode code = OH_NativeDisplayManager_CreateAvailableArea(m_info->id, &rawRect);
+        if (rawRect != nullptr && code == DISPLAY_MANAGER_OK) {
+            area = QRect(rawRect->left, rawRect->top, rawRect->width, rawRect->height);
+            OH_NativeDisplayManager_DestroyAvailableArea(rawRect);
+        }
+#else
+        if (!m_display) {
+            return {};
+        }
+        area = QtOh::runOnJsUIThreadWithPromise<QRect>([this](auto p) {
+            auto result = m_display->call("getAvailableArea");
+            QJsPromise promise(result.As<Napi::Promise>());
+            promise.onThen([p](const Napi::CallbackInfo &info) {
+                       Napi::Object rect = info[0].As<Napi::Object>();
+                       p->set_value(QtOh::jsRect2QRect(rect));
+                   }).onCatch([p](const Napi::CallbackInfo &info) {
+                        int code = info[0].As<Napi::Object>().Get("code").ToNumber();
+                        qWarning() << "getAvailableArea failed: " << code;
+                        p->set_value(QRect());
+                    });
+        });
+        if (area.width() == 0 || area.height() == 0) {
+            area = QRect(0, 0, m_info->width, m_info->height);
+        }
+#endif
+    } else {
+        area = QRect(0, 0, m_info->width, m_info->height);
+    }
+
+    return area;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohdisplay.h b/src/plugins/platforms/openharmony/qohdisplay.h
new file mode 100644
index 00000000000..6d6c8e1f14d
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohdisplay.h
@@ -0,0 +1,84 @@
+#ifndef QOHDISPLAY_H
+#define QOHDISPLAY_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qrect.h>
+#include <window_manager/oh_display_info.h>
+QT_BEGIN_NAMESPACE
+class QPlatformScreen;
+
+#if OHOS_SDK_VERSION >= 20
+#else
+class QJsObject;
+class QOhJsOnListener;
+#endif
+
+class QOhDisplay : public QObject
+{
+    Q_OBJECT
+public:
+#if OHOS_SDK_VERSION >= 20
+    explicit QOhDisplay(uint32_t id, QObject *parent = 0);
+#endif
+    explicit QOhDisplay(uint32_t id, const QPoint &pos, QObject *parent = 0);
+    ~QOhDisplay();
+
+    void setScreen(QPlatformScreen *screen);
+    QPlatformScreen *screen() const;
+
+    QPoint position() const;
+    void setPosition(const QPoint &p);
+    void setPrimary();
+    bool isPrimary() const;
+    bool isValid() const;
+    uint32_t id() const;
+    QString name() const;
+    Qt::ScreenOrientation orientation() const;
+    QSize size() const;
+    QRect geometry() const;
+    QRect availableGeometry() const;
+    QSize physicalSize() const;
+    qreal densityPixels() const;
+    qreal scaledDensity() const;
+    qreal oldScaledDensity() const;
+    qreal pixelDensity() const;
+    qreal densityDPI() const;
+    qreal xDPI() const;
+    qreal yDPI() const;
+    int refreshRate() const;
+#if OHOS_SDK_VERSION >= 20
+    void reObtainInfo(uint32_t id);
+    void checkAvailableGeometry();
+#else
+    void reObtainInfo(uint32_t id, const QPoint &pos);
+#endif
+Q_SIGNALS:
+    void orientationChanged();
+    void geometryChanged();
+    void availableGeometryChanged();
+    void physicalSizeChanged();
+    void densityPixelsChanged();
+    void scaledDensityChanged();
+    void pixelDensityChanged();
+    void refreshRateChanged();
+
+private:
+#if OHOS_SDK_VERSION >= 20
+    QPoint getPosition() const;
+#endif
+    QRect getAvailableArea() const;
+    QRect m_availableRect;
+    QPlatformScreen *m_screen;
+    NativeDisplayManager_DisplayInfo *m_info = nullptr;
+    bool m_isPrimary = false;
+    qreal m_oldScaledDensity = 0;
+    QPoint m_pos;
+#if OHOS_SDK_VERSION < 20
+    QScopedPointer<QJsObject> m_display;
+    QOhJsOnListener *m_availableAreaChangeListener;
+#endif
+};
+
+QT_END_NAMESPACE
+#endif // QOHDISPLAY_H
diff --git a/src/plugins/platforms/openharmony/qohdisplaylistener.cpp b/src/plugins/platforms/openharmony/qohdisplaylistener.cpp
new file mode 100644
index 00000000000..5ae6799dbec
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohdisplaylistener.cpp
@@ -0,0 +1,4 @@
+#include "qohdisplaylistener.h"
+QT_BEGIN_NAMESPACE
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohdisplaylistener.h b/src/plugins/platforms/openharmony/qohdisplaylistener.h
new file mode 100644
index 00000000000..29c5459e9ba
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohdisplaylistener.h
@@ -0,0 +1,50 @@
+#ifndef QOHDISPLAYLISTENER_H
+#define QOHDISPLAYLISTENER_H
+
+#include <QDebug>
+#include <window_manager/oh_display_info.h>
+
+QT_BEGIN_NAMESPACE
+class QOhAbstractDisplayListener
+{
+public:
+    virtual ~QOhAbstractDisplayListener()
+    {
+
+    }
+};
+
+template <typename... Args>
+using ListenerCallback = void(*)(Args...);
+
+template <typename... Args>
+class QOhDisplayListener : public QOhAbstractDisplayListener
+{
+public:
+    QOhDisplayListener(NativeDisplayManager_ErrorCode (*RegisterFunction)(ListenerCallback<Args...>, uint32_t*),
+                       NativeDisplayManager_ErrorCode (*UnregisterFunction)(uint32_t),
+                       ListenerCallback<Args...> callback)
+        : m_unregisterFunction(UnregisterFunction)
+    {
+        NativeDisplayManager_ErrorCode code = RegisterFunction(callback, &m_listenerIndex);
+
+        if (code != DISPLAY_MANAGER_OK) {
+            qWarning() << "registration failed with code:" << code;
+            m_listenerIndex = 0;
+        }
+    }
+
+    ~QOhDisplayListener() {
+        if (m_listenerIndex != 0 && m_unregisterFunction) {
+            m_unregisterFunction(m_listenerIndex);
+            m_listenerIndex = 0;
+        }
+    }
+
+private:
+    uint32_t m_listenerIndex = 0;
+    NativeDisplayManager_ErrorCode (*m_unregisterFunction)(uint32_t);
+};
+
+QT_END_NAMESPACE
+#endif // QOHDISPLAYLISTENER_H
diff --git a/src/plugins/platforms/openharmony/qohdisplaymanager.cpp b/src/plugins/platforms/openharmony/qohdisplaymanager.cpp
new file mode 100644
index 00000000000..6e526702f66
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohdisplaymanager.cpp
@@ -0,0 +1,485 @@
+#include <QDebug>
+#include <QHash>
+#include <QTimer>
+#include <QScopeGuard>
+#include <QRegularExpression>
+#include <QRegularExpressionMatchIterator>
+
+#include <private/qobject_p.h>
+#include <qopenharmonydefines.h>
+#include <private/qopenharmony_p.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <window_manager/oh_display_manager.h>
+
+
+#include "qohmain.h"
+#include "qjsdisplay.h"
+#include "qohdisplay.h"
+#include "qjscontext.h"
+#include "qjssettings.h"
+#include "qohauxiliary.h"
+#include "qohnormalwindow.h"
+#include "qohdisplaymanager.h"
+#include "qohplatformscreen.h"
+#include "qohdisplaylistener.h"
+#include "jsclass/qjscontext.h"
+#include "qohnativewindowmanager.h"
+#include "jsclass/qjswindowstage.h"
+#include "qohplatformopenglwindow.h"
+
+QT_BEGIN_NAMESPACE
+const static QString DisplayPositionKey = "user_set_relative_position";
+
+class QOhDisplayManagerPrivate : public QObjectPrivate
+{
+    Q_DECLARE_PUBLIC(QOhDisplayManager)
+    Q_DISABLE_COPY_MOVE(QOhDisplayManagerPrivate)
+
+public:
+    QOhDisplayManagerPrivate();
+    ~QOhDisplayManagerPrivate();
+
+    static QOhDisplayManagerPrivate* get(QOhDisplayManager*q) {return q->d_func();}
+    static QOhDisplayId displayIdForMainWindow();
+protected:
+    void init();
+    static void displayChangeCallback(QOhDisplayId displayId);
+    void handleDisplayChange(QOhDisplayId displayId);
+    void handleDisplayAdd(QOhDisplayId displayId);
+    void handleDisplayRemove(QOhDisplayId displayId);
+#if OHOS_SDK_VERSION >= 20
+    void handleDisplayAvailableAreaChange(QOhDisplayId displayId);
+#endif
+    static bool isVirtualDisplay(QOhDisplayId displayId) { return displayId >= 1000; }
+    void addDisplay(QOhDisplayId displayId, bool isPrimary);
+
+    static void foldDisplayModeChangeCallback(NativeDisplayManager_FoldDisplayMode displayMode);
+
+#if OHOS_SDK_VERSION < 20
+    QHash<uint64_t, QPoint> getDisplayPosition();
+    QPoint getDisplayPosition(QOhDisplayId displayId) const;
+    void listenDisplayPosition();
+#endif
+
+    class QOhPlatformScreenHolder
+    {
+    public:
+        explicit QOhPlatformScreenHolder(QOhDisplay*display, bool primary = false);
+
+        QOhPlatformScreenHolder(const QOhPlatformScreenHolder &) = delete;
+        QOhPlatformScreenHolder(QOhPlatformScreenHolder &&) = delete;
+        QOhPlatformScreenHolder &operator=(const QOhPlatformScreenHolder &) = delete;
+        QOhPlatformScreenHolder &operator=(QOhPlatformScreenHolder &&) = delete;
+
+        ~QOhPlatformScreenHolder();
+
+        QOhPlatformScreen *platformScreenOrNull() const;
+
+    private:
+        QOhPlatformScreen* m_platformScreen;
+    };
+
+    std::map<QOhDisplayId, std::unique_ptr<QOhPlatformScreenHolder>> m_displays;
+    QList<QOhAbstractDisplayListener *> m_listeners;
+#if OHOS_SDK_VERSION < 20
+    std::shared_ptr<QJsDisplay> m_jsDisplay;
+    QHash<uint64_t, QPoint> m_displayPosition;
+#endif
+};
+
+QOhDisplayManagerPrivate::QOhPlatformScreenHolder::QOhPlatformScreenHolder(QOhDisplay*display, bool primary)
+{
+    auto screen = std::make_unique<QOhPlatformScreen>(display);
+    m_platformScreen = screen.get();
+    QWindowSystemInterface::handleScreenAdded(screen.release(), primary);
+}
+
+QOhDisplayManagerPrivate::QOhPlatformScreenHolder::~QOhPlatformScreenHolder()
+{
+    if (m_platformScreen != nullptr) {
+        QWindowSystemInterface::handleScreenRemoved(m_platformScreen);
+    }
+}
+
+QOhPlatformScreen *QOhDisplayManagerPrivate::QOhPlatformScreenHolder::platformScreenOrNull() const
+{
+    return m_platformScreen;
+}
+
+QOhDisplayManagerPrivate::QOhDisplayManagerPrivate()
+{
+#if OHOS_SDK_VERSION < 20
+    m_jsDisplay = std::make_shared<QJsDisplay>();
+#endif
+}
+
+QOhDisplayManagerPrivate::~QOhDisplayManagerPrivate()
+{
+    qDeleteAll(m_listeners);
+    m_listeners.clear();
+}
+
+QOhDisplayId QOhDisplayManagerPrivate::displayIdForMainWindow()
+{
+    QOhNativeWindowManager *inst = QOhNativeWindowManager::instance();
+    auto ctx = inst->context();
+    if (!ctx || (ctx->contextType() != QJsContext::UIContext)) {
+        return QOhDisplayManager::m_startDisplayId;
+    }
+    auto stage = ctx->windowStage();
+    if (!stage) {
+        return QOhDisplayManager::m_startDisplayId;
+    }
+    return QtOh::runOnJsUIThreadWithResult([ctx]{
+        Napi::Object obj = ctx->windowStage()->call("getMainWindowSync").ToObject();
+        if (obj.IsEmpty())
+            return QOhDisplayManager::m_startDisplayId;
+        auto prop = QOhNormalWindow::getWindowProperties(obj);
+        return QOhDisplayId(prop.displayId());
+    });
+}
+
+void QOhDisplayManagerPrivate::init()
+{
+#if OHOS_SDK_VERSION >= 20
+    m_listeners << new QOhDisplayListener<uint64_t>(OH_NativeDisplayManager_RegisterDisplayChangeListener,
+                                                    OH_NativeDisplayManager_UnregisterDisplayChangeListener,
+                                                    &QOhDisplayManagerPrivate::displayChangeCallback);
+    m_listeners << new QOhDisplayListener<uint64_t>(OH_NativeDisplayManager_RegisterDisplayAddListener,
+                                                    OH_NativeDisplayManager_UnregisterDisplayAddListener,
+                                                    [](uint64_t displayId){
+                                                        if (QOhDisplayManagerPrivate::isVirtualDisplay(displayId)) {
+                                                            return;
+                                                        }
+                                                        auto manager = QOhDisplayManagerPrivate::get(QOhDisplayManager::instance());
+                                                        QtOh::runOnQtMainThread(&QOhDisplayManagerPrivate::handleDisplayAdd, manager, displayId);
+                                                    });
+    m_listeners << new QOhDisplayListener<uint64_t>(OH_NativeDisplayManager_RegisterDisplayRemoveListener,
+                                                    OH_NativeDisplayManager_UnregisterDisplayRemoveListener,
+                                                    [](uint64_t displayId){
+                                                        if (QOhDisplayManagerPrivate::isVirtualDisplay(displayId)) {
+                                                            return;
+                                                        }
+                                                        auto manager = QOhDisplayManagerPrivate::get(QOhDisplayManager::instance());
+                                                        QtOh::runOnQtMainThread(&QOhDisplayManagerPrivate::handleDisplayRemove, manager, displayId);
+                                                    });
+    m_listeners << new QOhDisplayListener<uint64_t>(OH_NativeDisplayManager_RegisterAvailableAreaChangeListener,
+                                                   OH_NativeDisplayManager_UnregisterAvailableAreaChangeListener,
+                                                   [](uint64_t displayId) {
+                                                       auto manager = QOhDisplayManagerPrivate::get(QOhDisplayManager::instance());
+                                                       QtOh::runOnQtMainThread(&QOhDisplayManagerPrivate::handleDisplayAvailableAreaChange, manager, displayId);
+                                                   });
+#else
+    this->m_displayPosition = this->getDisplayPosition();
+    // 监听屏幕相对位置变化
+    this->listenDisplayPosition();
+    // 由于C-API无法监听屏幕添加、移除,所以这里还是借用JS-API
+    QtOh::runOnJsUIThreadAndWait([this]{
+        m_jsDisplay->initialize(QJsDisplay::CreateInfo{
+                                    .displayChangeCb = &QOhDisplayManagerPrivate::displayChangeCallback,
+                                    .displayAddedCb = [this](uint64_t displayId) {
+                                        if (isVirtualDisplay(displayId)) {
+                                            return;
+                                        }
+                                        QtOh::runOnQtMainThread(&QOhDisplayManagerPrivate::handleDisplayAdd, this, displayId);
+                                  },
+                                  .displayRemovedCb = [this](uint64_t displayId) {
+                                      if (isVirtualDisplay(displayId)) {
+                                          return;
+                                      }
+                                      QtOh::runOnQtMainThread(&QOhDisplayManagerPrivate::handleDisplayRemove, this, displayId);
+                                  },
+                              });
+    });
+#endif
+    /* 折叠屏 */
+    if (OH_NativeDisplayManager_IsFoldable()) {
+        m_listeners << new QOhDisplayListener<NativeDisplayManager_FoldDisplayMode>(OH_NativeDisplayManager_RegisterFoldDisplayModeChangeListener,
+                                                                                    OH_NativeDisplayManager_UnregisterFoldDisplayModeChangeListener,
+                                                                                    &QOhDisplayManagerPrivate::foldDisplayModeChangeCallback);
+    }
+}
+
+void QOhDisplayManagerPrivate::handleDisplayChange(QOhDisplayId displayId)
+{
+    Q_Q(QOhDisplayManager);
+    QTimer::singleShot(200, q, [this, displayId]{
+        auto iter = m_displays.find(displayId);
+        if (iter == m_displays.end()) {
+            LOGW("handleDisplayChange cannot find display displayId=%{public}lu.", displayId);
+            return;
+        }
+        LOGI("handleDisplayChange displayId=%{public}lu.", displayId);
+        auto &holder = iter->second;
+        auto *platformScreen = holder->platformScreenOrNull();
+        if (platformScreen) {
+            QOhDisplay *display = platformScreen->display();
+            if (display != nullptr) {
+#if OHOS_SDK_VERSION >= 20
+                display->reObtainInfo(displayId);
+#else
+                QPoint p = getDisplayPosition(displayId);
+                display->reObtainInfo(displayId, p);
+#endif
+            }
+        }
+    });
+}
+
+void QOhDisplayManagerPrivate::handleDisplayAdd(QOhDisplayId displayId)
+{
+    auto iter = m_displays.find(displayId);
+    if (iter != m_displays.end()) {
+        LOGW("handleDisplayAdd duplicated displayId=%{public}lu.", displayId);
+        return;
+    }
+    addDisplay(displayId, false);
+}
+
+void QOhDisplayManagerPrivate::handleDisplayRemove(QOhDisplayId displayId)
+{
+    auto iter = m_displays.find(displayId);
+    if (iter == m_displays.end()) {
+        LOGW("handleDisplayChange cannot find display displayId=%{public}lu.", displayId);
+        return;
+    }
+    m_displays.erase(iter);
+    if (displayId == QOhDisplayManager::m_startDisplayId) {
+        NativeDisplayManager_DisplayInfo *displayInfo = nullptr;
+        if (DISPLAY_MANAGER_OK == OH_NativeDisplayManager_CreatePrimaryDisplay(&displayInfo)) {
+            QOhDisplayManager::m_startDisplayId = displayInfo->id;
+        }
+        if (displayInfo != nullptr) {
+            OH_NativeDisplayManager_DestroyDisplay(displayInfo);
+        }
+    }
+}
+
+#if OHOS_SDK_VERSION >= 20
+void QOhDisplayManagerPrivate::handleDisplayAvailableAreaChange(QOhDisplayId displayId)
+{
+    auto iter = m_displays.find(displayId);
+    if (iter == m_displays.end()) {
+        LOGW("handleDisplayAvailableAreaChange cannot find display displayId=%{public}lu.", displayId);
+        return;
+    }
+    auto &holder = iter->second;
+    auto *platformScreen = holder->platformScreenOrNull();
+    if (platformScreen) {
+        QOhDisplay *display = platformScreen->display();
+        if (display != nullptr) {
+            display->checkAvailableGeometry();
+        }
+    }
+}
+#endif
+
+void QOhDisplayManagerPrivate::addDisplay(QOhDisplayId displayId, bool isPrimary)
+{
+#if OHOS_SDK_VERSION >= 20
+    NativeDisplayManager_SourceMode mode = DISPLAY_SOURCE_MODE_NONE;
+    auto code = OH_NativeDisplayManager_GetDisplaySourceMode(displayId, &mode);
+    QScopedPointer<QOhDisplay> display;
+    if (code == DISPLAY_MANAGER_OK) {
+        if ((mode == DISPLAY_SOURCE_MODE_MAIN)
+            || (mode == DISPLAY_SOURCE_MODE_EXTEND)) {
+            display.reset(new QOhDisplay(displayId));
+        }
+    }
+#else
+    QPoint p = getDisplayPosition(displayId);
+    QScopedPointer<QOhDisplay> display(new QOhDisplay(displayId, p));
+#endif
+    if (display.isNull() || !display->isValid()) {
+        qWarning() << Q_FUNC_INFO << "failed";
+        return;
+    }
+    if (isPrimary) {
+        display->setPrimary();
+    }
+    m_displays.emplace(displayId, std::make_unique<QOhDisplayManagerPrivate::QOhPlatformScreenHolder>(display.take(), isPrimary));
+}
+
+void QOhDisplayManagerPrivate::displayChangeCallback(uint64_t displayId)
+{
+    QtOh::runOnQtMainThread([displayId] {
+        QOhDisplayManagerPrivate *d = QOhDisplayManagerPrivate::get(QOhDisplayManager::instance());
+        d->handleDisplayChange(displayId);
+    });
+}
+
+void QOhDisplayManagerPrivate::foldDisplayModeChangeCallback(NativeDisplayManager_FoldDisplayMode displayMode)
+{
+    // 暂时没什么用,某设备无法触发这个
+    // for (QOhDisplay* display : qAsConst(m_allDisplay)) {
+    //     QtOh::runOnQtMainThread([display] {
+    //         display->reObtainInfo(display->id());
+    //     });
+    // }
+    LOGI("foldDisplayModeChangeCallback mode: [%{public}d]", displayMode);
+}
+
+#if OHOS_SDK_VERSION < 20
+QHash<uint64_t, QPoint> QOhDisplayManagerPrivate::getDisplayPosition()
+{
+    QString positionValue = QJsSettings::instance()->getValueFromUserDomain(DisplayPositionKey);
+    if (positionValue.isEmpty())
+        return {};
+    QRegularExpression regex("\"\\s*(\\d+\\s+\\d+\\s+\\d+)\\s*\"");
+    regex.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
+
+    QRegularExpressionMatchIterator matches = regex.globalMatch(positionValue);
+
+    QHash<uint64_t, QPoint> result;
+    while (matches.hasNext()) {
+        QRegularExpressionMatch match = matches.next();
+        QString numStr = match.captured(1);
+
+        // 使用QString分割数字
+        QStringList parts = numStr.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts);
+        if (parts.size() == 3) {
+            bool ok[3];
+            int displayId = parts[0].toInt(&ok[0]);
+            int posX = parts[1].toInt(&ok[1]);
+            int posY = parts[2].toInt(&ok[2]);
+
+            if (ok[0] && ok[1] && ok[2]) {
+                result.insert(displayId, QPoint(posX, posY));
+            }
+        }
+    }
+    return result;
+}
+
+QPoint QOhDisplayManagerPrivate::getDisplayPosition(QOhDisplayId displayId) const
+{
+    if (m_displayPosition.contains(displayId)) {
+        return m_displayPosition.value(displayId, QPoint());
+    }
+
+    if (isVirtualDisplay(displayId) || displayId == 0) {
+        return QPoint();
+    }
+    // 对于不存在的displayId,尝试通过规则猜测扩展屏幕的位置
+    NativeDisplayManager_DisplayInfo *info = nullptr;
+    auto free = qScopeGuard([&info]() {
+        if (info) {
+            OH_NativeDisplayManager_DestroyDisplay(info);
+        }
+    });
+    NativeDisplayManager_ErrorCode code = OH_NativeDisplayManager_CreateDisplayById(0, &info);
+    if (code == 0) {
+        // 根据0号屏幕的方向,猜测扩展屏幕的位置
+        if (info->orientation == DISPLAY_MANAGER_LANDSCAPE
+            || info->orientation == DISPLAY_MANAGER_LANDSCAPE_INVERTED) {
+            return QPoint(info->width, 0);
+        } else {
+            return QPoint(0, info->height + 80); /* FIXME wanghao 折叠设备中间屏位置的临时处理 */
+        }
+    }
+    return QPoint();
+}
+
+void QOhDisplayManagerPrivate::listenDisplayPosition()
+{
+    QJsSettings::instance()->registerKeyObserver("user_set_relative_position", [this]() {
+        //in js thread
+        QtOh::runOnQtMainThread([this]{
+            this->m_displayPosition = this->getDisplayPosition();
+            // notify display change, refresh all displays
+            // 用户更改配置后,有时候会引发单独一个屏幕变化,有时候会导致所有屏幕变化
+            // 我们可以判断一下具体哪个屏幕的offset变化了
+            for(auto iter = m_displayPosition.begin(); iter != m_displayPosition.end(); iter++) {
+                auto displayId = iter.key();
+                this->handleDisplayChange(displayId);
+            }
+        });
+    });
+}
+#endif
+
+QOhDisplayManager::QOhDisplayManager(QObject *parent)
+    : QObject(*new QOhDisplayManagerPrivate(), parent)
+{
+    m_self = this;
+}
+
+QOhDisplayManager::~QOhDisplayManager()
+{
+    m_self = nullptr;
+}
+
+QOhDisplayManager *QOhDisplayManager::instance()
+{
+    return m_self;
+}
+
+QOhPlatformScreen *QOhDisplayManager::startScreen()
+{
+    return QOhDisplayManager::instance()->platformScreenOrNull(QOhDisplayManager::m_startDisplayId);
+}
+
+void QOhDisplayManager::init()
+{
+    Q_D(QOhDisplayManager);
+    d->init();
+    NativeDisplayManager_DisplaysInfo *all = nullptr;
+    NativeDisplayManager_ErrorCode code = OH_NativeDisplayManager_CreateAllDisplays(&all);
+    if (code != DISPLAY_MANAGER_OK || all == nullptr) {
+        qWarning() << "create all displays failed: " << code;
+        return;
+    }
+
+    auto freeGuard = qScopeGuard([all]() {
+        OH_NativeDisplayManager_DestroyAllDisplays(all);
+    });
+
+    if (all->displaysLength == 0)
+        return;
+
+    // 监听扩展屏相对位置变化
+    uint64_t startId = d->displayIdForMainWindow();
+    m_startDisplayId = startId;
+    qWarning() << Q_FUNC_INFO << "startId" << startId;
+    for (uint32_t i = 0; i < all->displaysLength; ++i) {
+        uint32_t id = all->displaysInfo[i].id;
+        d->addDisplay(id, id == 0);
+    }
+}
+
+QList<QOhPlatformScreen*> QOhDisplayManager::allScreens()
+{
+    Q_D(QOhDisplayManager);
+    QList<QOhPlatformScreen *> screens;
+    for (auto &iter : d->m_displays) {
+        auto &holder = iter.second;
+        QOhPlatformScreen *platformScreen = holder->platformScreenOrNull();
+        if (platformScreen) {
+            screens << platformScreen;
+        }
+    }
+
+    return screens;
+}
+
+QOhPlatformScreen* QOhDisplayManager::platformScreenOrNull(QOhDisplayId displayId) const
+{
+    Q_D(const QOhDisplayManager);
+    auto iter = d->m_displays.find(displayId);
+    return iter == d->m_displays.end() ? nullptr : iter->second->platformScreenOrNull();
+}
+
+QOhPlatformScreen *QOhDisplayManager::screenAt(const QPoint &point)
+{
+    Q_D(QOhDisplayManager);
+    for (auto &iter : d->m_displays) {
+        auto &holder = iter.second;
+        QOhPlatformScreen *platformScreen = holder->platformScreenOrNull();
+        if (platformScreen && platformScreen->geometry().contains(point)) {
+            return platformScreen;
+        }
+    }
+    return nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohdisplaymanager.h b/src/plugins/platforms/openharmony/qohdisplaymanager.h
new file mode 100644
index 00000000000..4f5de4d45cb
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohdisplaymanager.h
@@ -0,0 +1,36 @@
+#ifndef QOHDISPLAYMANAGER_H
+#define QOHDISPLAYMANAGER_H
+
+#include <QtCore/qobject.h>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+class QOhDisplay;
+class QJsDisplay;
+class QOhPlatformScreen;
+class QOhDisplayManagerPrivate;
+typedef uint64_t QOhDisplayId;
+class QOhDisplayManager : public QObject
+{
+    Q_OBJECT
+    Q_DECLARE_PRIVATE(QOhDisplayManager)
+    Q_DISABLE_COPY_MOVE(QOhDisplayManager)
+
+    static inline QOhDisplayManager *m_self = nullptr;
+
+public:
+    explicit QOhDisplayManager(QObject *parent = 0);
+    ~QOhDisplayManager();
+
+    void init();
+    static QOhDisplayManager *instance();
+    static QOhPlatformScreen *startScreen();
+    QList<QOhPlatformScreen*> allScreens();
+    QOhPlatformScreen* platformScreenOrNull(QOhDisplayId) const;
+    QOhPlatformScreen* screenAt(const QPoint &point);
+private:
+    static inline QOhDisplayId m_startDisplayId = 0;
+};
+
+QT_END_NAMESPACE
+#endif // QOHDISPLAYMANAGER_H
diff --git a/src/plugins/platforms/openharmony/qohdrag.cpp b/src/plugins/platforms/openharmony/qohdrag.cpp
new file mode 100644
index 00000000000..51bd8692519
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohdrag.cpp
@@ -0,0 +1,392 @@
+#include "qohdrag.h"
+#include "qohmain.h"
+#include "qohdisplay.h"
+#include "qohauxiliary.h"
+#include "qohdragevent.h"
+#include "qohwindownode.h"
+#include "qohplatformwindow.h"
+#include <QMutex>
+#include <QSemaphore>
+#include <QScreen>
+#include <qopenharmonydefines.h>
+#include <QtGui/qguiapplication.h>
+#include <QtCore/QLoggingCategory>
+#include <private/qhighdpiscaling_p.h>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <QtCore/qmimedata.h>
+#include <QtCore/qscopeguard.h>
+#include <QtGui/qpainter.h>
+#include <multimedia/image_framework/image/pixelmap_native.h>
+#include <QAtomicPointer>
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(ohDnd, "qt.openharmony.dnd")
+
+
+QOhDropTarget::QOhDropTarget(QOhWindowNode *node)
+    : m_node(node)
+{
+
+}
+
+QOhDropTarget::~QOhDropTarget()
+{
+
+}
+
+void QOhDropTarget::handleDragDropEvent(ArkUI_NodeEvent* event)
+{
+    ArkUI_NodeEventType type = OH_ArkUI_NodeEvent_GetEventType(event);
+    switch (type) {
+    case NODE_ON_DRAG_ENTER:
+        handleDragEnter(event);
+        break;
+    case NODE_ON_DRAG_MOVE:
+        handleDrag(event);
+        break;
+    case NODE_ON_DRAG_LEAVE:
+    {
+        QtOh::runOnQtMainThread([this]{
+            if (!QOhWindowNode::nodeDestroyed(m_node)) {
+                auto pw = m_node->platformWindow();
+                if (pw == nullptr)
+                    return;
+                QWindowSystemInterface::handleDrag(pw->window(), nullptr,
+                                                   QPoint(), Qt::IgnoreAction,
+                                                   Qt::NoButton, Qt::NoModifier);
+            }
+        });
+    }
+    break;
+    case NODE_ON_DROP:
+        handleDrop(event);
+        break;
+    default:
+        break;
+    }
+}
+
+QMimeData *QOhDropTarget::dropData()
+{
+    QOhDrag *drag = static_cast<QOhDrag *>(QGuiApplicationPrivate::platformIntegration()->drag());
+    if (drag && drag->dropData())
+        return drag->dropData();
+    return nullptr;
+}
+
+QWindow *QOhDropTarget::window() const
+{
+    auto pw = m_node->platformWindow();
+    if (pw == nullptr)
+        return nullptr;
+    return pw->window();
+}
+
+void QOhDropTarget::handleDrag(ArkUI_NodeEvent* event)
+{
+    ArkUI_DragEvent *drag = OH_ArkUI_NodeEvent_GetDragEvent(event);
+    if (nullptr == drag)
+        return;
+
+    QOhDragEvent dragEvent(drag);
+    auto actions = dragEvent.actions();
+    auto nodePoint = dragEvent.touchPoint();
+    auto keys = dragEvent.keyboardModifiers(); /* Qt 6 only modify */
+
+    QPlatformDragQtResponse dragResponse(false, Qt::IgnoreAction, QRect());
+    QPointer<QWindow> guard = window();
+    QSharedPointer<QEventLoop> loop(new QEventLoop);
+	/* Qt 6 only modify */
+    QtOh::runOnQtMainThread([this, loop, actions, nodePoint, guard, keys, &dragResponse]{
+        if (!QOhWindowNode::nodeDestroyed(m_node) && !guard.isNull())
+            dragResponse = QWindowSystemInterface::handleDrag(guard.data(), dropData(),
+                                                              QHighDpi::fromNativeLocalPosition(nodePoint, guard.data()),
+                                                              actions, Qt::NoButton, keys);
+
+        if (!loop.isNull() && loop->isRunning())
+            QMetaObject::invokeMethod(loop.data(), "quit", Qt::QueuedConnection);
+    });
+    if (QtOh::wait(loop.data(), 500)) {
+        // timeout
+        dragEvent.failed();
+    } else {
+        dragEvent.setSuggestedDropOperation(dragResponse.acceptedAction());
+        dragEvent.setResult(dragResponse.isAccepted());
+    }
+}
+
+void QOhDropTarget::handleDrop(ArkUI_NodeEvent* event)
+{
+    ArkUI_DragEvent *drag = OH_ArkUI_NodeEvent_GetDragEvent(event);
+    if (drag == nullptr) {
+        return;
+    }
+    QOhDragEvent dragEvent(drag);
+    auto actions = dragEvent.actions();
+    auto data = dropData();
+    data->clear();
+    dragEvent.acquireDatas(data);
+    auto nodePoint = dragEvent.touchPoint();
+    auto keys = dragEvent.keyboardModifiers(); /* Qt 6 only modify */
+
+    QPlatformDropQtResponse dropResponse(false, Qt::IgnoreAction);
+    QPointer<QWindow> guard = window();
+    QSharedPointer<QEventLoop> loop(new QEventLoop);
+	/* Qt 6 only modify */
+    QtOh::runOnQtMainThread([this, data, nodePoint, actions, guard, loop, keys, &dropResponse]{
+        if (!QOhWindowNode::nodeDestroyed(m_node) && !guard.isNull())
+            dropResponse = QWindowSystemInterface::handleDrop(guard.data(), data,
+                                                              QHighDpi::fromNativeLocalPosition(nodePoint, guard.data()),
+                                                              actions, Qt::NoButton, keys);
+        if (!loop.isNull() && loop->isRunning())
+            QMetaObject::invokeMethod(loop.data(), "quit", Qt::QueuedConnection);
+    });
+
+    if (QtOh::wait(loop.data(), 500)) {
+        dragEvent.failed();
+    } else {
+        dragEvent.setResult(dropResponse.isAccepted());
+    }
+}
+
+void QOhDropTarget::handleDragEnter(ArkUI_NodeEvent *event)
+{
+    ArkUI_DragEvent *drag = OH_ArkUI_NodeEvent_GetDragEvent(event);
+    if (nullptr == drag)
+        return;
+
+    QOhDragEvent dragEvent(drag);
+
+    auto types = dragEvent.types();
+    auto actions = dragEvent.actions();
+    auto nodePoint = dragEvent.touchPoint();
+    auto keys = dragEvent.keyboardModifiers(); /* Qt 6 only modify */
+
+    QPlatformDragQtResponse dragResponse(false, Qt::IgnoreAction, QRect());
+    QPointer<QWindow> guard = window();
+    QSharedPointer<QEventLoop> loop(new QEventLoop);
+	/* Qt 6 only modify */
+    QtOh::runOnQtMainThread([this, actions, nodePoint,
+                            &dragResponse, types, guard, loop, keys]{
+        if (!QOhWindowNode::nodeDestroyed(m_node) && !guard.isNull()) {
+            auto data = dropData();
+            data->clear();
+            for (int i = 0; i < types.count(); ++i) {
+                data->setData(types.at(i), QByteArray());
+            }
+            dragResponse = QWindowSystemInterface::handleDrag(guard.data(), data,
+                                                              QHighDpi::fromNativeLocalPosition(nodePoint, guard.data()),
+                                                              actions, Qt::NoButton, keys);
+        }
+        if (!loop.isNull() && loop->isRunning())
+            QMetaObject::invokeMethod(loop.data(), "quit", Qt::QueuedConnection);
+    });
+
+
+    if (QtOh::wait(loop.data(), 500)) {
+        dragEvent.failed();
+    } else {
+        dragEvent.setSuggestedDropOperation(dragResponse.acceptedAction());
+        dragEvent.setResult(dragResponse.isAccepted());
+    }
+}
+
+class QOhDragHandler
+{
+public:
+    QAtomicInteger<bool> m_ended;
+    QOhDragHandler(ArkUI_DragAction *dragAction);
+    ~QOhDragHandler();
+    bool setData(QMimeData *dropData);
+    bool createPreview(QDrag *drag);
+    Qt::DropAction startDrag();
+    void setDropResult(Qt::DropAction action);
+    void setSupportedActions(Qt::DropActions actions);
+    static void dragStatusListener(ArkUI_DragAndDropInfo* dragAndDropInfo, void* userData);
+    Qt::DropActions supportedActions() const;
+
+private:
+    ArkUI_DragAction *m_dragAction;            
+    ArkUI_DragPreviewOption *m_previewOption;
+    Qt::DropAction m_action;
+    Qt::DropActions m_supportedActions;
+    QEventLoop m_loop;
+    std::unique_ptr<OH_PixelmapNative, decltype(&::OH_PixelmapNative_Release)> m_preview;
+};
+
+QOhDragHandler::QOhDragHandler(ArkUI_DragAction *dragAction)
+    : m_dragAction(dragAction)
+      , m_preview(nullptr, ::OH_PixelmapNative_Release)
+      , m_previewOption(nullptr)
+      , m_action(Qt::IgnoreAction)
+{    
+    m_ended.storeRelease(false);
+}
+
+QOhDragHandler::~QOhDragHandler()
+{
+    if (m_dragAction != nullptr) {
+        OH_ArkUI_DragAction_UnregisterStatusListener(m_dragAction);
+        OH_ArkUI_DragAction_Dispose(m_dragAction);
+    }
+
+    if (m_previewOption != nullptr) {
+        OH_ArkUI_DragPreviewOption_Dispose(m_previewOption);
+    }
+}
+
+bool QOhDragHandler::setData(QMimeData *dropData)
+{
+    if (m_dragAction == nullptr)
+        return false;
+    OH_UdmfData *data = QtOh::UdmfHelper::makeUdmfDataFromMime(dropData, false);
+    bool result = OH_ArkUI_DragAction_SetData(m_dragAction, data) == ARKUI_ERROR_CODE_NO_ERROR;
+    if (!result)
+        OH_UdmfData_Destroy(data);
+    return result;
+}
+
+Qt::DropAction QOhDragHandler::startDrag()
+{
+    if (m_dragAction == nullptr)
+        return m_action;
+
+    OH_ArkUI_DragAction_RegisterStatusListener(m_dragAction, this, &QOhDragHandler::dragStatusListener);
+    if (OH_ArkUI_StartDrag(m_dragAction) != ARKUI_ERROR_CODE_NO_ERROR)
+        return m_action;
+
+    if (!m_ended.loadAcquire())
+        m_loop.exec();
+
+    return m_action;
+}
+
+void QOhDragHandler::setDropResult(Qt::DropAction action)
+{
+    m_action = action;
+    if (m_loop.isRunning())
+        m_loop.quit();
+
+    m_ended.storeRelease(true);
+}
+
+void QOhDragHandler::setSupportedActions(Qt::DropActions actions)
+{
+    m_supportedActions = actions;
+}
+
+void QOhDragHandler::dragStatusListener(ArkUI_DragAndDropInfo *dragAndDropInfo, void *userData)
+{
+    ArkUI_DragStatus status = OH_ArkUI_DragAndDropInfo_GetDragStatus(dragAndDropInfo);
+    QOhDragHandler *handler = reinterpret_cast<QOhDragHandler *>(userData);
+    Q_ASSERT(handler != nullptr);
+    if (status == ARKUI_DRAG_STATUS_ENDED) {
+        ArkUI_DragEvent *dragEvent = OH_ArkUI_DragAndDropInfo_GetDragEvent(dragAndDropInfo);
+        Qt::DropAction action = Qt::IgnoreAction;
+        if (dragEvent != nullptr) {
+            ArkUI_DragResult result = ARKUI_DRAG_RESULT_CANCELED;
+            OH_ArkUI_DragEvent_GetDragResult(dragEvent, &result);
+            ArkUI_DropOperation operation = ARKUI_DROP_OPERATION_COPY;
+            OH_ArkUI_DragEvent_GetDropOperation(dragEvent, &operation);
+            switch (result) {
+            case ARKUI_DRAG_RESULT_SUCCESSFUL:
+                action = (operation == ARKUI_DROP_OPERATION_COPY) ? Qt::CopyAction : Qt::MoveAction;
+                break;
+            default:
+                break;
+            }
+        }
+
+        handler->setDropResult(action);
+    } else if (status == ARKUI_DRAG_STATUS_STARTED) {
+        ArkUI_DragEvent *dragEvent = OH_ArkUI_DragAndDropInfo_GetDragEvent(dragAndDropInfo);
+        if (dragEvent != nullptr) {
+            ArkUI_DropOperation operation = ARKUI_DROP_OPERATION_COPY;
+            const Qt::DropActions possibleActions = handler->supportedActions();
+            if (possibleActions & Qt::MoveAction)
+                operation = ARKUI_DROP_OPERATION_MOVE;
+            OH_ArkUI_DragEvent_SetSuggestedDropOperation(dragEvent, operation);
+        }
+    }
+}
+
+Qt::DropActions QOhDragHandler::supportedActions() const
+{
+    return m_supportedActions;
+}
+
+#define CHECK_RESULT(result, msg, action) \
+if (!(result)) { \
+            qCWarning(ohDnd) << msg;             \
+            action;                          \
+}
+
+bool QOhDragHandler::createPreview(QDrag *drag)
+{
+    const QPixmap pixmap = drag->pixmap();
+    const bool hasPixmap = !pixmap.isNull();
+    const QPoint hotSpot = drag->hotSpot();
+    OH_ArkUI_DragAction_SetTouchPointX(m_dragAction, qMax(hotSpot.x(), 0));
+    OH_ArkUI_DragAction_SetTouchPointY(m_dragAction, qMax(hotSpot.y(), 0));
+
+    if (hasPixmap) {
+        QImage image = pixmap.toImage();        
+        m_preview = std::unique_ptr<OH_PixelmapNative, decltype(&::OH_PixelmapNative_Release)>
+                (QtOh::UdmfHelper::createNativePixelMapFromQImage(image),
+                 ::OH_PixelmapNative_Release);
+
+        OH_PixelmapNative *pixelmapArray[1]{ m_preview.get() };
+        int32_t result = OH_ArkUI_DragAction_SetPixelMaps(m_dragAction, pixelmapArray, 1);
+
+        CHECK_RESULT(result == ARKUI_ERROR_CODE_NO_ERROR, "create native pixmap failed.", return false);
+    }
+    m_previewOption = OH_ArkUI_CreateDragPreviewOption();
+    bool enabled = QtOh::isEnvironmentVariableIsTrue("QT_ENABLE_DRAG_NUMBADGE", true);
+    // qWarning() << "drag num badge enabled:" << enabled;
+    OH_ArkUI_DragPreviewOption_SetNumberBadgeEnabled(m_previewOption, enabled);
+    OH_ArkUI_DragAction_SetDragPreviewOption(m_dragAction, m_previewOption);
+    return true;
+}
+
+QOhDrag::QOhDrag() = default;
+QOhDrag::~QOhDrag()
+{
+
+}
+
+Qt::DropAction QOhDrag::drag(QDrag *drag)
+{
+    QMimeData *dropData = drag->mimeData();
+    Qt::DropAction dragResult = Qt::IgnoreAction;
+
+    QWindow *focusWindow = QGuiApplication::focusWindow();
+    if (focusWindow == nullptr)
+        return dragResult;
+
+    WindowNode *node = reinterpret_cast<WindowNode *>(focusWindow->winId());
+    CHECK_RESULT(node != nullptr, "get window node failed.", return dragResult);
+
+    ArkUI_DragAction *dragAction = OH_ArkUI_CreateDragActionWithNode(node->node);
+    CHECK_RESULT(dragAction != nullptr, "create drag action failed.", return dragResult);
+    QScopedPointer<QOhDragHandler> dragHandler(new QOhDragHandler(dragAction));
+
+    bool result = dragHandler->setData(dropData);
+    CHECK_RESULT(result, "set drag data failed.", return dragResult);
+    result = dragHandler->createPreview(drag);
+    CHECK_RESULT(result, "create drag preview failed.", return dragResult);
+    dragHandler->setSupportedActions(drag->supportedActions());
+    dragResult = dragHandler->startDrag();
+    return dragResult;
+}
+
+QMimeData *QOhDrag::dropData()
+{
+    if (const QDrag *drag = currentDrag())
+        return drag->mimeData();
+    return &m_mimeData;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/openharmony/qohdrag.h b/src/plugins/platforms/openharmony/qohdrag.h
new file mode 100644
index 00000000000..994cc6279ff
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohdrag.h
@@ -0,0 +1,51 @@
+#ifndef QOHDRAG_H
+#define QOHDRAG_H
+
+#include <QtCore/qhash.h>
+#include <QtGui/qdrag.h>
+#include <QtGui/qpixmap.h>
+#include <QtCore/qmimedata.h>
+#include <qpa/qplatformdrag.h>
+
+struct ArkUI_NodeEvent;
+struct ArkUI_DragAction;
+struct OH_PixelmapNative;
+
+QT_BEGIN_NAMESPACE
+class QOhWindowNode;
+class QMimeData;
+class QOhDropTarget
+{
+public:
+    QOhDropTarget(QOhWindowNode *node);
+    ~QOhDropTarget();
+    void handleDrag(ArkUI_NodeEvent* event);
+    void handleDrop(ArkUI_NodeEvent* event);
+    void handleDragEnter(ArkUI_NodeEvent* event);
+    void handleDragDropEvent(ArkUI_NodeEvent* event);
+    QMimeData *dropData();
+private:
+    QWindow *window() const;
+private:
+    QOhWindowNode *m_node;
+};
+
+class QOhDrag : public QPlatformDrag
+{
+public:
+    QOhDrag();
+    virtual ~QOhDrag();
+
+    void cancelDrag() override { QOhDrag::m_canceled = true; }
+    Qt::DropAction drag(QDrag *drag) override;
+
+    QMimeData *dropData();
+
+private:
+    QMimeData m_mimeData;
+    static inline bool m_canceled = true;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHDRAG_H
diff --git a/src/plugins/platforms/openharmony/qohevent.h b/src/plugins/platforms/openharmony/qohevent.h
new file mode 100644
index 00000000000..a7d4b955e1e
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohevent.h
@@ -0,0 +1,182 @@
+#ifndef QOHEVENT_H
+#define QOHEVENT_H
+
+#include <variant>
+#include <qrect.h>
+#include <qwindow.h>
+#include <qpointer.h>
+#include <QtGui/qpointingdevice.h> /* Qt 6 only modify */
+#include <qpa/qwindowsysteminterface.h>
+#include <ace/xcomponent/native_xcomponent_key_event.h>
+#include <ace/xcomponent/native_interface_xcomponent.h>
+QT_BEGIN_NAMESPACE
+namespace QtOh {
+
+enum EventType {
+    Key,
+    Wheel,
+    Touch,
+    Mouse,
+    Tablet,
+    Gesture,
+    EnterLeave,
+    GeometryChange
+};
+
+class Event
+{
+public:
+    Event(int _type)
+        : type(_type)
+        , timestamp(0)
+        , window(nullptr)
+    {
+
+    }
+    virtual ~Event() {}
+    int type;
+    int64_t timestamp;
+    QPointer<QWindow> window;
+};
+
+class InputEvent : public Event
+{
+public:
+    InputEvent(int _type) : Event(_type) {}
+    int64_t deviceId;
+    Qt::KeyboardModifiers keyboardModifiers;
+};
+
+class KeyEvent : public InputEvent
+{
+public:
+    KeyEvent()
+        : InputEvent(Key) {}
+    OH_NativeXComponent_KeyCode code;
+    OH_NativeXComponent_KeyAction action;
+    OH_NativeXComponent_EventSourceType stype;
+    int64_t timeStamp;
+};
+
+#if OHOS_SDK_VERSION >= 17
+class NewKeyEvent : public InputEvent
+{
+public:
+    NewKeyEvent()
+        : InputEvent(Key) {}
+    int32_t type;
+    int32_t code;
+    QString text;
+};
+#endif
+
+class WheelEvent : public InputEvent
+{
+public:
+    WheelEvent()
+        : InputEvent(Wheel)
+          , local()
+          , global()
+          , toolType(0)
+          , axisAction(0)
+          , scrollStep(1)
+          , sourceType(0)
+          , pinchScale(0.f)
+          , verticalValue(0.f)
+          , horizontalValue(0.f)
+    {
+
+    }
+
+    QPointF local;
+    QPointF global;
+    int32_t toolType;
+    int32_t axisAction; /* since api 15 */
+    int32_t scrollStep; /* since api 17 */
+    int32_t sourceType;
+    float pinchScale;
+    double verticalValue;
+    double horizontalValue;
+};
+
+class TouchEvent : public InputEvent
+{
+public:
+//    struct TouchPoint {
+//        int id;
+//        QPointF pos;
+//        double size;
+//        float force;
+//        QPointF screen;
+//        QPointF global;
+//        int pointState;
+//        bool isPressed;
+//        long long timeStamp;
+//    };
+    TouchEvent() : InputEvent(Touch)
+    , actionType(-1)
+    {
+
+    }
+    int id;
+    int actionType;    
+    QList<QWindowSystemInterface::TouchPoint> touchPoints;
+	/* Qt 6 only modify */
+    QPointingDevice::DeviceType deviceType; 
+    QPointingDevice::PointerType pointerType;
+};
+
+class TabletEvent : public InputEvent
+{
+public:
+    TabletEvent():InputEvent(Tablet){}
+    qreal presure;
+    QPointF global;
+    qint64 uniqueID;
+    int xTilt, yTilt;
+	double rotation;
+    Qt::MouseButton btn;
+    QPointingDevice::PointerType pointerType; /* Qt 6 only modify */
+};
+
+class GestureEvent : public InputEvent
+{
+public:
+    GestureEvent() : InputEvent(Gesture){}
+
+    qreal value;
+    QPointF local;
+    QPointF global;    
+    int32_t sourceType;    
+    Qt::NativeGestureType gestureType;
+};
+
+class GeometryChangeEvent : public Event
+{
+public:
+    GeometryChangeEvent() : Event(GeometryChange) {}
+    QRect rect;
+    int reason;
+};
+
+class EnterLeaveEvent : public Event
+{
+public:
+    EnterLeaveEvent() : Event(EnterLeave) {}
+    bool enter;    
+};
+
+class MouseEvent : public InputEvent
+{
+public:
+    MouseEvent() : InputEvent(Mouse) {}
+    QPointF xcPos;
+    QPointF scPos; /* screenPos */
+    QEvent::Type mouseEventType;
+    Qt::MouseButton mouseButton;
+};
+
+}
+Q_DECLARE_METATYPE(QtOh::KeyEvent)
+QT_END_NAMESPACE
+#endif // QOHEVENT_H
diff --git a/src/plugins/platforms/openharmony/qoheventdispatcher.cpp b/src/plugins/platforms/openharmony/qoheventdispatcher.cpp
new file mode 100644
index 00000000000..1ed23b24031
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qoheventdispatcher.cpp
@@ -0,0 +1,1026 @@
+#include <cmath>
+#include <math.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef QT_NO_EVENTFD
+#  include <sys/eventfd.h>
+#endif
+
+#include <QDebug>
+#include <QGuiApplication>
+#include <QtCore/QWriteLocker> /* Qt 6 only modify */
+#include <qopenharmonydefines.h>
+#include <qpa/qplatformcursor.h>
+#include <private/qhighdpiscaling_p.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <QtGui/private/qpointingdevice_p.h> /* Qt 6 only modify */
+#include "qohkeys.h"
+#include "qohevent.h"
+#include "qopenharmony.h"
+#include "qohplatformtheme.h"
+#include "qohwindowcontext.h"
+#include "qoheventdispatcher.h"
+#include "qohplatformintegration.h"
+#include "qohplatforminputcontext.h"
+#include "qohplatformopenglwindow.h"
+
+#if OHOS_SDK_VERSION >= 17
+#include <arkui/native_key_event.h>
+#endif
+/* Qt 6 only modify */
+using namespace Qt::Literals::StringLiterals;
+
+class QOhPointingDevice : public QPointingDevice
+{
+public:
+    QOhPointingDevice(const QString &name, qint64 systemId, QInputDevice::DeviceType devType,
+                      PointerType pType, Capabilities caps, int maxPoints, int buttonCount,
+                      const QString &seatName = QString(),
+                      QPointingDeviceUniqueId uniqueId = QPointingDeviceUniqueId(),
+                      QObject *parent = nullptr)
+    : QPointingDevice(name, systemId, devType,
+                          pType, caps, maxPoints, buttonCount,
+                          seatName,
+                          uniqueId,
+                          parent)
+          , m_systemId(systemId)
+    {
+
+    }
+    qint64 systemId() const
+    {
+        return m_systemId;
+    }
+
+private:
+    qint64 m_systemId;
+};
+
+QPoint translatePoint(const QPointF &global, QWindow *w)
+{
+    auto pw = w->handle();
+    QPoint local = pw->mapFromGlobal(global.toPoint());
+    return local;
+}
+
+using WheelEvents = QMultiHash<QtOh::EventType, QSharedPointer<QtOh::WheelEvent>>;
+class QOhEventDispatcherPrivate : public QEventDispatcherUNIXPrivate
+{
+    Q_DECLARE_PUBLIC(QOhEventDispatcher)
+    Q_DISABLE_COPY_MOVE(QOhEventDispatcherPrivate)
+
+public:
+    QOhEventDispatcherPrivate(QOhPlatformIntegration * const inte);
+    ~QOhEventDispatcherPrivate();
+
+    void operator()(QSharedPointer<QtOh::WheelEvent> e);
+    void operator()(QSharedPointer<QtOh::TouchEvent> e);
+    void operator()(QSharedPointer<QtOh::MouseEvent> e);
+    void operator()(QSharedPointer<QtOh::TabletEvent> e);
+    void operator()(QSharedPointer<QtOh::GestureEvent> e);
+    void operator()(QSharedPointer<QtOh::EnterLeaveEvent> e);
+    void operator()(QSharedPointer<QtOh::GeometryChangeEvent> e);
+    void operator()(QSharedPointer<QtOh::KeyEvent> e);
+#if OHOS_SDK_VERSION >= 17
+    void operator()(QSharedPointer<QtOh::NewKeyEvent> e);
+#endif
+    void handleKeyEvent(QWindow *window, QEvent::Type type, int32_t code, Qt::KeyboardModifiers mod, bool autorep = false);
+#if OHOS_SDK_VERSION < 18
+    void handleWindowHidden(const QWindow *window);
+#endif
+
+protected:
+    void uniqueGeometryChangeEvent();
+    void wakeUpWheelEvent(QSharedPointer<QtOh::WheelEvent> event);
+    void wakeUpWheelPinch(QSharedPointer<QtOh::WheelEvent> event);
+    void reduceWheelEvent(QSharedPointer<QtOh::WheelEvent> event);
+    void reduceWheelEventImple(QSharedPointer<QtOh::WheelEvent> event);
+    void mouseMove(QSharedPointer<QtOh::MouseEvent> event);
+    void mousePress(QSharedPointer<QtOh::MouseEvent> event);
+    void mouseRelease(QSharedPointer<QtOh::MouseEvent> event);
+
+    void nonClientAreaMouseMove(QSharedPointer<QtOh::MouseEvent> event);
+    void nonClientAreaMousePress(QSharedPointer<QtOh::MouseEvent> event);
+    void nonClientAreaMouseRelease(QSharedPointer<QtOh::MouseEvent> event);
+
+    QPointF getLastTouchPoint(int id) const;
+    void updateLastTouchPoints(int id, const QPointF &point);
+
+    void updateCursorPos(const QPoint &pt);
+private:
+    void removeWheelEvent(QSharedPointer<QtOh::WheelEvent> event);
+    void insertWheelEvent(QSharedPointer<QtOh::WheelEvent> event);
+    void replaceWheelEvent(QSharedPointer<QtOh::WheelEvent> event);
+
+    QSharedPointer<QtOh::WheelEvent> getLastWheelEvent() {
+        QReadLocker locker(&m_lock);
+        auto event = m_WheelEvents.value(QtOh::Wheel, QSharedPointer<QtOh::WheelEvent>());
+        return event;
+    }
+	/* Qt 6 only modify */
+    QSharedPointer<QOhPointingDevice> touchDevice(qint64 systemId, QPointingDevice::DeviceType, QPointingDevice::PointerType pointerType);
+#if QT_CONFIG(tabletevent)
+    QSharedPointer<QPointingDevice> tabletDevice(QPointingDevice::PointerType pointerType) const
+    {
+        for (const auto &d : m_tabletDevices) {
+            if (d->pointerType() == pointerType)
+                return d;
+        }
+        return {};
+    }
+#endif
+private:
+    using Devices = QList<QSharedPointer<QOhPointingDevice>>;
+    Devices m_devices;
+    QList<QSharedPointer<QPointingDevice>> m_tabletDevices;
+
+    int m_timerId;
+    QReadWriteLock m_lock;
+    WheelEvents m_WheelEvents;
+    QHash<int, QPointF> m_lastTouchPoints;
+    QOhPlatformIntegration *const m_inte;
+    static QAtomicPointer<QOhEventDispatcher> m_qinstance;
+    QHash<QWindow*, QSharedPointer<QtOh::GeometryChangeEvent>> m_geometryEvents;
+#if OHOS_SDK_VERSION < 18
+    QSharedPointer<QtOh::MouseEvent> m_button_down;
+#endif
+};
+QAtomicPointer<QOhEventDispatcher> QOhEventDispatcherPrivate::m_qinstance = nullptr;
+
+QOhEventDispatcherPrivate::QOhEventDispatcherPrivate(QOhPlatformIntegration * const inte)
+    : QEventDispatcherUNIXPrivate()
+    , m_timerId(0)
+    , m_inte(inte)
+{
+    Q_ASSERT(nullptr != inte);
+}
+
+QOhEventDispatcherPrivate::~QOhEventDispatcherPrivate()
+{
+    {
+        QWriteLocker locker(&m_lock);
+        m_WheelEvents.clear();
+        m_geometryEvents.clear();
+    }
+}
+
+void QOhEventDispatcherPrivate::operator()(QSharedPointer<QtOh::WheelEvent> e)
+{
+    if (e.isNull() || e->window.isNull())
+        return;
+
+#if OHOS_SDK_VERSION >= 15
+    if (UI_INPUT_EVENT_TOOL_TYPE_MOUSE == e->toolType) {
+        /* 鼠标滚轮操作 */
+        wakeUpWheelEvent(e);
+        return;
+    } else if (UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD == e->toolType) {
+        /* 触控板操作 */
+        if (!qFuzzyIsNull(e->pinchScale)) {
+            /* 触控板捏合处理 */
+            wakeUpWheelPinch(e);
+        } else {
+#endif
+            reduceWheelEvent(e);
+#if OHOS_SDK_VERSION >= 15
+        }
+    }
+#endif
+}
+
+void QOhEventDispatcherPrivate::operator()(QSharedPointer<QtOh::TouchEvent> e)
+{
+    if (e.isNull() || e->window.isNull())
+        return;
+
+	/* Qt 6 only modify */
+    auto dev = touchDevice(e->deviceId, e->deviceType, e->pointerType);
+    QWindow *w = e->window.data();
+    if (UI_TOUCH_EVENT_ACTION_CANCEL == e->actionType) {
+        QWindowSystemInterface::handleTouchCancelEvent(w, dev.data(),
+#if OHOS_SDK_VERSION >= 17
+                                                       e->keyboardModifiers
+#else
+                                                       QOhKeys::keyboardModifiers()
+#endif
+                                                       );
+        updateCursorPos(QPoint());
+        return;
+    }
+
+    QOhPlatformInputContext::ohInputContext()->setRequestKeyboardReason(InputMethod::RequestKeyboardReason::TOUCH);
+
+	/* Qt 6 only modify std::as_const */
+    for (const auto &point : std::as_const(e->touchPoints))
+    {
+        updateCursorPos(point.rawPositions.first().toPoint());
+    }
+
+    /* NOTE 鸿蒙触摸事件源
+     * OH_NATIVEXCOMPONENT_SOURCE_TYPE_UNKNOWN = 0
+     * OH_NATIVEXCOMPONENT_SOURCE_TYPE_MOUSE
+     * OH_NATIVEXCOMPONENT_SOURCE_TYPE_TOUCHSCREEN
+     * OH_NATIVEXCOMPONENT_SOURCE_TYPE_TOUCHPAD,
+     * OH_NATIVEXCOMPONENT_SOURCE_TYPE_JOYSTICK,
+     * OH_NATIVEXCOMPONENT_SOURCE_TYPE_KEYBOARD
+     */
+#if OHOS_SDK_VERSION >= 17
+    Qt::KeyboardModifiers modify = e->keyboardModifiers;
+#else
+    Qt::KeyboardModifiers modify = QOhKeys::keyboardModifiers();
+#endif
+    if (UI_TOUCH_EVENT_ACTION_UP == e->actionType) {
+        /* NOTE 有popup窗口时press事件可能会触发qt额外模拟的press事件
+         * 此时应将系统release事件处理放到模拟的press事件之后,如果直接在ui线程中
+         * 将release事件加入队列会导致release事件直接执行,在模拟的press事件之前
+         */
+        QtOh::runOnQtMainThread([=]{
+            QWindowSystemInterface::handleTouchEvent(w, dev.data(), e->touchPoints, modify); /* Qt 6 only modify */
+        });
+    } else {
+        QWindowSystemInterface::handleTouchEvent(w, dev.data(), e->touchPoints, modify); /* Qt 6 only modify */
+    }
+}
+
+void QOhEventDispatcherPrivate::operator()(QSharedPointer<QtOh::MouseEvent> e)
+{
+    if (e.isNull() || e->window.isNull())
+        return;
+
+    QPoint p = e->scPos.toPoint();
+    updateCursorPos(p);
+    QOhPlatformInputContext::ohInputContext()->setRequestKeyboardReason(InputMethod::RequestKeyboardReason::MOUSE);
+
+    if (e->mouseEventType == QEvent::MouseMove) {
+        mouseMove(e);
+    } else if (e->mouseEventType == QEvent::MouseButtonPress) {
+        mousePress(e);
+    } else if (e->mouseEventType == QEvent::MouseButtonRelease) {
+        /* NOTE 有popup窗口时press事件可能会触发qt额外模拟的press事件
+         *此时应将系统release事件处理放到模拟的press事件之后,如果直接在ui线程中
+         *将release事件加入队列会导致release事件直接执行,在模拟的press事件之前
+         */
+        QtOh::runOnQtMainThread([=, this]{
+            mouseRelease(e);
+        });
+    } else if (e->mouseEventType == QEvent::NonClientAreaMouseMove) {
+        nonClientAreaMouseMove(e);
+    } else if (e->mouseEventType == QEvent::NonClientAreaMouseButtonPress) {
+        nonClientAreaMousePress(e);
+    } else if (e->mouseEventType == QEvent::NonClientAreaMouseButtonRelease) {
+        nonClientAreaMouseRelease(e);
+    }
+}
+
+void QOhEventDispatcherPrivate::operator()(QSharedPointer<QtOh::TabletEvent> e)
+{
+/* Qt 6 only modify */
+#if QT_CONFIG(tabletevent)
+    if (e.isNull() || e->window.isNull())
+        return;
+
+        updateCursorPos(e->global.toPoint());
+    auto device = tabletDevice(e->pointerType);
+    if (device.isNull()) {
+        QInputDevice::Capabilities caps(QInputDevice::Capability::Position
+                                        | QInputDevice::Capability::MouseEmulation
+                                        | QInputDevice::Capability::Hover);
+        caps |= QInputDevice::Capability::Pressure;
+        caps |= QInputDevice::Capability::Rotation;
+        caps |= QInputDevice::Capability::XTilt;
+        caps |= QInputDevice::Capability::YTilt;
+        const qint64 uniqueId = e->deviceId | (qint64(e->pointerType) << 32L);
+        device.reset(new QPointingDevice("ohostablet"_L1,
+                                         e->deviceId, QInputDevice::DeviceType::Stylus,
+                                         e->pointerType, caps, 1, 3, QString(),
+                                         QPointingDeviceUniqueId::fromNumericId(uniqueId)));
+        QWindowSystemInterface::registerInputDevice(device.data());
+        m_tabletDevices.append(device);
+    }
+
+    QWindowSystemInterface::handleTabletEvent(e->window, NSTOMS(e->timestamp), device.data(), translatePoint(e->global, e->window), e->global,
+                                              e->btn, e->presure,
+                                              e->xTilt, e->yTilt, 0, e->rotation, 0,
+#if OHOS_SDK_VERSION >= 17
+                                              e->keyboardModifiers
+#else
+                                              QOhKeys::keyboardModifiers()
+#endif
+                                                                                          );
+#endif
+}
+
+void QOhEventDispatcherPrivate::operator()(QSharedPointer<QtOh::GestureEvent> e)
+{
+    if (e.isNull() || e->window.isNull())
+        return;
+
+    updateCursorPos(QPoint(e->global.x(), e->global.y()));
+
+	/* Qt 6 only modify */
+    auto dev = touchDevice(e->deviceId, QPointingDevice::DeviceType::TouchScreen, QPointingDevice::PointerType::Finger);
+
+    /* NOTE 鸿蒙手势事件源
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    QPointF local = QHighDpi::fromNativeLocalPosition(e->local, e->window.data());
+    QPointF global = QHighDpi::fromNativePixels(e->global, e->window.data());
+    QWindowSystemInterface::handleGestureEventWithRealValue(e->window, NSTOMS(e->timestamp), dev.data(),
+                                                            e->gestureType, e->value, local, global);
+}
+
+void QOhEventDispatcherPrivate::operator()(QSharedPointer<QtOh::EnterLeaveEvent> e)
+{
+    if (!e.isNull() && !e->window.isNull() && e->window->handle()) {
+        if (e->enter) {
+            QWindow *tlw = QOhWindowContext::mouseGrabberWindow();
+            if ((tlw && tlw != e->window) || QOhWindowContext::underMouseWindow() == e->window)
+                return;
+
+            QPoint globalPos, localPos;
+            if (QPlatformScreen *ps = e->window->screen()->handle()) {
+                if (ps->cursor()) {
+                    globalPos = ps->cursor()->pos();
+                    localPos = e->window->handle()->mapFromGlobal(globalPos);
+                }
+            }
+
+            QWindowSystemInterface::handleEnterEvent(e->window, localPos, globalPos);
+            QOhWindowContext::setUnderMouseWindow(e->window);
+        } else {
+            if (QOhWindowContext::underMouseWindow() == e->window) {
+                QOhWindowContext::setUnderMouseWindow(nullptr);
+                QWindowSystemInterface::handleLeaveEvent(e->window);
+            }
+        }
+    }
+}
+
+void QOhEventDispatcherPrivate::operator()(QSharedPointer<QtOh::GeometryChangeEvent> e)
+{
+    if (e.isNull() || e->window.isNull())
+        return;
+    {
+        QWriteLocker locker(&m_lock);
+        m_geometryEvents.insert(e->window, e);
+    }
+}
+
+void QOhEventDispatcherPrivate::operator()(QSharedPointer<QtOh::KeyEvent> e)
+{
+    if (e.isNull() || e->window.isNull())
+        return;
+    QWindow *w = e->window.data();
+    QWindow *keyGrabber = QOhWindowContext::keyGrabberWindow();
+    QWindow *receiver = keyGrabber ? keyGrabber : w;
+    OH_NativeXComponent_KeyCode code = e->code;
+    OH_NativeXComponent_KeyAction action = e->action;
+    OH_NativeXComponent_EventSourceType stype = e->stype;
+    Q_UNUSED(stype);
+
+    QEvent::Type t = (action == OH_NATIVEXCOMPONENT_KEY_ACTION_DOWN) ? QEvent::KeyPress :
+                                                                     ((action == OH_NATIVEXCOMPONENT_KEY_ACTION_UP) ? QEvent::KeyRelease : QEvent::None);
+
+    /* 长按判断
+     * 记录按下的字符,判断字符是否已经按下
+     * 如果字符已经按下则认为是长按状态
+     */
+    bool ar = QOhKeys::autoRepeat(action, code);
+
+    handleKeyEvent(receiver, t, code, QOhKeys::keyboardModifiers(), ar);
+}
+
+void QOhEventDispatcherPrivate::handleKeyEvent(QWindow *window, QEvent::Type type, int32_t code, Qt::KeyboardModifiers mod, bool autorep)
+{
+    if (autorep && type == QEvent::KeyPress) {
+         /* 不重复发送按下的辅助按键 */
+        if (code == KEY_CTRL_LEFT || code == KEY_CTRL_RIGHT
+                || code == KEY_SHIFT_LEFT || code == KEY_SHIFT_RIGHT
+                || code == KEY_ALT_LEFT || code == KEY_ALT_RIGHT)
+            return;
+    }
+
+    auto nativeModifier = mod;
+    int state = 0;
+    state |= (nativeModifier & Qt::ShiftModifier ? int(Qt::ShiftModifier) : 0);
+    state |= (nativeModifier & Qt::ControlModifier ? int(Qt::ControlModifier) : 0);
+    state |= (nativeModifier & Qt::AltModifier ? int(Qt::AltModifier) : 0);
+    state |= (nativeModifier & Qt::MetaModifier ? int(Qt::MetaModifier) : 0);
+
+    if (code == KEY_CTRL_LEFT || code == KEY_CTRL_RIGHT)
+        state = state ^ Qt::ControlModifier;
+    else if (code == KEY_SHIFT_LEFT || code == KEY_SHIFT_RIGHT)
+        state = state ^ Qt::ShiftModifier;
+    else if (code == KEY_ALT_LEFT || code == KEY_ALT_RIGHT)
+        state = state ^ Qt::AltModifier;
+
+    Qt::KeyboardModifiers modifiers(state);
+    if (QOhKeys::isKeypad(code))
+        modifiers |= Qt::KeypadModifier;
+
+    Qt::Key key = QOhKeys::ohCode2QtKey(code, modifiers);
+
+    /* Map SHIFT + Tab to SHIFT + BackTab */
+    if (key == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier)
+        key = Qt::Key_Backtab;
+
+    /* 赋值键盘文本 */
+    QString keyText = QOhKeys::key2String(key, modifiers);
+    QWindowSystemInterface::handleExtendedKeyEvent(window, type, key, modifiers, code, code, nativeModifier, keyText, autorep);
+}
+
+#if OHOS_SDK_VERSION < 18
+/* 处理mousePress事件时关闭窗口系统不会发送mouseRelease事件,在此处补发 */
+void QOhEventDispatcherPrivate::handleWindowHidden(const QWindow *window)
+{
+    QtOh::runOnJsUIThreadNoWait([this, window]{
+        if (m_button_down.isNull() || window != m_button_down->window)
+            return;
+
+        m_button_down->mouseEventType = QEvent::MouseButtonRelease;
+        mouseRelease(m_button_down);
+    });
+}
+#endif
+
+void QOhEventDispatcherPrivate::uniqueGeometryChangeEvent()
+{
+    QHash<QWindow*, QSharedPointer<QtOh::GeometryChangeEvent>> events {};
+    {
+        QWriteLocker locker(&m_lock);
+        events.swap(m_geometryEvents);
+    }
+
+    for (const auto &e : events) {
+        if (e.isNull() || e->window.isNull())
+            continue;
+
+        if (auto *pw = dynamic_cast<QOhPlatformOpenGLWindow *>(e->window->handle())) {
+            pw->setNativeGeometry(e->rect);
+        }
+        QWindowSystemInterface::handleGeometryChange(e->window, e->rect);
+    }
+}
+
+#if OHOS_SDK_VERSION >= 17
+void QOhEventDispatcherPrivate::operator()(QSharedPointer<QtOh::NewKeyEvent> e)
+{
+    if (e.isNull() || e->window.isNull())
+        return;
+    QWindow *w = e->window.data();
+    QWindow *keyGrabber = QOhWindowContext::keyGrabberWindow();
+    QWindow *receiver = keyGrabber ? keyGrabber : w;
+    auto code = e->code;
+
+    QEvent::Type type = QEvent::None;
+    if (e->type == ARKUI_KEY_EVENT_DOWN)
+        type = QEvent::KeyPress;
+    else if (e->type == ARKUI_KEY_EVENT_UP)
+        type = QEvent::KeyRelease;
+
+//    bool autoRepeat = e->type == ARKUI_KEY_EVENT_LONG_PRESS;
+    bool autoRepeat = QOhKeys::autoRepeat(type == QEvent::KeyPress ? 0 : 1, code);
+    
+    handleKeyEvent(receiver, type, code,
+#if OHOS_SDK_VERSION >= 17
+                   e->keyboardModifiers
+#else
+                   QOhKeys::keyboardModifiers()
+#endif
+                   , autoRepeat);
+}
+#endif
+
+#if OHOS_SDK_VERSION >= 15
+static Qt::ScrollPhase ohAxisActionToQtScrollPhase(int32_t action)
+{
+    static QHash<int32_t, Qt::ScrollPhase> convert {
+        { UI_AXIS_EVENT_ACTION_NONE,    Qt::NoScrollPhase },
+        { UI_AXIS_EVENT_ACTION_BEGIN,   Qt::ScrollBegin },
+        { UI_AXIS_EVENT_ACTION_UPDATE,  Qt::ScrollUpdate },
+        { UI_AXIS_EVENT_ACTION_END,     Qt::ScrollEnd },
+        { UI_AXIS_EVENT_ACTION_CANCEL,  Qt::NoScrollPhase}
+    };
+    return convert.value(action, Qt::NoScrollPhase);
+}
+#endif
+
+void QOhEventDispatcherPrivate::wakeUpWheelEvent(QSharedPointer<QtOh::WheelEvent> event)
+{
+    if (event.isNull())
+        return;        
+    updateCursorPos(event->global.toPoint());
+
+    if (nullptr == event->window ||
+        QOhPlatformInputContext::ohInputContext()->ignoreMouse())
+        return;
+
+    QWindow *tlw = QOhWindowContext::mouseGrabberWindow();
+    if (!tlw)
+        tlw = event->window;
+
+    QPlatformScreen *screen = tlw->screen()->handle();
+    QPoint localPos = event->local.toPoint();
+    Qt::KeyboardModifiers mf { Qt::NoModifier };
+#if OHOS_SDK_VERSION >= 15
+    /* 鼠标滚轮回调中 X/Y轴事件中值代表角度
+     * 角度转换为像素值的公式:
+     * px =  (axis_value  / 15 * 21) * scaleDensity = (7 * axis_value * scaleDensity)/5
+     * 1.axis_value 为多模上报角度
+     * 2.单格高度:21 vp  (未加权(权:系统设置中的一次滚几格,此配置已被多模应用,UI框架拿到是加权后的角度))
+     * 3.单格对应角度:15度
+     *
+     * 触控板回调中, X/Y轴事件中值代表像素
+     * 公式通过角度转像素公式反推: axis_value = (px * 5) / (7 * scaleDensity)
+     * 转成Qt中的对应角度:axis_value = (px * 5) / (7 * scaleDensity) * 8
+     * axis_value = (px * 40) / (7 * scaleDensity)
+     */
+    auto [pixelDelta, angleDelta] = [event, screen]()->std::tuple<QPoint, QPoint>{
+        if (UI_INPUT_EVENT_TOOL_TYPE_MOUSE == event->toolType) {
+            constexpr int angleXMin = -120;
+            constexpr int angleXMax = 120;
+            int xAxisValueMultiplier = QtOh::apiVersion() >= 17 ? -8 : -10;
+
+            constexpr int angleYMin = angleXMin;
+            constexpr int angleYMax = angleXMax;
+            int yAxisValueMultiplier = xAxisValueMultiplier;
+
+            int step = QtOh::apiVersion() >= 17 ? event->scrollStep : 1;
+            if (QtOh::apiVersion() >= 17)
+                QOhPlatformTheme::wheelScrollLines = step;
+
+            QPoint angle;
+            angle.setY(qBound(angleYMin, static_cast<int>(event->verticalValue / step * yAxisValueMultiplier), angleYMax));
+            angle.setX(qBound(angleXMin, static_cast<int>(event->horizontalValue / step * xAxisValueMultiplier), angleXMax));
+
+            return std::make_tuple(
+                    QPoint((angle.x() * 7 * QtOh::densityPixels(screen)) / 5 ,
+                           (angle.y() * 7 * QtOh::densityPixels(screen)) / 5),
+
+                    angle
+                    );
+        } else if (UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD == event->toolType) {
+            QPoint pixel(event->horizontalValue, event->verticalValue);
+            /* NOTE 鸿蒙值和Qt相反,乘负数取反 */
+            return std::make_tuple(
+                    pixel,
+                    QPoint((pixel.x() * -1 * 40.f) / (7.f * QtOh::densityPixels(screen)) / 3,
+                           (pixel.y() * -1 * 40.f) / (7.f * QtOh::densityPixels(screen)) / 3)
+                    );
+        }
+        return std::make_tuple(QPoint(), QPoint());
+    }();
+#else
+    float pinchValue = event->pinchScale;
+    bool isScale = !qFuzzyIsNull(pinchValue);
+    QPoint pixelDelta;
+    if(isScale) {
+        mf = Qt::ControlModifier;
+        pixelDelta.setY(pinchValue > 1.0f ? -12 : 12);
+    } else {
+        mf = Qt::NoModifier;
+        pixelDelta.setY(event->verticalValue);
+        pixelDelta.setX(event->horizontalValue);
+    }
+
+    constexpr int angleXMin = -120;
+    constexpr int angleXMax = 120;
+    constexpr int xAxisValueMultiplier = -10;
+
+    constexpr int angleYMin = angleXMin;
+    constexpr int angleYMax = angleXMax;
+    constexpr int yAxisValueMultiplier = xAxisValueMultiplier;
+
+    QPoint angleDelta;
+    angleDelta.setY(qBound(angleYMin, static_cast<int>(pixelDelta.y() * yAxisValueMultiplier), angleYMax));
+    angleDelta.setX(qBound(angleXMin, static_cast<int>(pixelDelta.x() * xAxisValueMultiplier), angleXMax));
+#endif
+
+    /* NOTE QML中 Flickable使用的是毫秒级别计算动画效果
+     * 鸿蒙的时间戳为纳秒级别
+     * 1s【秒】 = 1000ms【毫秒】
+     * 1ms【毫秒】 = 1000μs【微秒】
+    * 1μs【微秒】 = 1000ns【纳秒】
+     * 1ns 【纳秒】 = 1000ps【皮秒】
+     */
+    QWindowSystemInterface::handleWheelEvent(tlw, NSTOMS(event->timestamp),
+                                             localPos, event->global,
+                                             pixelDelta, angleDelta,
+                                             mf | event->keyboardModifiers
+#if OHOS_SDK_VERSION >= 15
+                                             , (UI_INPUT_EVENT_TOOL_TYPE_MOUSE == event->toolType) ? Qt::NoScrollPhase : ohAxisActionToQtScrollPhase(event->axisAction)
+#else
+                                             , Qt::NoScrollPhase
+#endif
+                                             );
+}
+/*!
+ * \brief 处理触控板的捏合缩放处理
+ * \param event 触控板轴事件
+ */
+void QOhEventDispatcherPrivate::wakeUpWheelPinch(QSharedPointer<QtOh::WheelEvent> event)
+{
+#if OHOS_SDK_VERSION >= 15
+    if (event.isNull())
+        return;
+    updateCursorPos(event->global.toPoint());
+
+    if (nullptr == event->window ||
+        QOhPlatformInputContext::ohInputContext()->ignoreMouse())
+        return;
+
+    QWindow *tlw = QOhWindowContext::mouseGrabberWindow();
+    if (!tlw)
+        tlw = event->window;
+
+    // QWindowSystemInterface::handleGestureEventWithRealValue中没有坐标缩放
+    QPoint globalPos = QHighDpi::fromNativePixels(event->global.toPoint(), tlw);
+    QPoint localPos = tlw->mapFromGlobal(globalPos);
+    // QPoint globalPos = QHighDpi::fromNativeLocalPosition(event->global.toPoint(), tlw);
+    // QPoint localPos = tlw->mapFromGlobal(globalPos);
+
+    /* NOTE 鸿蒙手势事件源
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+	 /* Qt 6 only modify */
+    auto dev = touchDevice(event->deviceId, QPointingDevice::DeviceType::TouchScreen, QPointingDevice::PointerType::Finger);
+
+    auto gestureType = [](int actionType) {
+        switch (actionType) {
+        case UI_AXIS_EVENT_ACTION_END:
+        case UI_AXIS_EVENT_ACTION_NONE:
+        case UI_AXIS_EVENT_ACTION_CANCEL:
+            return Qt::EndNativeGesture;
+        case UI_AXIS_EVENT_ACTION_BEGIN:
+            return Qt::BeginNativeGesture;
+        default:
+            break;
+        }
+        return Qt::ZoomNativeGesture;
+    };
+
+    QPointF localF = QPointF(localPos);
+    QPointF globalF = QPointF(globalPos);
+    QWindowSystemInterface::handleGestureEventWithRealValue(tlw, NSTOMS(event->timestamp), dev.data(),
+                                                            gestureType(event->axisAction), event->pinchScale,
+                                                            localF, globalF);
+#endif
+}
+/*!
+ * \brief 压缩合并16毫秒内的触控板轴事件
+ * \param event 触控板轴事件
+ */
+void QOhEventDispatcherPrivate::reduceWheelEvent(QSharedPointer<QtOh::WheelEvent> event)
+{
+#if OHOS_SDK_VERSION >= 15
+    if (QtOh::apiVersion() >= 15) {
+        switch(event->axisAction) {
+        case UI_AXIS_EVENT_ACTION_NONE:
+        case UI_AXIS_EVENT_ACTION_CANCEL:
+        {
+            qWarning("%s the axis event is cancel or abnormal", Q_FUNC_INFO);
+            removeWheelEvent(event);
+        }
+        break;
+        case UI_AXIS_EVENT_ACTION_END: {
+            wakeUpWheelEvent(getLastWheelEvent());
+            wakeUpWheelEvent(event);
+            removeWheelEvent(event);
+        }
+        break;
+        case UI_AXIS_EVENT_ACTION_BEGIN:
+        {
+            wakeUpWheelEvent(event);
+        }
+        break;
+        case UI_AXIS_EVENT_ACTION_UPDATE:
+        {
+            reduceWheelEventImple(event);
+        }
+        break;
+        default: break;
+        }
+    } else {
+        reduceWheelEventImple(event);
+    }
+#else
+    reduceWheelEventImple(event);
+#endif
+}
+
+void QOhEventDispatcherPrivate::reduceWheelEventImple(QSharedPointer<QtOh::WheelEvent> event)
+{
+    auto lastWheel = getLastWheelEvent();
+    if (!lastWheel.isNull()) {
+        qint64 timeDiff = event->timestamp - lastWheel->timestamp;
+        if (MSTONS(16) >= timeDiff) {
+            lastWheel->local = event->local;
+            lastWheel->global = event->global;
+            lastWheel->pinchScale *= event->pinchScale;
+            lastWheel->verticalValue += event->verticalValue;
+            lastWheel->horizontalValue += event->horizontalValue;
+        } else {
+            wakeUpWheelEvent(lastWheel);
+            replaceWheelEvent(event);
+        }
+        return;
+    }
+    wakeUpWheelEvent(lastWheel);
+    replaceWheelEvent(event);
+}
+
+void QOhEventDispatcherPrivate::mouseMove(QSharedPointer<QtOh::MouseEvent> event)
+{
+    QWindow *window = event->window;
+    if (window == nullptr || QOhPlatformInputContext::ohInputContext()->ignoreMouse())
+        return;
+    QWindow *tlw = QOhWindowContext::mouseGrabberWindow();
+    bool windowChanged = (tlw != nullptr && tlw != window);
+    if (!tlw)
+        tlw = window;
+    QPoint _local = event->xcPos.toPoint();
+    const QPointF global = event->scPos;
+    if (windowChanged) {
+        _local = translatePoint(global, tlw);
+    }
+
+    //QOhWindowContext::setUnderMouseWindow(event->window, _local, global.toPoint());
+
+	/* Qt 6 only modify */
+    QWindowSystemInterface::handleMouseEvent(tlw, _local, global.toPoint(), Qt::MouseButtons(event->mouseButton),
+                                             Qt::NoButton, QEvent::MouseMove,
+                                             event->keyboardModifiers);
+}
+
+void QOhEventDispatcherPrivate::mousePress(QSharedPointer<QtOh::MouseEvent> event)
+{
+    QWindow *window = event->window;
+    if (window == nullptr || QOhPlatformInputContext::ohInputContext()->ignoreMouse())
+        return;
+
+    QWindow *grabber = QOhWindowContext::mouseGrabberWindow();
+    QPoint _local = event->xcPos.toPoint();
+    const QPointF global = event->scPos;
+    if (grabber != nullptr && grabber != window) {
+        _local = translatePoint(global, grabber);
+    }
+
+#if OHOS_SDK_VERSION < 18
+    m_button_down = event;
+#endif
+
+    //QOhWindowContext::setUnderMouseWindow(event->window, _local, global.toPoint());
+    QWindowSystemInterface::handleMouseEvent(grabber == nullptr ? window : grabber, _local, global.toPoint(), Qt::MouseButtons(event->mouseButton),
+                                             event->mouseButton, QEvent::MouseButtonPress,
+                                             event->keyboardModifiers);
+}
+
+void QOhEventDispatcherPrivate::mouseRelease(QSharedPointer<QtOh::MouseEvent> event)
+{
+    QWindow *window = event->window;
+    if (window == nullptr || QOhPlatformInputContext::ohInputContext()->ignoreMouse())
+        return;
+
+    QWindow *tlw = QOhWindowContext::mouseGrabberWindow();
+    bool windowChanged = (tlw != nullptr && tlw != window);
+    if (!tlw)
+        tlw = window;
+
+    QPoint _local = event->xcPos.toPoint();
+    const QPointF global = event->scPos;
+    if (windowChanged) {
+        _local = translatePoint(global, tlw);
+    }
+#if OHOS_SDK_VERSION < 18
+    m_button_down.reset();
+#endif
+
+    //QOhWindowContext::setUnderMouseWindow(event->window, _local, global.toPoint());
+    QWindowSystemInterface::handleMouseEvent(tlw, _local, global.toPoint(),
+                                             Qt::NoButton,
+                                             event->mouseButton, QEvent::MouseButtonRelease,
+                                             event->keyboardModifiers);
+
+}
+
+void QOhEventDispatcherPrivate::nonClientAreaMouseMove(QSharedPointer<QtOh::MouseEvent> event)
+{
+    QWindow *window = event->window;
+    if (window == nullptr || QOhPlatformInputContext::ohInputContext()->ignoreMouse())
+        return;
+
+    QWindow *tlw = QOhWindowContext::mouseGrabberWindow();
+    bool windowChanged = (tlw != nullptr && tlw != window);
+    if (!tlw)
+        tlw = window;
+    QPoint _local = event->xcPos.toPoint();
+    const QPointF global = event->scPos;
+    if (windowChanged) {
+        _local = translatePoint(global, tlw);
+    }
+
+	/* Qt 6 only modify */
+    QWindowSystemInterface::handleFrameStrutMouseEvent(tlw, _local, global.toPoint(), Qt::MouseButtons(event->mouseButton),
+                                             Qt::NoButton, QEvent::NonClientAreaMouseMove,
+                                             event->keyboardModifiers);
+}
+
+void QOhEventDispatcherPrivate::nonClientAreaMousePress(QSharedPointer<QtOh::MouseEvent> event)
+{
+    QWindow *window = event->window;
+    if (window == nullptr || QOhPlatformInputContext::ohInputContext()->ignoreMouse())
+        return;
+
+    QWindow *grabber = QOhWindowContext::mouseGrabberWindow();
+    bool windowChanged = (grabber != nullptr && grabber != window);
+    QWindow *send = grabber == nullptr ? window : grabber;
+    QPoint _local = event->xcPos.toPoint();
+    const QPointF global = event->scPos;
+    if (windowChanged) {
+        _local = translatePoint(global, send);
+        QWindowSystemInterface::handleMouseEvent(send, _local, global.toPoint(), Qt::MouseButtons(event->mouseButton),
+                                                           event->mouseButton, QEvent::MouseButtonPress,
+                                                           event->keyboardModifiers);
+        return;
+    }
+	/* Qt 6 only modify */
+    QWindowSystemInterface::handleFrameStrutMouseEvent(send, _local, global.toPoint(), Qt::MouseButtons(event->mouseButton),
+                                             event->mouseButton, QEvent::NonClientAreaMouseButtonPress,
+                                             event->keyboardModifiers);
+}
+
+void QOhEventDispatcherPrivate::nonClientAreaMouseRelease(QSharedPointer<QtOh::MouseEvent> event)
+{
+    QWindow *window = event->window;
+    if (window == nullptr || QOhPlatformInputContext::ohInputContext()->ignoreMouse())
+        return;
+
+    QWindow *tlw = QOhWindowContext::mouseGrabberWindow();
+    bool windowChanged = (tlw != nullptr && tlw != window);
+    if (!tlw)
+        tlw = window;
+    QPoint _local = event->xcPos.toPoint();
+    const QPointF global = event->scPos;
+    if (windowChanged) {
+        _local = translatePoint(global, tlw);
+    }
+	/* Qt 6 only modify */
+    QWindowSystemInterface::handleFrameStrutMouseEvent(tlw, _local, global.toPoint(),
+                                                       Qt::MouseButtons(Qt::NoButton),
+                                                       event->mouseButton, QEvent::NonClientAreaMouseButtonRelease,
+                                                       event->keyboardModifiers);
+}
+
+QPointF QOhEventDispatcherPrivate::getLastTouchPoint(int id) const
+{
+    return m_lastTouchPoints.value(id, QPointF());
+}
+
+void QOhEventDispatcherPrivate::updateLastTouchPoints(int id, const QPointF &point)
+{
+    point.isNull() && m_lastTouchPoints.contains(id) ? void(m_lastTouchPoints.remove(id))
+                                                     : void(m_lastTouchPoints.insert(id, point));
+}
+
+void QOhEventDispatcherPrivate::updateCursorPos(const QPoint &pt)
+{
+    auto screens = QGuiApplication::screens();
+    for (int i = 0; i < screens.count(); ++i) {
+        if (QPlatformCursor *cursor = screens.at(i)->handle()->cursor())
+            cursor->setPos(pt);
+    }
+}
+
+void QOhEventDispatcherPrivate::removeWheelEvent(QSharedPointer<QtOh::WheelEvent> event)
+{
+    if (event) {
+        QWriteLocker locker(&m_lock);
+        m_WheelEvents.remove(QtOh::EventType(event->type));
+    }
+}
+
+void QOhEventDispatcherPrivate::insertWheelEvent(QSharedPointer<QtOh::WheelEvent> event)
+{
+    if (event) {
+        QWriteLocker locker(&m_lock);
+        m_WheelEvents.insert(QtOh::EventType(event->type), event);
+    }
+}
+
+void QOhEventDispatcherPrivate::replaceWheelEvent(QSharedPointer<QtOh::WheelEvent> event)
+{
+    if (event) {
+        QWriteLocker locker(&m_lock);
+        m_WheelEvents.replace(QtOh::EventType(event->type), event);
+    }
+}
+/* Qt 6 only modify */
+QSharedPointer<QOhPointingDevice> QOhEventDispatcherPrivate::touchDevice(qint64 deviceId, QPointingDevice::DeviceType deviceType,
+                                                                         QPointingDevice::PointerType pointerType)
+{
+    for (const auto &d : m_devices) {
+        if (d->systemId() == deviceId && d->type() == deviceType
+            && d->pointerType() == pointerType) {
+            return d;
+        }
+    }
+    QPointingDevice::Capabilities capabilities = QPointingDevice::Capability::Position | QPointingDevice::Capability::Area |
+            QPointingDevice::Capability::NormalizedPosition | QPointingDevice::Capability::Pressure;
+#if 0
+        if (touchDevice->type() == QPointingDevice::DeviceType::TouchPad)
+            capabilities |= QPointingDevice::Capability::MouseEmulation;
+#endif
+    const qint64 uniqueId = deviceId | (qint64(pointerType) << 32L);
+    auto device = QSharedPointer<QOhPointingDevice>::create("ohostouch"_L1,
+                                     deviceId, deviceType,
+                                     pointerType, capabilities, 1, 3, QString(),
+                                     QPointingDeviceUniqueId::fromNumericId(uniqueId));
+    QWindowSystemInterface::registerInputDevice(device.data());
+    m_devices.append(device);
+    return device;
+}
+
+static void launchTimer()
+{
+    /* NOTE 执行逻辑上保证了不需要判断该单例的为空的情况 */
+    QMetaObject::invokeMethod(QOhEventDispatcher::instance(), "launchTimer");
+}
+static constexpr int SC_INTERVAL(15);
+Q_COREAPP_STARTUP_FUNCTION(launchTimer)
+QOhEventDispatcher::QOhEventDispatcher(QOhPlatformIntegration *const inte, QObject *parent)
+    : QEventDispatcherUNIX(*(new QOhEventDispatcherPrivate(inte)), parent)
+{
+    d_func()->m_qinstance.storeRelease(this);
+}
+
+QOhEventDispatcher::~QOhEventDispatcher()
+{
+    Q_D(QOhEventDispatcher);
+    if (d->m_timerId)
+        killTimer(d->m_timerId);
+
+    d->m_qinstance.storeRelease((nullptr));
+}
+
+QOhEventDispatcher *QOhEventDispatcher::instance()
+{
+    return QOhEventDispatcherPrivate::m_qinstance.loadRelaxed();
+}
+
+void QOhEventDispatcher::appendOhEvent(QtOh::EventVar var)
+{
+    Q_D(QOhEventDispatcher);
+    std::visit(*d, var);
+}
+
+void QOhEventDispatcher::updateLastTouchPoints(int id, const QPointF &point)
+{
+    Q_D(QOhEventDispatcher);
+    d->updateLastTouchPoints(id, point);
+}
+
+QPointF QOhEventDispatcher::getLastTouchPoint(int id) const
+{
+    Q_D(const QOhEventDispatcher);
+    return d->getLastTouchPoint(id);
+}
+
+#if OHOS_SDK_VERSION < 18
+void QOhEventDispatcher::handleWindowHidden(const QWindow *window)
+{
+    Q_D(QOhEventDispatcher);
+    d->handleWindowHidden(window);
+}
+#endif
+
+void QOhEventDispatcher::timerEvent(QTimerEvent *event)
+{
+    Q_D(QOhEventDispatcher);
+    if (d->m_timerId == event->timerId()) {
+        d->uniqueGeometryChangeEvent();
+        // killTimer(d->m_timerId);
+        // d->m_timerId = 0;
+    }
+    QEventDispatcherUNIX::timerEvent(event);
+}
+
+bool QOhEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+    const bool didSendEvents = QEventDispatcherUNIX::processEvents(flags);
+    return QWindowSystemInterface::sendWindowSystemEvents(flags) || didSendEvents;
+}
+
+void QOhEventDispatcher::launchTimer()
+{
+    Q_D(QOhEventDispatcher);
+    d->m_timerId = startTimer(SC_INTERVAL);
+}
+
+
+
diff --git a/src/plugins/platforms/openharmony/qoheventdispatcher.h b/src/plugins/platforms/openharmony/qoheventdispatcher.h
new file mode 100644
index 00000000000..955935378e5
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qoheventdispatcher.h
@@ -0,0 +1,75 @@
+#ifndef QOHEVENTDISPATCHER_H
+#define QOHEVENTDISPATCHER_H
+
+#include <QtCore/QMutex>
+#include <QtCore/QQueue>
+#include <qsharedpointer.h>
+#include <QtCore/QSemaphore>
+#include <qpa/qwindowsysteminterface_p.h>
+#include <QtCore/private/qeventdispatcher_unix_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#define MSTONS(x) x*1000000
+#define NSTOMS(x) x/1000000
+
+class QPointingDevice; /* Qt 6 only modify */
+namespace QtOh {
+class Event;
+class WheelEvent;
+class TouchEvent;
+class MouseEvent;
+class TabletEvent;
+class GestureEvent;
+class EnterLeaveEvent;
+class GeometryChangeEvent;
+class KeyEvent;
+#if OHOS_SDK_VERSION >= 17
+class NewKeyEvent;
+#endif
+
+using EventVar = std::variant<QSharedPointer<WheelEvent>,
+                              QSharedPointer<TouchEvent>,
+                              QSharedPointer<MouseEvent>,
+                              QSharedPointer<TabletEvent>,
+                              QSharedPointer<GestureEvent>,
+                              QSharedPointer<EnterLeaveEvent>,
+                              QSharedPointer<GeometryChangeEvent>,
+                              QSharedPointer<KeyEvent>
+                              #if OHOS_SDK_VERSION >= 17
+                              ,QSharedPointer<NewKeyEvent>
+                              #endif
+>;
+}
+QT_END_NAMESPACE
+
+
+class QOhPlatformIntegration;
+class QOhEventDispatcherPrivate;
+class QOhEventDispatcher : public QEventDispatcherUNIX
+{
+    Q_OBJECT
+    Q_DECLARE_PRIVATE(QOhEventDispatcher)
+    Q_DISABLE_COPY_MOVE(QOhEventDispatcher)
+
+public:
+    explicit QOhEventDispatcher(QOhPlatformIntegration * const inte, QObject *parent = nullptr);
+    ~QOhEventDispatcher();
+
+
+    static QOhEventDispatcher *instance();
+    void appendOhEvent(QtOh::EventVar var);    
+    void updateLastTouchPoints(int id, const QPointF &point);
+    QPointF getLastTouchPoint(int id) const;
+#if OHOS_SDK_VERSION < 18
+    void handleWindowHidden(const QWindow *window);
+#endif
+
+protected:
+    void timerEvent(QTimerEvent *event) override;
+    bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
+
+private:
+    Q_INVOKABLE void launchTimer();
+};
+#endif // QOHEVENTDISPATCHER_H
diff --git a/src/plugins/platforms/openharmony/qohextensionwindow.cpp b/src/plugins/platforms/openharmony/qohextensionwindow.cpp
new file mode 100644
index 00000000000..fa66e05c071
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohextensionwindow.cpp
@@ -0,0 +1,137 @@
+#include "qohextensionwindow.h"
+#include "qjsability.h"
+#include "qohevent.h"
+#include "qohauxiliary.h"
+#include "qoheventdispatcher.h"
+#include "qohjsonlistener.h"
+#include "qjsuiextensioncontextsession.h"
+#include "qjsuiextensionability.h"
+#include "qopenharmonydefines.h"
+
+QOhExtensionWindow::QOhExtensionWindow(QOhExtensionWindow *parent)
+    : QOhNativeWindow(parent)
+{
+}
+
+QOhNativeWindow::WindowType QOhExtensionWindow::nativeWindowType() const
+{
+    return QOhNativeWindow::EXTENSION_WINDOW;
+}
+
+QJsAbility *QOhExtensionWindow::ability() const
+{
+    return m_ability;
+}
+
+int32_t QOhExtensionWindow::id() const
+{
+    return 0;
+}
+
+void QOhExtensionWindow::setWindowLimits(WindowLimits &, bool)
+{
+
+}
+
+QOhNativeWindow::WindowLimits QOhExtensionWindow::getWindowLimits()
+{
+    return WindowLimits();
+}
+
+bool QOhExtensionWindow::isFocused()
+{
+    return false;
+}
+
+bool QOhExtensionWindow::setGeometry(const QRect &rect)
+{
+    safeExec([&] {
+        QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance();
+        QSharedPointer<QtOh::GeometryChangeEvent> e(new QtOh::GeometryChangeEvent());
+        e->window = m_window->window();
+        e->rect = rect;
+        dispatcher->appendOhEvent(e);
+    });
+    return true;
+}
+
+QRect QOhExtensionWindow::geometry() const
+{
+    QRect result;
+    if (QtOh::apiVersion() >= 14) {
+        result = safeExec([this]{
+            Napi::Object properties = get("properties").As<Napi::Object>();
+            if (properties.IsObject()) {
+                Napi::Object windowRect = properties.Get("uiExtensionHostWindowProxyRect").As<Napi::Object>();
+                return QtOh::jsRect2QRect(windowRect);
+            }
+            return QRect();
+        });
+    }
+    return result;
+}
+
+QMargins QOhExtensionWindow::frameMargins() const
+{
+    return QMargins();
+}
+
+void QOhExtensionWindow::requestFocus()
+{
+
+}
+
+void QOhExtensionWindow::startListener()
+{
+    safeExec([&] {
+        if (QtOh::apiVersion() >= 14) {
+            auto listener = new QOhJsOnListener(this, "rectChange", [this](const Napi::CallbackInfo &info) {
+                                if (info.Length() < 1 || !info[0].IsObject()) {
+                                    return;
+                                }
+                                Napi::Object RectChangeOptions = info[0].As<Napi::Object>();
+                                Napi::Object rect = RectChangeOptions.Get("rect").As<Napi::Object>();
+                                QRect qtRect = QtOh::jsRect2QRect(rect);
+                                LOGI("rectChange: QRect(%{public}d, %{public}d %{public}dX%{public}d)", qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height());
+                                setGeometry(qtRect);
+            });
+            listener->setExtraArgs(1);
+            m_listeners << listener;
+        } else {
+            m_listeners << new QOhJsOnListener(this, "windowSizeChange",  [this](const Napi::CallbackInfo &info) {
+                if (info.Length() < 1 || !info[0].IsObject()) {
+                    return;
+                }
+                Napi::Object size = info[0].As<Napi::Object>();
+                QRect qtRect(0, 0, size.Get("width").As<Napi::Number>(), size.Get("height").As<Napi::Number>());
+                LOGI("window rect changed: QRect(%{public}d, %{public}d %{public}dX%{public}d)", qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height());
+                // qtRect = qtRect - m;
+                // NOTE:geometry在处理事件时才会更新,此处不应判断
+                if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+                    QSharedPointer<QtOh::GeometryChangeEvent> e(new QtOh::GeometryChangeEvent());
+                    e->window = m_window->window();
+                    e->rect = qtRect;
+                    dispatcher->appendOhEvent(e);
+                }
+            });
+        }
+
+        QOhNativeWindow::startListener();
+    });
+}
+
+bool QOhExtensionWindow::loadContent(const QString &name)
+{
+    QOhNativeWindow::loadContent(name);
+    return safeExec([this](const QString &name){
+        QJsUIExtensionAbility *ability = dynamic_cast<QJsUIExtensionAbility *>(this->ability());
+        if (ability == nullptr)
+            return false;
+        QJsObject store(ability->newLocalStorage().As<Napi::Object>());
+        store.call("setOrCreate", {Napi::String::New(env(), "idName"), Napi::String::New(env(), name.toStdString())});
+        auto session = ability->session();
+        store.call("setOrCreate", "session", session->object());
+        session->call("loadContent", "pages/Index", store.object());
+        return true;
+    }, name);
+}
diff --git a/src/plugins/platforms/openharmony/qohextensionwindow.h b/src/plugins/platforms/openharmony/qohextensionwindow.h
new file mode 100644
index 00000000000..ce7c8f4d798
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohextensionwindow.h
@@ -0,0 +1,36 @@
+#ifndef QOHEXTENSIONWINDOW_H
+#define QOHEXTENSIONWINDOW_H
+
+#include "qohnativewindow.h"
+
+class QOhExtensionWindow : public QOhNativeWindow
+{
+public:
+    QOhExtensionWindow(QOhExtensionWindow *parent = nullptr);
+
+    QOhNativeWindow::WindowType nativeWindowType() const override;
+
+    QJsAbility *ability() const override;
+
+    int32_t id() const override;
+
+    void setWindowLimits(WindowLimits &, bool force = false) override;
+
+    WindowLimits getWindowLimits() override;
+
+    bool isFocused() override;
+
+    bool setGeometry(const QRect &rectIn) override;
+
+    QRect geometry() const override;
+
+    QMargins frameMargins() const override;
+
+    void requestFocus() override;
+
+    void startListener() override;
+
+    virtual bool loadContent(const QString &name) override;
+};
+
+#endif // QOHEXTENSIONWINDOW_H
diff --git a/src/plugins/platforms/openharmony/qohfileenginehandler.cpp b/src/plugins/platforms/openharmony/qohfileenginehandler.cpp
new file mode 100644
index 00000000000..c713093c9bf
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohfileenginehandler.cpp
@@ -0,0 +1,448 @@
+#include <QString>
+#include <QByteArray>
+#include <QSharedPointer>
+#include <rawfile/raw_dir.h>
+#include <rawfile/raw_file.h>
+#include <rawfile/raw_file_manager.h>
+#include "qohnativewindowmanager.h"
+#include "qohfileenginehandler.h"
+
+
+QT_BEGIN_NAMESPACE
+typedef QVector<QString> FilesList;
+
+static const QLatin1String rawfilePrefix("rawfile:");
+const static int prefixSize = 8;
+
+static inline QString cleanRawFilePath(QString file)
+{
+    if (file.startsWith(rawfilePrefix))
+        file.remove(0, prefixSize);
+    file.replace(QLatin1String("//"), QLatin1String("/"));
+    if (file.startsWith(QLatin1Char('/')) || file.startsWith('\\'))
+        file.remove(0, 1);
+    if (file.endsWith(QLatin1Char('/')))
+        file.chop(1);
+    return file;
+}
+
+static inline QString prefixedPath(QString path)
+{
+    path = rawfilePrefix + QLatin1Char('/') + path;
+    path.replace(QLatin1String("//"), QLatin1String("/"));
+    return path;
+}
+
+struct RawFileItem {
+    enum class Type {
+        File,
+        Folder,
+        Invalid
+    };
+    RawFileItem() = default;
+    RawFileItem (const QString &rawName)
+        : name(rawName)
+    {
+        if (name.endsWith(QLatin1Char('/'))) {
+            type = Type::Folder;
+            name.chop(1);
+        }
+    }
+    Type type = Type::File;
+    QString name;
+    qint64 size = -1;
+};
+
+using RawFileItemList = QVector<RawFileItem>;
+
+class FolderIterator : public RawFileItemList
+{
+public:
+    static QSharedPointer<FolderIterator> fromCache(const QString &path, bool clone)
+    {
+        QMutexLocker lock(&m_rawFileCacheMutex);
+        QSharedPointer<FolderIterator> *folder = m_rawFilesCache.object(path);
+        if (!folder) {
+            folder = new QSharedPointer<FolderIterator>{new FolderIterator{path}};
+            if ((*folder)->empty() || !m_rawFilesCache.insert(path, folder)) {
+                QSharedPointer<FolderIterator> res = *folder;
+                delete folder;
+                return res;
+            }
+        }
+        return clone ? QSharedPointer<FolderIterator>{new FolderIterator{*(*folder)}} : *folder;
+    }
+
+    static RawFileItem::Type fileType(const QString &filePath)
+    {
+        if (filePath.isEmpty())
+            return RawFileItem::Type::Folder;
+        const QStringList paths = filePath.split(QLatin1Char('/'));
+        QString fullPath;
+        RawFileItem::Type res = RawFileItem::Type::Invalid;
+        for (const auto &path: paths) {
+            auto folder = fromCache(fullPath, false);
+            auto it = std::lower_bound(folder->begin(), folder->end(), RawFileItem{path}, [](const RawFileItem &val, const RawFileItem &RawFileItem) {
+                return val.name < RawFileItem.name;
+            });
+            if (it == folder->end() || it->name != path)
+                return RawFileItem::Type::Invalid;
+            if (!fullPath.isEmpty())
+                fullPath.append(QLatin1Char('/'));
+            fullPath += path;
+            res = it->type;
+        }
+        return res;
+    }
+
+    FolderIterator(const FolderIterator &other)
+        : RawFileItemList(other)
+          , m_index(-1)
+          , m_path(other.m_path)
+    {}
+
+    FolderIterator(const QString &path)
+        : m_path(path)
+    {
+        QByteArray fileNameByte = path.toUtf8();
+        auto *rawfileDir = OH_ResourceManager_OpenRawDir(qNativeWindowManager->resourceManager(), fileNameByte.constData());
+        if (rawfileDir) {
+            int count = OH_ResourceManager_GetRawFileCount(rawfileDir);
+            for (int i = 0; i < count; ++i) {
+                const char *fileName = OH_ResourceManager_GetRawFileName(rawfileDir, i);
+                RawFileItem item{QString::fromUtf8(fileName)};
+                insert(std::upper_bound(begin(), end(), item, [](const auto &a, const auto &b){
+                           return a.name < b.name;
+                       }), item);
+            }
+            OH_ResourceManager_CloseRawDir(rawfileDir);
+        }
+        m_path = rawfilePrefix + QLatin1Char('/') + m_path + QLatin1Char('/');
+        m_path.replace(QLatin1String("//"), QLatin1String("/"));
+    }
+
+    QString currentFileName() const
+    {
+        if (m_index < 0 || m_index >= size())
+            return {};
+        return at(m_index).name;
+    }
+    QString currentFilePath() const
+    {
+        if (m_index < 0 || m_index >= size())
+            return {};
+        return m_path + at(m_index).name;
+    }
+
+    bool hasNext() const
+    {
+        return !empty() && m_index + 1 < size();
+    }
+
+    std::optional<std::pair<QString, RawFileItem>> next()
+    {
+        if (!hasNext())
+            return {};
+        ++m_index;
+        return std::pair<QString, RawFileItem>(currentFileName(), at(m_index));
+    }
+
+private:
+    int m_index = -1;
+    QString m_path;
+    static QCache<QString, QSharedPointer<FolderIterator>> m_rawFilesCache;
+    static QMutex m_rawFileCacheMutex;
+};
+
+QCache<QString, QSharedPointer<FolderIterator>> FolderIterator::m_rawFilesCache(50);
+QMutex FolderIterator::m_rawFileCacheMutex;
+
+class QOhAbstractFileEngineIterator: public QAbstractFileEngineIterator
+{
+public:
+    QOhAbstractFileEngineIterator(QDir::Filters filters,
+                                      const QStringList &nameFilters,
+                                      const QString &path)
+        : QAbstractFileEngineIterator(filters, nameFilters)
+    {
+        m_currentIterator = FolderIterator::fromCache(cleanRawFilePath(path), true);
+    }
+
+    QFileInfo currentFileInfo() const override
+    {
+        return QFileInfo(currentFilePath());
+    }
+
+    QString currentFileName() const override
+    {
+        if (!m_currentIterator)
+            return {};
+        return m_currentIterator->currentFileName();
+    }
+
+    virtual QString currentFilePath() const
+    {
+        if (!m_currentIterator)
+            return {};
+        return m_currentIterator->currentFilePath();
+    }
+
+    bool hasNext() const override
+    {
+        if (!m_currentIterator)
+            return false;
+        return m_currentIterator->hasNext();
+    }
+
+    QString next() override
+    {
+        if (!m_currentIterator)
+            return {};
+        auto res = m_currentIterator->next();
+        if (!res)
+            return {};
+        return res->first;
+    }
+
+private:
+    QSharedPointer<FolderIterator> m_currentIterator;
+};
+
+class QOhRawfileEngine: public QAbstractFileEngine
+{
+public:
+   explicit QOhRawfileEngine(const QString &fileName)
+        : m_file(nullptr)
+    {
+        setFileName(fileName);
+    }
+
+    ~QOhRawfileEngine()
+    {
+        close();
+    }
+
+    bool open(QIODevice::OpenMode openMode, std::optional<QFile::Permissions> permissions = std::nullopt) override
+    {
+        if (!m_rawFile || m_rawFile->type != RawFileItem::Type::File || (openMode & QIODevice::WriteOnly))
+            return false;
+        close();
+        QByteArray fileNameByte = m_fileName.toUtf8();
+        m_file = OH_ResourceManager_OpenRawFile64(qNativeWindowManager->resourceManager(), fileNameByte.constData());
+        return m_file != nullptr;
+    }
+
+    virtual int handle() const override
+    {
+        if (m_file) {
+            RawFileDescriptor64 desc;
+            if (OH_ResourceManager_GetRawFileDescriptor64(m_file, &desc)) {
+                int result = desc.fd;
+                OH_ResourceManager_ReleaseRawFileDescriptor64(&desc);
+                return result;
+            }
+        }
+        return -1;
+    }
+
+    bool close() override
+    {
+        if (m_file) {
+            OH_ResourceManager_CloseRawFile64(m_file);
+            m_file = 0;
+            return true;
+        }
+        return false;
+    }
+
+    qint64 size() const override
+    {
+        if (m_rawFile)
+            return m_rawFile->size;
+        return -1;
+    }
+
+    qint64 pos() const override
+    {
+        if (m_file)
+            return OH_ResourceManager_GetRawFileOffset64(m_file);
+        return -1;
+    }
+
+    bool seek(qint64 pos) override
+    {
+        if (m_file)
+            return 0 == OH_ResourceManager_SeekRawFile64(m_file, pos, 0);
+        return false;
+    }
+
+    qint64 read(char *data, qint64 maxlen) override
+    {
+        if (m_file)
+            return OH_ResourceManager_ReadRawFile64(m_file, data, maxlen);
+        return -1;
+    }
+
+    bool isSequential() const override
+    {
+        return false;
+    }
+
+    bool caseSensitive() const override
+    {
+        return true;
+    }
+
+    bool isRelativePath() const override
+    {
+        return false;
+    }
+
+    FileFlags fileFlags(FileFlags type = FileInfoAll) const override
+    {
+        FileFlags commonFlags(ReadOwnerPerm|ReadUserPerm|ReadGroupPerm|ReadOtherPerm|ExistsFlag);
+        FileFlags flags;
+        if (m_rawFile) {
+            if (m_rawFile->type == RawFileItem::Type::File)
+                flags = FileType | commonFlags;
+            else if (m_rawFile->type == RawFileItem::Type::Folder)
+                flags = DirectoryType | commonFlags;
+        }
+        return type & flags;
+    }
+
+    QString fileName(FileName file = DefaultName) const override
+    {
+        int pos;
+        switch (file) {
+        case DefaultName:
+        case AbsoluteName:
+        case CanonicalName:
+            return prefixedPath(m_fileName);
+        case BaseName:
+            if ((pos = m_fileName.lastIndexOf(QChar(QLatin1Char('/')))) != -1)
+                return prefixedPath(m_fileName.mid(pos));
+            else
+                return prefixedPath(m_fileName);
+        case PathName:
+        case AbsolutePathName:
+        case CanonicalPathName:
+            if ((pos = m_fileName.lastIndexOf(QChar(QLatin1Char('/')))) != -1)
+                return prefixedPath(m_fileName.left(pos));
+            else
+                return prefixedPath(m_fileName);
+        default:
+            return QString();
+        }
+    }
+
+    void setFileName(const QString &file) override
+    {
+        if (m_fileName == cleanRawFilePath(file))
+            return;
+        close();
+        m_fileName = cleanRawFilePath(file);
+
+        {
+            QMutexLocker lock(&m_rawFileCacheMutex);
+            QSharedPointer<RawFileItem> *rawFilePtr = m_rawFileCache.object(m_fileName);
+            if (rawFilePtr && (*rawFilePtr)->type != RawFileItem::Type::Invalid) {
+                m_rawFile = *rawFilePtr;
+                return;
+            }
+        }
+        QSharedPointer<RawFileItem> *newRawfilePtr = new QSharedPointer<RawFileItem>(new RawFileItem);
+
+        m_rawFile = *newRawfilePtr;
+        m_rawFile->name = m_fileName;
+        m_rawFile->type = RawFileItem::Type::Invalid;
+
+        QByteArray fileNameByte = m_fileName.toUtf8();
+        bool isDir = m_fileName.isEmpty() || OH_ResourceManager_IsRawDir(qNativeWindowManager->resourceManager(), fileNameByte.constData());
+
+        if (!isDir) {
+            m_file = OH_ResourceManager_OpenRawFile64(qNativeWindowManager->resourceManager(), fileNameByte.constData());
+            if (m_file != nullptr) {
+                m_rawFile->type = RawFileItem::Type::File;
+                m_rawFile->size = OH_ResourceManager_GetRawFileSize64(m_file);
+            }
+        } else {
+            auto *rawfileDir = OH_ResourceManager_OpenRawDir(qNativeWindowManager->resourceManager(), fileNameByte.constData());
+            if (rawfileDir) {
+                m_rawFile->type = RawFileItem::Type::Folder;
+                OH_ResourceManager_CloseRawDir(rawfileDir);
+            }
+        }
+        if (m_rawFile->type != RawFileItem::Type::Invalid) {
+            QMutexLocker lock(&m_rawFileCacheMutex);
+            m_rawFileCache.insert(m_fileName, newRawfilePtr);
+        }
+    }
+
+    Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override
+    {
+        if (m_rawFile && m_rawFile->type == RawFileItem::Type::Folder)
+            return new QOhAbstractFileEngineIterator(filters, filterNames, m_fileName);
+        return nullptr;
+    }
+private:
+    RawFile64 *m_file;
+    QString m_fileName = QLatin1String(".");
+    QSharedPointer<RawFileItem> m_rawFile;
+
+    static QCache<QString, QSharedPointer<RawFileItem>> m_rawFileCache;
+    static QMutex m_rawFileCacheMutex;
+};
+
+QCache<QString, QSharedPointer<RawFileItem>> QOhRawfileEngine::m_rawFileCache(200);
+QMutex QOhRawfileEngine::m_rawFileCacheMutex;
+
+
+QOhFileEngineHandler::QOhFileEngineHandler()
+{
+
+}
+
+QAbstractFileEngine *QOhFileEngineHandler::create(const QString &fileName) const
+{
+    if (fileName.isEmpty())
+        return 0;
+    if (!fileName.startsWith(rawfilePrefix))
+        return 0;
+
+    QString _fileName = cleanRawFilePath(fileName);
+    return new QOhRawfileEngine(_fileName);
+//    if (byteArray.isEmpty() && OH_ResourceManager_IsRawDir(qNativeWindowManager->resourceManager(), byteArray.constData())) {
+//        return new QOhRawfileEngine(fileName);
+
+//        ) {
+//        /* 处理目录 */
+//        m_rawfileCacheMutext.lock();
+//        QSharedPointer<QOhRawDir> *ohrd = m_rawDirCache.object(_fileName.toLatin1());
+//        m_rawfileCacheMutext.unlock();
+
+//        if (!ohrd) {
+//            if (!m_hasPrepopulatedCache) {
+//                RawDir *rd = OH_ResourceManager_OpenRawDir(qNativeWindowManager->resourceManager(), byteArray.constData());
+//                if (rd) {
+//                    ohrd = new QSharedPointer<QOhRawDir>(new QOhRawDir(rd));
+//                    m_rawfileCacheMutext.lock();
+//                    m_rawDirCache.insert(_fileName.toLatin1(), ohrd);
+//                    m_rawfileCacheMutext.unlock();
+
+//                }
+//            }
+//        } else {
+//            return new QOhRawfileEngine(*ohrd, fileName);
+//        }
+//    } else {
+//        /* 处理文件 */
+//        RawFile *file = OH_ResourceManager_OpenRawFile(qNativeWindowManager->resourceManager(), byteArray.constData());
+//        if (file != nullptr) {
+
+//        }
+//    }
+//    return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohfileenginehandler.h b/src/plugins/platforms/openharmony/qohfileenginehandler.h
new file mode 100644
index 00000000000..81e38809793
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohfileenginehandler.h
@@ -0,0 +1,22 @@
+#ifndef QOHFILEENGINEHANDLER_H
+#define QOHFILEENGINEHANDLER_H
+
+#include <QtCore/private/qabstractfileengine_p.h>
+#include <QString>
+#include <QCache>
+#include <QMutex>
+#include <QSharedPointer>
+
+QT_BEGIN_NAMESPACE
+struct QOhRawDir;
+class QOhFileEngineHandler : public QAbstractFileEngineHandler
+{
+public:
+    QOhFileEngineHandler();
+    virtual QAbstractFileEngine *create(const QString &fileName) const override;
+private:
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHFILEENGINEHANDLER_H
diff --git a/src/plugins/platforms/openharmony/qohgesturemanager.cpp b/src/plugins/platforms/openharmony/qohgesturemanager.cpp
new file mode 100644
index 00000000000..e2472640144
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohgesturemanager.cpp
@@ -0,0 +1,430 @@
+#include "qohevent.h"
+#include "qohgesturemanager.h"
+#include "qoheventdispatcher.h"
+#include <qopenharmonydefines.h>
+#include <arkui/native_interface.h>
+
+#include "qohkeys.h"
+#include "qohdisplaymanager.h"
+#include "qohplatformscreen.h"
+#include "qohplatforminputcontext.h"
+
+QT_BEGIN_NAMESPACE
+
+QOhGestureManager::QOhGestureManager()
+{
+
+}
+
+void QOhGestureManager::createGestureRecognizerForNode(ArkUI_NodeHandle node)
+{
+    auto gestureApi = reinterpret_cast<ArkUI_NativeGestureAPI_1 *>(
+            OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_GESTURE, "ArkUI_NativeGestureAPI_1"));
+    /* 创建手势组 */
+    auto groupGesture = gestureApi->createGroupGesture(ArkUI_GroupGestureMode::PARALLEL_GROUP);
+
+    /* 创建拖动手势 */
+    auto panGesture = gestureApi->createPanGesture(1, GESTURE_DIRECTION_ALL, 5);
+    int32_t result = gestureApi->setGestureEventTarget(panGesture,
+                                                       GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE |
+                                                       GESTURE_EVENT_ACTION_END | GESTURE_EVENT_ACTION_CANCEL,
+                                                       this, QOhGestureManager::handlePanGestureEvent);
+
+    if (0 != result)
+        LOGE("set panGesture Target Failed.");
+
+    /* 创建捏合手势 */
+    auto pinchGesture = gestureApi->createPinchGesture(2, 0);
+    result = gestureApi->setGestureEventTarget(pinchGesture,
+                                               GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE |
+                                               GESTURE_EVENT_ACTION_END | GESTURE_EVENT_ACTION_CANCEL,
+                                               this, QOhGestureManager::handlePinchGestureEvent);
+    if (0 != result)
+        LOGE("set pinchGesture Target Failed.");
+
+    /* 创建滑动手势 */
+    auto swipeGesture = gestureApi->createSwipeGesture(1, GESTURE_DIRECTION_ALL, 0);
+    result = gestureApi->setGestureEventTarget(swipeGesture,
+                                               GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE |
+                                               GESTURE_EVENT_ACTION_END | GESTURE_EVENT_ACTION_CANCEL,
+                                               this, QOhGestureManager::handleSwipeGestureEvent);
+    if (0 != result)
+        LOGE("set swipeGesture Target Failed.");
+
+    /* 创建旋转手势 */
+    auto rotationGesture = gestureApi->createRotationGesture(2, 0);
+    result = gestureApi->setGestureEventTarget(rotationGesture,
+                                               GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE |
+                                               GESTURE_EVENT_ACTION_END | GESTURE_EVENT_ACTION_CANCEL,
+                                               this, QOhGestureManager::handleRotationGestureEvent);
+
+    /* 创建长按手势 */
+    auto longPressGesture = gestureApi->createLongPressGesture(1, false, 500);
+    gestureApi->setGestureEventTarget(longPressGesture,
+                                      GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE |
+                                      GESTURE_EVENT_ACTION_END | GESTURE_EVENT_ACTION_CANCEL,
+                                      this, QOhGestureManager::handleLongPressGesture);
+
+    /* 将手势添加到手势组 */
+    if (gestureApi->addChildGesture) {
+        /* FIXME panGesture造成无边框时三键位置无响应 */
+        //gestureApi->addChildGesture(groupGesture, panGesture);
+        gestureApi->addChildGesture(groupGesture, pinchGesture);
+        gestureApi->addChildGesture(groupGesture, longPressGesture);
+        //gestureApi->addChildGesture(groupGesture, swipeGesture);
+        //gestureApi->addChildGesture(groupGesture, rotationGesture);
+    }
+
+    /* 将手势组设置到组件上 */
+    gestureApi->addGestureToNode(node, groupGesture, PARALLEL, NORMAL_GESTURE_MASK);
+}
+
+void QOhGestureManager::setWindow(QWindow *w)
+{
+    m_window = w;
+}
+
+bool QOhGestureManager::isSupported()
+{
+    auto gestureApi = reinterpret_cast<ArkUI_NativeGestureAPI_1 *>(
+            OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_GESTURE, "ArkUI_NativeGestureAPI_1"));
+    return (gestureApi->createGroupGesture != nullptr);
+}
+
+bool QOhGestureManager::isValidEvent(ArkUI_GestureEvent *event, QOhGestureManager *manager)
+{
+    if ((nullptr == event) || (nullptr == manager) ||
+        manager->m_window.isNull())
+        return false;
+    return true;
+}
+
+static QPointF fix_global_point(const QPointF &pt, int32_t displayId)
+{
+    auto platformScreen = QOhDisplayManager::instance()->platformScreenOrNull(displayId);
+    QPointF result = pt;
+    if (platformScreen) {
+        result += platformScreen->geometry().topLeft();
+    }
+    return result;
+}
+void QOhGestureManager::handlePanGestureEvent(ArkUI_GestureEvent *event, void *extraParam)
+{
+    QOhGestureManager *manager = reinterpret_cast<QOhGestureManager*>(extraParam);
+    if (!isValidEvent(event, manager))
+        return;
+
+    auto inputEvent = OH_ArkUI_GestureEvent_GetRawInputEvent(event);
+    float velocity = OH_ArkUI_PanGesture_GetVelocity(event);
+
+    /* GESTURE_EVENT_ACTION_END = 0x04
+     * GESTURE_EVENT_ACTION_ACCEPT = 0x01
+     * GESTURE_EVENT_ACTION_UPDATE = 0x02
+     * GESTURE_EVENT_ACTION_CANCEL = 0x08
+     */
+    ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);
+
+    /* 获取UI输入事件发生的时间 */
+    int64_t timestamp = OH_ArkUI_UIInputEvent_GetEventTime(inputEvent);
+
+    /* 从带有指向性的输入事件中获取相对于当前屏幕左上角的坐标 */
+    float gx = OH_ArkUI_PointerEvent_GetDisplayX(inputEvent);
+    float gy = OH_ArkUI_PointerEvent_GetDisplayY(inputEvent);
+    int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(inputEvent);
+
+    /* 获取特定接触点相对于当前应用窗口左上角的坐标 */
+    float lx = OH_ArkUI_PointerEvent_GetWindowX(inputEvent);
+    float ly = OH_ArkUI_PointerEvent_GetWindowY(inputEvent);
+
+    /* 获取产生UI输入事件的来源类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(inputEvent);
+    auto gestureType = [](int actionType) {
+        switch (actionType) {
+        case GESTURE_EVENT_ACTION_END:
+            return Qt::EndNativeGesture;
+        case GESTURE_EVENT_ACTION_ACCEPT:
+            return Qt::BeginNativeGesture;
+        default:
+            break;
+        }
+        return Qt::PanNativeGesture;
+    };
+
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+        QSharedPointer<QtOh::GestureEvent> e(new QtOh::GestureEvent());
+        e->value = velocity;
+        e->timestamp = timestamp;
+        e->local = QPointF(lx, ly);
+        e->global = fix_global_point(QPointF(gx,gy), displayId);
+        e->gestureType = gestureType(actionType);
+        e->window = manager->m_window;
+        dispatcher->appendOhEvent(e);
+    }
+}
+
+void QOhGestureManager::handleLongPressGesture(ArkUI_GestureEvent *event, void *extraParam)
+{
+    QOhGestureManager *manager = reinterpret_cast<QOhGestureManager*>(extraParam);
+    if (!isValidEvent(event, manager))
+        return;
+
+    auto inputEvent = OH_ArkUI_GestureEvent_GetRawInputEvent(event);
+    /* 获取产生UI输入事件的工具类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_TOOL_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENT_TOOL_TYPE_FINGER = 1,
+     * UI_INPUT_EVENT_TOOL_TYPE_PEN = 2,
+     * UI_INPUT_EVENT_TOOL_TYPE_MOUSE = 3,
+     * UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD = 4,
+     * UI_INPUT_EVENT_TOOL_TYPE_JOYSTICK = 5
+     */
+    int32_t toolType = OH_ArkUI_UIInputEvent_GetToolType(inputEvent);
+
+    float scale = OH_ArkUI_PinchGesture_GetScale(event);
+    /* GESTURE_EVENT_ACTION_ACCEPT = 0x01
+     * GESTURE_EVENT_ACTION_UPDATE = 0x02,
+     * GESTURE_EVENT_ACTION_END = 0x04,
+     * GESTURE_EVENT_ACTION_CANCEL = 0x08
+     */
+    ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);
+
+    /* 获取产生UI输入事件的来源类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(inputEvent);
+
+    /* 获取UI输入事件发生的时间 */
+    int64_t timestamp = OH_ArkUI_UIInputEvent_GetEventTime(inputEvent);
+
+    /* 从带有指向性的输入事件中获取相对于当前屏幕左上角的坐标 */
+    float gx = OH_ArkUI_PointerEvent_GetDisplayX(inputEvent);
+    float gy = OH_ArkUI_PointerEvent_GetDisplayY(inputEvent);
+    int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(inputEvent);
+
+    /* 获取特定接触点相对于当前应用窗口左上角的坐标 */
+    float lx = OH_ArkUI_PointerEvent_GetWindowX(inputEvent);
+    float ly = OH_ArkUI_PointerEvent_GetWindowY(inputEvent);
+    bool mouseTriggered = (UI_INPUT_EVENT_TOOL_TYPE_MOUSE == toolType || UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD == toolType);
+    /* NOTE 将长按手势绑定到Qt的QContextMenu事件
+     * 只处理开始的通知,避免重复发送事件通知
+     */    
+    if (GESTURE_EVENT_ACTION_ACCEPT == actionType) {
+        // Todo 从event 获取mods
+        QWindowSystemInterface::handleContextMenuEvent(manager->m_window,  mouseTriggered, QPointF(lx, ly).toPoint(), fix_global_point(QPointF(gx, gy), displayId).toPoint(),
+                                                   QOhKeys::keyboardModifiers());
+    }
+}
+
+void QOhGestureManager::handlePinchGestureEvent(ArkUI_GestureEvent *event, void *extraParam)
+{
+    QOhGestureManager *manager = reinterpret_cast<QOhGestureManager*>(extraParam);
+    if (!isValidEvent(event, manager))
+        return;
+
+    auto inputEvent = OH_ArkUI_GestureEvent_GetRawInputEvent(event);
+    /* 获取产生UI输入事件的工具类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_TOOL_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENT_TOOL_TYPE_FINGER = 1,
+     * UI_INPUT_EVENT_TOOL_TYPE_PEN = 2,
+     * UI_INPUT_EVENT_TOOL_TYPE_MOUSE = 3,
+     * UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD = 4,
+     * UI_INPUT_EVENT_TOOL_TYPE_JOYSTICK = 5
+     */
+    int32_t toolType = OH_ArkUI_UIInputEvent_GetToolType(inputEvent);
+
+    /* 过滤来自鼠标/触控板的系统手势 */
+    if (UI_INPUT_EVENT_TOOL_TYPE_MOUSE == toolType ||
+        UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD == toolType) {
+        return;
+    }
+
+    float scale = OH_ArkUI_PinchGesture_GetScale(event);
+    /* GESTURE_EVENT_ACTION_ACCEPT = 0x01
+     * GESTURE_EVENT_ACTION_UPDATE = 0x02,
+     * GESTURE_EVENT_ACTION_END = 0x04,
+     * GESTURE_EVENT_ACTION_CANCEL = 0x08
+     */
+    ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);
+
+    /* 获取产生UI输入事件的来源类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(inputEvent);
+
+    /* 获取UI输入事件发生的时间 */
+    int64_t timestamp = OH_ArkUI_UIInputEvent_GetEventTime(inputEvent);
+
+    /* 从带有指向性的输入事件中获取相对于当前屏幕左上角的坐标 */
+    float gx = OH_ArkUI_PointerEvent_GetDisplayX(inputEvent);
+    float gy = OH_ArkUI_PointerEvent_GetDisplayY(inputEvent);
+    int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(inputEvent);
+    /* 获取特定接触点相对于当前应用窗口左上角的坐标 */
+    float lx = OH_ArkUI_PointerEvent_GetWindowX(inputEvent);
+    float ly = OH_ArkUI_PointerEvent_GetWindowY(inputEvent);
+
+    auto gestureType = [](int actionType) {
+        switch (actionType) {
+        case GESTURE_EVENT_ACTION_END:
+            return Qt::EndNativeGesture;
+        case GESTURE_EVENT_ACTION_ACCEPT:
+            return Qt::BeginNativeGesture;
+        default:
+            break;
+        }
+        return Qt::ZoomNativeGesture;
+    };
+
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+        QSharedPointer<QtOh::GestureEvent> e(new QtOh::GestureEvent());
+        e->value = scale;
+        e->timestamp = timestamp;
+        e->local = QPointF(lx, ly);
+        e->global = fix_global_point(QPointF(gx, gy), displayId);
+        e->gestureType = gestureType(actionType);
+        e->window = manager->m_window;
+        dispatcher->appendOhEvent(e);
+    }
+}
+
+void QOhGestureManager::handleSwipeGestureEvent(ArkUI_GestureEvent *event, void *extraParam)
+{
+    QOhGestureManager *manager = reinterpret_cast<QOhGestureManager*>(extraParam);
+    if (!isValidEvent(event, manager))
+        return;
+
+    auto inputEvent = OH_ArkUI_GestureEvent_GetRawInputEvent(event);
+    float angle = OH_ArkUI_SwipeGesture_GetAngle(event);
+    float velocity = OH_ArkUI_SwipeGesture_GetVelocity(event);
+
+    /* GESTURE_EVENT_ACTION_ACCEPT = 0x01
+     * GESTURE_EVENT_ACTION_UPDATE = 0x02,
+     * GESTURE_EVENT_ACTION_END = 0x04,
+     * GESTURE_EVENT_ACTION_CANCEL = 0x08
+     */
+    ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);
+
+    /* 获取UI输入事件发生的时间 */
+    int64_t timestamp = OH_ArkUI_UIInputEvent_GetEventTime(inputEvent);
+
+    /* 获取产生UI输入事件的来源类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(inputEvent);
+
+    /* 从带有指向性的输入事件中获取相对于当前屏幕左上角的坐标 */
+    float gx = OH_ArkUI_PointerEvent_GetDisplayX(inputEvent);
+    float gy = OH_ArkUI_PointerEvent_GetDisplayY(inputEvent);
+    int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(inputEvent);
+    /* 获取特定接触点相对于当前应用窗口左上角的坐标 */
+    float lx = OH_ArkUI_PointerEvent_GetWindowX(inputEvent);
+    float ly = OH_ArkUI_PointerEvent_GetWindowY(inputEvent);
+
+    auto gestureType = [](int actionType) {
+        switch (actionType) {
+        case GESTURE_EVENT_ACTION_END:
+            return Qt::EndNativeGesture;
+        case GESTURE_EVENT_ACTION_ACCEPT:
+            return Qt::BeginNativeGesture;
+        default:
+            break;
+        }
+        return Qt::SwipeNativeGesture;
+    };
+
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+        QSharedPointer<QtOh::GestureEvent> e(new QtOh::GestureEvent());
+        e->value = velocity;
+        e->timestamp = timestamp;
+        e->local = QPointF(lx, ly);
+        e->global = fix_global_point(QPointF(gx, gy), displayId);
+        e->gestureType = gestureType(actionType);
+        e->window = manager->m_window;
+        dispatcher->appendOhEvent(e);
+    }
+}
+
+void QOhGestureManager::handleRotationGestureEvent(ArkUI_GestureEvent *event, void *extraParam)
+{
+    QOhGestureManager *manager = reinterpret_cast<QOhGestureManager*>(extraParam);
+    if (!isValidEvent(event, manager))
+        return;
+
+    auto inputEvent = OH_ArkUI_GestureEvent_GetRawInputEvent(event);
+#if 1
+    /* 获取产生UI输入事件的工具类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_TOOL_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENT_TOOL_TYPE_FINGER = 1,
+     * UI_INPUT_EVENT_TOOL_TYPE_PEN = 2,
+     * UI_INPUT_EVENT_TOOL_TYPE_MOUSE = 3,
+     * UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD = 4,
+     * UI_INPUT_EVENT_TOOL_TYPE_JOYSTICK = 5
+     */
+    int32_t toolType = OH_ArkUI_UIInputEvent_GetToolType(inputEvent);
+
+    /* 过滤来自鼠标/触控板的系统手势 */
+    if (UI_INPUT_EVENT_TOOL_TYPE_MOUSE == toolType ||
+        UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD == toolType) {
+        return;
+    }
+#endif
+    /* GESTURE_EVENT_ACTION_END = 0x04
+     * GESTURE_EVENT_ACTION_ACCEPT = 0x01
+     * GESTURE_EVENT_ACTION_UPDATE = 0x02
+     * GESTURE_EVENT_ACTION_CANCEL = 0x08
+     */
+    ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);
+
+    float angle = OH_ArkUI_RotationGesture_GetAngle(event);
+
+    /* 获取UI输入事件发生的时间 */
+    int64_t timestamp = OH_ArkUI_UIInputEvent_GetEventTime(inputEvent);
+
+    /* 获取产生UI输入事件的来源类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(inputEvent);
+
+    /* 从带有指向性的输入事件中获取相对于当前屏幕左上角的坐标 */
+    float gx = OH_ArkUI_PointerEvent_GetDisplayX(inputEvent);
+    float gy = OH_ArkUI_PointerEvent_GetDisplayY(inputEvent);
+    int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(inputEvent);
+    /* 获取特定接触点相对于当前应用窗口左上角的坐标 */
+    float lx = OH_ArkUI_PointerEvent_GetWindowX(inputEvent);
+    float ly = OH_ArkUI_PointerEvent_GetWindowY(inputEvent);
+
+    auto gestureType = [](int actionType) {
+        switch (actionType) {
+        case GESTURE_EVENT_ACTION_END:
+            return Qt::EndNativeGesture;
+        case GESTURE_EVENT_ACTION_ACCEPT:
+            return Qt::BeginNativeGesture;
+        default:
+            break;
+        }
+        return Qt::RotateNativeGesture;
+    };
+
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+        QSharedPointer<QtOh::GestureEvent> e(new QtOh::GestureEvent());
+        e->value = angle;
+        e->timestamp = timestamp;
+        e->local = QPointF(lx, ly);
+        e->global = fix_global_point(QPointF(gx, gy), displayId);
+        e->gestureType = gestureType(actionType);
+        e->window = manager->m_window;
+        dispatcher->appendOhEvent(e);
+    }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohjsonlistener.cpp b/src/plugins/platforms/openharmony/qohjsonlistener.cpp
new file mode 100644
index 00000000000..ecb63b6509b
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohjsonlistener.cpp
@@ -0,0 +1,58 @@
+#include <QDebug>
+
+#include "qopenharmony.h"
+#include "qohjsonlistener.h"
+#include "qohnativewindow.h"
+
+QT_BEGIN_NAMESPACE
+
+void QOhJsOnListener::on()
+{
+    QtOh::runOnJsUIThreadAndWait([this]{
+        if (m_args != nullptr) {
+            std::vector<napi_value> args;
+            args.push_back(QNapi::create(m_event));
+            std::vector<Napi::Reference<Napi::Value>> extras;
+            m_args->toNapiValue(extras);
+            for (auto &arg : extras) {
+                args.push_back(arg.Value());
+            }
+            args.push_back(m_callback.Value());
+            Napi::Function on = QNapi::get<Napi::Function>(m_object->object(), "on");
+            on.Call(m_object->object(), args);
+        } else {
+            m_object->call("on", {Napi::String::New(m_object->env(), m_event.toStdString()), m_callback.Value()});
+        }
+    });
+}
+
+void QOhJsOnListener::off()
+{
+    // windowWillClose会打印This window state is abnormal.错误信息?
+    if (m_callback.IsEmpty() || m_event == "windowWillClose")
+        return;
+    while (m_isRunning.loadRelaxed()) {
+        QGuiApplication::processEvents();
+    }
+    QtOh::runOnJsUIThreadAndWait([this]{
+        m_object->call("off",  {Napi::String::New(m_object->env(), m_event.toStdString()), m_callback.Value()});
+    });
+    deleteArgs();
+}
+
+void QOhJsOnListener::deleteArgs()
+{
+    if (m_args != nullptr) {
+        delete m_args;
+        m_args = nullptr;
+    }
+}
+
+QOhJsOnListener::~QOhJsOnListener()
+{    
+    QtOh::runOnJsUIThreadAndWait([this]{
+        m_callback.Reset();
+    });
+}
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/openharmony/qohjsonlistener.h b/src/plugins/platforms/openharmony/qohjsonlistener.h
new file mode 100644
index 00000000000..5f57fb1edc7
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohjsonlistener.h
@@ -0,0 +1,74 @@
+#ifndef QOHJSONLISTENER_H
+#define QOHJSONLISTENER_H
+
+#include <QAtomicInteger>
+#include <functional>
+#include <QJsObject>
+#include <qnapi.h>
+#include <QScopedPointer>
+#include <private/qopenharmony_p.h>
+QT_BEGIN_NAMESPACE
+
+class QOhJsOnListener
+{
+    struct Args{
+        virtual void toNapiValue(std::vector<Napi::Reference<Napi::Value>> &out) const = 0;
+        virtual ~Args() {}
+    };
+    template<typename... Params>
+    struct OnArgs : Args
+    {
+        OnArgs(Params&&... args): argsTuple(std::forward<Params>(args)...) {}
+        std::tuple<Params...> argsTuple;
+        virtual void toNapiValue(std::vector<Napi::Reference<Napi::Value>> &out) const override
+        {
+            std::apply([&out](const auto&... args) {
+                (out.push_back(Napi::Persistent(QNapi::create(args))), ...);
+            }, argsTuple);
+        }
+    };
+public:
+    template<typename Function>
+    QOhJsOnListener(QJsObject *object, const QString &event, Function&& handler)
+        : m_object(object)
+        , m_event(event)
+    {
+        m_isRunning.storeRelaxed(false);
+        m_callback = QtOh::runOnJsUIThreadWithResult([this, function = std::forward<Function>(handler)](){
+            Napi::Function func = QNapi::create([this, function](const Napi::CallbackInfo& info) {
+                m_isRunning.storeRelaxed(true);
+                if constexpr (std::is_void_v<std::invoke_result_t<Function, Napi::CallbackInfo>>) {
+                    function(info);
+                    m_isRunning.storeRelaxed(false);
+                } else {
+                    auto result = function(info);
+                    m_isRunning.storeRelaxed(false);
+                    return result;
+                }
+            });
+            Napi::FunctionReference result = Napi::Persistent(func);
+            return result;
+        });
+    }
+    ~QOhJsOnListener();
+
+    void on();
+    void off();
+    template<typename... Args>
+    void setExtraArgs(Args&&... args)
+    {
+        deleteArgs();
+        m_args = new OnArgs<Args...>(std::forward<Args>(args)...);
+    }
+
+private:
+    void deleteArgs();
+    QJsObject *m_object;
+    QString m_event;
+    QAtomicInteger<bool> m_isRunning;
+    Args *m_args = nullptr;
+    Napi::FunctionReference m_callback;
+};
+
+QT_END_NAMESPACE
+#endif // QOHJSONLISTENER_H
diff --git a/src/plugins/platforms/openharmony/qohkeys.cpp b/src/plugins/platforms/openharmony/qohkeys.cpp
new file mode 100644
index 00000000000..331d92ba822
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohkeys.cpp
@@ -0,0 +1,845 @@
+#include "qohkeys.h"
+#include "qohwindowcontext.h"
+#include "qohobjectholder.h"
+
+#include <QtCore/QHash>
+#include <qpa/qwindowsysteminterface.h>
+QT_BEGIN_NAMESPACE
+
+struct KeyRecord {
+    KeyRecord(int c, int a, int s, const QString &t) : code(c), ascii(a), state(s), text(t) {}
+    KeyRecord() {}
+
+    int code;
+    int ascii;
+    int state;
+    QString text;
+};
+
+// We need to record the pressed keys in order to decide, whether the key event is an autorepeat
+// event. As soon as its state changes, the chain of autorepeat events will be broken.
+static const int QT_MAX_KEY_RECORDINGS = 64; // User has LOTS of fingers...
+struct KeyRecorder
+{
+    inline KeyRecord *findKey(int32_t code, bool remove);
+    inline void storeKey(int32_t code, int ascii, int state, const QString& text);
+    inline void clearKeys();
+
+    int nrecs = 0;
+    KeyRecord deleted_record; // A copy of last entry removed from records[]
+    KeyRecord records[QT_MAX_KEY_RECORDINGS];
+};
+
+static KeyRecorder key_recorder;
+
+static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state)
+{
+    if (state == Qt::ApplicationInactive)
+        key_recorder.clearKeys();
+}
+
+KeyRecord *KeyRecorder::findKey(int32_t code, bool remove)
+{
+    KeyRecord *result = nullptr;
+    for (int i = 0; i < nrecs; ++i) {
+        if (records[i].code == code) {
+            if (remove) {
+                deleted_record = records[i];
+                // Move rest down, and decrease count
+                while (i + 1 < nrecs) {
+                    records[i] = records[i + 1];
+                    ++i;
+                }
+                --nrecs;
+                result = &deleted_record;
+            } else {
+                result = &records[i];
+            }
+            break;
+        }
+    }
+    return result;
+}
+
+void KeyRecorder::storeKey(int32_t code, int ascii, int state, const QString& text)
+{
+    Q_ASSERT_X(nrecs != QT_MAX_KEY_RECORDINGS,
+               "Internal KeyRecorder",
+               "Keyboard recorder buffer overflow, consider increasing QT_MAX_KEY_RECORDINGS");
+
+    if (nrecs == QT_MAX_KEY_RECORDINGS) {
+        qWarning("Qt: Internal keyboard buffer overflow");
+        return;
+    }
+    records[nrecs++] = KeyRecord(code,ascii,state,text);
+}
+
+void KeyRecorder::clearKeys()
+{
+    nrecs = 0;
+}
+
+bool QOhKeys::isKeyPressed(int32_t keyCode)
+{
+    bool ret = false;
+    QOhObjectHolder<Input_KeyState> keyState(OH_Input_CreateKeyState, OH_Input_DestroyKeyState);
+    Input_KeyState *input_key_state = keyState.object();
+    OH_Input_SetKeyCode(input_key_state, keyCode);
+    Input_Result result = OH_Input_GetKeyState(input_key_state);
+    if (INPUT_SUCCESS == result) {
+        int iPressed = OH_Input_GetKeyPressed(input_key_state);
+        ret = (KEY_PRESSED == iPressed);
+    }
+    return ret;
+}
+
+bool QOhKeys::isKeyLockActive(int32_t keyCode)
+{
+    bool ret = false;
+    static QOhObjectHolder<Input_KeyState> keyState(OH_Input_CreateKeyState, OH_Input_DestroyKeyState);
+    static Input_KeyState *input_key_state = keyState.object();
+    OH_Input_SetKeyCode(input_key_state, keyCode);
+    Input_Result result = OH_Input_GetKeyState(input_key_state);
+    if (INPUT_SUCCESS == result) {
+        int iSwitch = OH_Input_GetKeySwitch(input_key_state);
+        ret = (KEY_SWITCH_ON == iSwitch);
+    }
+    return ret;
+}
+
+Qt::Key QOhKeys::ohCode2QtKey(int32_t keyCode, Qt::KeyboardModifiers modifiers)
+{
+    static QHash<int32_t, Qt::Key> sKeyMap
+    {
+        { KEY_HOME, Qt::Key_Home },
+        { KEY_BACK, Qt::Key_Back },
+        { KEY_MEDIA_PLAY_PAUSE, Qt::Key_MediaTogglePlayPause },
+        { KEY_MEDIA_STOP, Qt::Key_MediaStop },
+        { KEY_MEDIA_NEXT, Qt::Key_MediaNext },
+        { KEY_MEDIA_PREVIOUS, Qt::Key_MediaPrevious },
+        { KEY_MEDIA_REWIND, Qt::Key_AudioRewind },
+        { KEY_MEDIA_FAST_FORWARD, Qt::Key_AudioForward },
+        { KEY_VOLUME_UP, Qt::Key_VolumeUp },
+        { KEY_VOLUME_DOWN, Qt::Key_VolumeDown },
+        { KEY_POWER, Qt::Key_PowerDown },
+        { KEY_CAMERA, Qt::Key_Camera },
+        { KEY_VOLUME_MUTE, Qt::Key_VolumeMute },
+        { KEY_MUTE, Qt::Key_MicMute },
+        { KEY_BRIGHTNESS_UP, Qt::Key_MonBrightnessUp },
+        { KEY_BRIGHTNESS_DOWN, Qt::Key_MonBrightnessDown },
+        { KEY_0, Qt::Key_0 },
+        { KEY_1, Qt::Key_1 },
+        { KEY_2, Qt::Key_2 },
+        { KEY_3, Qt::Key_3 },
+        { KEY_4, Qt::Key_4 },
+        { KEY_5, Qt::Key_5 },
+        { KEY_6, Qt::Key_6 },
+        { KEY_7, Qt::Key_7 },
+        { KEY_8, Qt::Key_8 },
+        { KEY_9, Qt::Key_9 },
+        { KEY_STAR, Qt::Key_Asterisk },
+        { KEY_POUND, Qt::Key_NumberSign },
+        { KEY_DPAD_UP, Qt::Key_Up },
+        { KEY_DPAD_DOWN, Qt::Key_Down },
+        { KEY_DPAD_LEFT, Qt::Key_Left },
+        { KEY_DPAD_RIGHT, Qt::Key_Right },
+        //{ KEY_DPAD_CENTER, Qt::Key_ },
+        { KEY_A, Qt::Key_A },
+        { KEY_B, Qt::Key_B },
+        { KEY_C, Qt::Key_C },
+        { KEY_D, Qt::Key_D },
+        { KEY_E, Qt::Key_E },
+        { KEY_F, Qt::Key_F },
+        { KEY_G, Qt::Key_G },
+        { KEY_H, Qt::Key_H },
+        { KEY_I, Qt::Key_I },
+        { KEY_J, Qt::Key_J },
+        { KEY_K, Qt::Key_K },
+        { KEY_L, Qt::Key_L },
+        { KEY_M, Qt::Key_M },
+        { KEY_N, Qt::Key_N },
+        { KEY_O, Qt::Key_O },
+        { KEY_P, Qt::Key_P },
+        { KEY_Q, Qt::Key_Q },
+        { KEY_R, Qt::Key_R },
+        { KEY_S, Qt::Key_S },
+        { KEY_T, Qt::Key_T },
+        { KEY_U, Qt::Key_U },
+        { KEY_V, Qt::Key_V },
+        { KEY_W, Qt::Key_W },
+        { KEY_X, Qt::Key_X },
+        { KEY_Y, Qt::Key_Y },
+        { KEY_Z, Qt::Key_Z },
+        { KEY_COMMA, Qt::Key_Comma },
+        { KEY_PERIOD, Qt::Key_Period },
+        { KEY_ALT_LEFT, Qt::Key_Alt },
+        { KEY_ALT_RIGHT, Qt::Key_Alt },
+        { KEY_SHIFT_LEFT, Qt::Key_Shift },
+        { KEY_SHIFT_RIGHT, Qt::Key_Shift },
+        { KEY_TAB, Qt::Key_Tab  },
+        { KEY_SPACE, Qt::Key_Space },
+        //{ KEY_SYM, Qt::KEY_},
+        { KEY_EXPLORER, Qt::Key_Explorer },
+        //{ KEY_ENVELOPE, Qt::Key_ },
+        { KEY_ENTER, Qt::Key_Return },
+        { KEY_DEL, Qt::Key_Backspace },
+        { KEY_GRAVE, Qt::Key_QuoteLeft },
+        { KEY_MINUS, Qt::Key_Minus },
+        { KEY_EQUALS, Qt::Key_Equal },
+        { KEY_LEFT_BRACKET, Qt::Key_BracketLeft },
+        { KEY_RIGHT_BRACKET, Qt::Key_BracketRight },
+        { KEY_BACKSLASH, Qt::Key_Backslash },
+        { KEY_SEMICOLON, Qt::Key_Semicolon },
+        { KEY_APOSTROPHE, Qt::Key_Apostrophe },
+        { KEY_SLASH, Qt::Key_Slash },
+        { KEY_AT, Qt::Key_At },
+        { KEY_PLUS, Qt::Key_Plus },
+        { KEY_MENU, Qt::Key_Menu },
+        { KEY_PAGE_UP, Qt::Key_PageUp },
+        { KEY_PAGE_DOWN, Qt::Key_PageDown },
+        { KEY_ESCAPE, Qt::Key_Escape },
+        { KEY_FORWARD_DEL, Qt::Key_Delete },
+        { KEY_CTRL_LEFT, Qt::Key_Control },
+        { KEY_CTRL_RIGHT, Qt::Key_Control },
+        { KEY_CAPS_LOCK, Qt::Key_CapsLock },
+        { KEY_SCROLL_LOCK, Qt::Key_ScrollLock },
+        { KEY_META_LEFT, Qt::Key_Meta },
+        { KEY_META_RIGHT, Qt::Key_Meta },
+        //{ KEY_FUNCTION, Qt::Key_ },
+        { KEY_SYSRQ, Qt::Key_SysReq },
+        { KEY_BREAK, Qt::Key_Pause },
+        { KEY_MOVE_HOME, Qt::Key_Home },
+        { KEY_MOVE_END, Qt::Key_End },
+        { KEY_INSERT, Qt::Key_Insert },
+        { KEY_FORWARD, Qt::Key_Forward },
+        { KEY_MEDIA_PLAY, Qt::Key_MediaPlay },
+        { KEY_MEDIA_PAUSE, Qt::Key_MediaPause },
+        //{ KEY_MEDIA_CLOSE, Qt::Key_Media },
+        //{ KEY_MEDIA_EJECT, Qt::Key_Eject },
+        { KEY_MEDIA_RECORD, Qt::Key_MediaRecord },
+        { KEY_F1, Qt::Key_F1 },
+        { KEY_F2, Qt::Key_F2 },
+        { KEY_F3, Qt::Key_F3 },
+        { KEY_F4, Qt::Key_F4 },
+        { KEY_F5, Qt::Key_F5 },
+        { KEY_F6, Qt::Key_F6 },
+        { KEY_F7, Qt::Key_F7 },
+        { KEY_F8, Qt::Key_F8 },
+        { KEY_F9, Qt::Key_F9 },
+        { KEY_F10, Qt::Key_F10 },
+        { KEY_F11, Qt::Key_F11 },
+        { KEY_F12, Qt::Key_F12 },
+        { KEY_NUM_LOCK, Qt::Key_NumLock },
+        { KEY_NUMPAD_0, Qt::Key_0 },
+        { KEY_NUMPAD_1, Qt::Key_1 },
+        { KEY_NUMPAD_2, Qt::Key_2 },
+        { KEY_NUMPAD_3, Qt::Key_3 },
+        { KEY_NUMPAD_4, Qt::Key_4 },
+        { KEY_NUMPAD_5, Qt::Key_5 },
+        { KEY_NUMPAD_6, Qt::Key_6 },
+        { KEY_NUMPAD_7, Qt::Key_7 },
+        { KEY_NUMPAD_8, Qt::Key_8 },
+        { KEY_NUMPAD_9, Qt::Key_9 },
+        { KEY_NUMPAD_DIVIDE, Qt::Key_Slash },
+        { KEY_NUMPAD_MULTIPLY, Qt::Key_Asterisk },
+        { KEY_NUMPAD_SUBTRACT, Qt::Key_Minus },
+        { KEY_NUMPAD_ADD, Qt::Key_Plus },
+        { KEY_NUMPAD_DOT, Qt::Key_Period },
+        { KEY_NUMPAD_COMMA, Qt::Key_Comma },
+        { KEY_NUMPAD_ENTER, Qt::Key_Enter },
+        { KEY_NUMPAD_EQUALS, Qt::Key_Equal },
+        { KEY_NUMPAD_LEFT_PAREN, Qt::Key_ParenLeft },
+        { KEY_NUMPAD_RIGHT_PAREN, Qt::Key_ParenRight },
+        //{ KEY_VIRTUAL_MULTITASK, Qt::Key_ },
+        { KEY_SLEEP, Qt::Key_Sleep },
+        { KEY_ZENKAKU_HANKAKU, Qt::Key_Zenkaku_Hankaku },
+        //{ KEY_102ND,  Qt::Key_ },
+        //{ KEY_RO,  Qt::Key_ },
+        { KEY_KATAKANA, Qt::Key_Katakana },
+        { KEY_HIRAGANA, Qt::Key_Hiragana },
+        { KEY_HENKAN, Qt::Key_Henkan },
+        { KEY_KATAKANA_HIRAGANA, Qt::Key_Hiragana_Katakana },
+        { KEY_MUHENKAN, Qt::Key_Muhenkan },
+        { KEY_LINEFEED, Qt::Key_Enter },
+        //{ KEY_MACRO, Qt::Key_macron },
+        //{ KEY_NUMPAD_PLUSMINUS, Qt::Key_ },
+        //{ KEY_SCALE, Qt::Key_ },
+        { KEY_HANGUEL, Qt::Key_Hangul },
+        { KEY_HANJA, Qt::Key_Hangul_Hanja },
+        { KEY_YEN, Qt::Key_yen },
+        { KEY_STOP, Qt::Key_Stop },
+        //{ KEY_AGAIN, Qt::Key_ },
+        //{ KEY_PROPS, Qt::Key_ },
+        { KEY_UNDO, Qt::Key_Undo },
+        { KEY_COPY, Qt::Key_Copy },
+        { KEY_OPEN, Qt::Key_Open },
+        { KEY_PASTE, Qt::Key_Paste },
+        { KEY_FIND, Qt::Key_Find },
+        { KEY_CUT, Qt::Key_Cut },
+        { KEY_HELP, Qt::Key_Help },
+        //{ KEY_CALC, Qt::Key_ },
+        //{ KEY_FILE, Qt::Key_ },
+        //{ KEY_BOOKMARKS, Qt::Key_Book },
+        //{ KEY_NEXT, Qt::Key_ },
+        //{ KEY_PLAYPAUSE, Qt::Key_MediaTogglePlayPause }
+        //{ KEY_PREVIOUS, Qt::Key_ },
+        //{ KEY_STOPCD, Qt::Key_ },
+        //{ KEY_CONFIG, Qt::Key_ },
+        { KEY_REFRESH, Qt::Key_Refresh },
+        { KEY_EXIT, Qt::Key_Exit },
+        //{ KEY_EDIT, Qt::Key_ },
+        //{ KEY_SCROLLUP, Qt::Key_ },
+        //{ KEY_SCROLLDOWN, Qt::Key_ },
+        { KEY_NEW, Qt::Key_New },
+        { KEY_REDO, Qt::Key_Redo },
+        { KEY_CLOSE, Qt::Key_Close },
+        { KEY_PLAY, Qt::Key_Play },
+        //{ KEY_BASSBOOST, Qt::Key_ },
+        { KEY_PRINT, Qt::Key_Print },
+        //{ KEY_CHAT, Qt::Key_ },
+        { KEY_FINANCE, Qt::Key_Finance },
+        { KEY_CANCEL, Qt::Key_Cancel },
+        //{ KEY_KBDILLUM_TOGGLE, Qt::Key_ },
+        { KEY_KBDILLUM_DOWN, Qt::Key_KeyboardBrightnessDown },
+        { KEY_KBDILLUM_UP, Qt::Key_KeyboardBrightnessUp },
+        { KEY_SEND, Qt::Key_Send },
+        { KEY_REPLY, Qt::Key_Reply },
+        { KEY_FORWARDMAIL, Qt::Key_Forward },
+        { KEY_SAVE, Qt::Key_Save },
+        { KEY_DOCUMENTS, Qt::Key_Documents },
+        //{ KEY_VIDEO_NEXT, Qt::Key_ },
+        //{ KEY_VIDEO_PREV, Qt::Key_ },
+        //{ KEY_BRIGHTNESS_CYCLE, Qt::Key_ },
+        //{ KEY_BRIGHTNESS_ZERO, Qt::Key_ },
+        //{ KEY_DISPLAY_OFF, Qt::Key_ },
+        //{ KEY_BTN_MISC, Qt::Key_ },
+        { KEY_GOTO, Qt::Key_Go },
+        { KEY_INFO, Qt::Key_Info },
+        //{ KEY_PROGRAM, Qt::Key_ },
+        //{ KEY_PVR, Qt::Key_ },
+        { KEY_SUBTITLE, Qt::Key_Subtitle },
+        //{ KEY_FULL_SCREEN, Qt::Key_ },
+        //{ KEY_KEYBOARD, Qt::Key_ },
+        //{ KEY_ASPECT_RATIO, Qt::Key_ },
+        //{ KEY_PC, Qt::Key_ },
+        //{ KEY_TV, Qt::Key_ },
+        //{ KEY_TV2, Qt::Key_ },
+        //{ KEY_VCR, Qt::Key_ },
+        //{ KEY_VCR2, Qt::Key_ },
+        //{ KEY_SAT, Qt::Key_ },
+        { KEY_CD, Qt::Key_CD },
+        //{ KEY_TAPE, Qt::Key_ },
+        //{ KEY_TUNER, Qt::Key_ },
+        { KEY_PLAYER, Qt::Key_Play },
+        //{ KEY_DVD, Qt::Key_ },
+        //{ KEY_AUDIO, Qt::Key_ },
+        { KEY_VIDEO, Qt::Key_Video },
+        { KEY_MEMO, Qt::Key_Memo },
+        { KEY_CALENDAR, Qt::Key_Calendar },
+        { KEY_RED, Qt::Key_Red },
+        { KEY_GREEN, Qt::Key_Green },
+        { KEY_YELLOW, Qt::Key_Yellow },
+        { KEY_BLUE, Qt::Key_Blue },
+        { KEY_CHANNELUP, Qt::Key_ChannelUp },
+        { KEY_CHANNELDOWN, Qt::Key_ChannelDown },
+        //{ KEY_LAST, Qt::Key_ },
+        //{ KEY_RESTART, Qt::Key_ },
+        //{ KEY_SLOW, Qt::Key_ },
+        //{ KEY_SHUFFLE, Qt::Key_ },
+        //{ KEY_VIDEOPHONE, Qt::Key_ },
+        { KEY_GAMES, Qt::Key_Game },
+        { KEY_ZOOMIN, Qt::Key_ZoomIn },
+        { KEY_ZOOMOUT, Qt::Key_ZoomOut },
+        //{ KEY_ZOOMRESET, Qt::Key_ },
+        //{ KEY_WORDPROCESSOR, Qt::Key_ },
+        //{ KEY_EDITOR, Qt::Key_ },
+        //{ KEY_SPREADSHEET, Qt::Key_ },
+        //{ KEY_GRAPHICSEDITOR, Qt::Key_ },
+        //{ KEY_PRESENTATION, Qt::Key_ },
+        //{ KEY_DATABASE, Qt::Key_ },
+        { KEY_NEWS, Qt::Key_News },
+        //{ KEY_VOICEMAIL, Qt::Key_ },
+        //{ KEY_ADDRESSBOOK, Qt::Key_ },
+        { KEY_MESSENGER, Qt::Key_Messenger },
+        //{ KEY_BRIGHTNESS_TOGGLE, Qt::Key_BrightnessAdjust }
+        //{ KEY_SPELLCHECK, Qt::Key_Spell }
+        //{ KEY_COFFEE, Qt::Key_ },
+        //{ KEY_MEDIA_REPEAT, Qt::Key_ },
+        //{ KEY_IMAGES, Qt::Key_ },
+        //{ KEY_BUTTONCONFIG, Qt::Key_ },
+        //{ KEY_TASKMANAGER, Qt::Key_TaskPane }
+        //{ KEY_JOURNAL, Qt::Key_ },
+        //{ KEY_CONTROLPANEL, Qt::Key_ },
+        //{ KEY_APPSELECT, Qt::Key_ },
+        { KEY_SCREENSAVER, Qt::Key_ScreenSaver },
+        //{ KEY_ASSISTANT, Qt::Key_ },
+        //{ KEY_KBD_LAYOUT_NEXT, Qt::Key_ },
+        //{ KEY_BRIGHTNESS_MIN, Qt::Key_ },
+        //{ KEY_BRIGHTNESS_MAX, Qt::Key_ },
+        //{ KEY_KBDINPUTASSIST_PREV, Qt::Key_ },
+        //{ KEY_KBDINPUTASSIST_NEXT, Qt::Key_ },
+        //{ KEY_KBDINPUTASSIST_PREVGROUP, Qt::Key_ },
+        //{ KEY_KBDINPUTASSIST_NEXTGROUP, Qt::Key_ },
+        //{ KEY_KBDINPUTASSIST_ACCEPT, Qt::Key_ },
+        //{ KEY_KBDINPUTASSIST_CANCEL, Qt::Key_ },
+        //{ KEY_FRONT, Qt::Key_ }
+        //{ KEY_SETUP, Qt::Key_Settings },
+        { KEY_WAKEUP, Qt::Key_WakeUp },
+        //{ KEY_SENDFILE, Qt::Key_ },
+        //{ KEY_DELETEFILE, Qt::Key_ },
+        { KEY_XFER, Qt::Key_Xfer },
+        //{ KEY_PROG1, Qt::Key_ },
+        //{ KEY_PROG2, Qt::Key_ },
+        //{ KEY_MSDOS, Qt::Key_ },
+        //{ KEY_SCREENLOCK, Qt::Key_ },
+        //{ KEY_DIRECTION_ROTATE_DISPLAY, Qt::Key },
+        //{ KEY_CYCLEWINDOWS, Qt::Key_ },
+        //{ KEY_COMPUTER, Qt::Key },
+        { KEY_EJECTCLOSECD, Qt::Key_Eject },
+        //{ KEY_ISO, Qt::Key_ },
+        //{ KEY_MOVE, Qt::Key_ },
+        { KEY_F13, Qt::Key_F13 },
+        { KEY_F14, Qt::Key_F14 },
+        { KEY_F15, Qt::Key_F15 },
+        { KEY_F16, Qt::Key_F16 },
+        { KEY_F17, Qt::Key_F17 },
+        { KEY_F18, Qt::Key_F18 },
+        { KEY_F19, Qt::Key_F19 },
+        { KEY_F20, Qt::Key_F20 },
+        { KEY_F21, Qt::Key_F21 },
+        { KEY_F22, Qt::Key_F22 },
+        { KEY_F23, Qt::Key_F23 },
+        { KEY_F24, Qt::Key_F24 },
+        //{ KEY_PROG3, Qt::Key_ },
+        //{ KEY_PROG4, Qt::Key_ },
+        //{ KEY_DASHBOARD, Qt::Key_ },
+        { KEY_SUSPEND, Qt::Key_Suspend },
+        //{ KEY_HP, Qt::Key_ },
+        //{ KEY_SOUND, Qt::Key_ },
+        { KEY_QUESTION, Qt::Key_Question },
+        //{ KEY_CONNECT, Qt::Key_ },
+        //{ KEY_SPORT, Qt::Key_ },
+        { KEY_SHOP, Qt::Key_Shop },
+        //{ KEY_ALTERASE, Qt::Key_ },
+        //{ KEY_SWITCHVIDEOMODE, Qt::Key_Mode_switch }
+        { KEY_BATTERY, Qt::Key_Battery },
+        { KEY_BLUETOOTH, Qt::Key_Bluetooth },
+        { KEY_WLAN, Qt::Key_WLAN },
+        { KEY_UWB, Qt::Key_UWB },
+        //{ KEY_WWAN_WIMAX, Qt::Key_ },
+        //{ KEY_RFKILL, Qt::Key_ },
+        //{ KEY_CHANNEL, Qt::Key_ },
+        { KEY_BTN_0, Qt::Key_0 },
+        { KEY_BTN_1, Qt::Key_1 },
+        { KEY_BTN_2, Qt::Key_2 },
+        { KEY_BTN_3, Qt::Key_3 },
+        { KEY_BTN_4, Qt::Key_4 },
+        { KEY_BTN_5, Qt::Key_5 },
+        { KEY_BTN_6, Qt::Key_6 },
+        { KEY_BTN_7, Qt::Key_7 },
+        { KEY_BTN_8, Qt::Key_8 },
+        { KEY_BTN_9, Qt::Key_9 }
+    };
+    auto result = sKeyMap.value(keyCode, Qt::Key_unknown);
+
+    /* 按下shift 按键映射 */
+    static QHash<int32_t, Qt::Key> sKeyShiftMap{
+        { KEY_GRAVE, Qt::Key_AsciiTilde},
+        { KEY_1, Qt::Key_Exclam },
+        { KEY_2, Qt::Key_At },
+        { KEY_3, Qt::Key_NumberSign },
+        { KEY_4, Qt::Key_Dollar },
+        { KEY_5, Qt::Key_Percent },
+        { KEY_6, Qt::Key_AsciiCircum },
+        { KEY_7, Qt::Key_Ampersand },
+        { KEY_8, Qt::Key_Asterisk },
+        { KEY_9, Qt::Key_ParenLeft },
+        { KEY_0, Qt::Key_ParenRight },
+        { KEY_MINUS, Qt::Key_Underscore},
+        { KEY_EQUALS, Qt::Key_Plus},
+        { KEY_LEFT_BRACKET, Qt::Key_BraceLeft},
+        { KEY_RIGHT_BRACKET, Qt::Key_BraceRight},
+        { KEY_SEMICOLON, Qt::Key_Colon},
+        { KEY_APOSTROPHE, Qt::Key_QuoteDbl},
+        { KEY_BACKSLASH, Qt::Key_Bar},
+        { KEY_COMMA, Qt::Key_Less},
+        { KEY_PERIOD, Qt::Key_Greater},
+        { KEY_SLASH, Qt::Key_Question}
+    };
+
+    /* 按下NUM_Lock按键映射 */
+    static QHash<int32_t, Qt::Key> sKeyNumLockMap{
+        { KEY_NUMPAD_0, Qt::Key_Insert },
+        { KEY_NUMPAD_1, Qt::Key_End },
+        { KEY_NUMPAD_2, Qt::Key_Down },
+        { KEY_NUMPAD_3, Qt::Key_PageDown },
+        { KEY_NUMPAD_4, Qt::Key_Left },
+        { KEY_NUMPAD_5, Qt::Key_Clear },
+        { KEY_NUMPAD_6, Qt::Key_Right },
+        { KEY_NUMPAD_7, Qt::Key_Home },
+        { KEY_NUMPAD_8, Qt::Key_Up },
+        { KEY_NUMPAD_9, Qt::Key_PageUp },
+        { KEY_NUMPAD_DOT, Qt::Key_Delete },
+    };
+
+
+    /* NUM_Lock未按下 */
+    if (!isKeyLockActive(KEY_NUM_LOCK) && sKeyNumLockMap.contains(keyCode)) {
+        result = sKeyNumLockMap.value(keyCode, Qt::Key_unknown);
+    }
+
+    /* Shift按下 */
+    if (modifiers.testFlag(Qt::ShiftModifier) && sKeyShiftMap.contains(keyCode)) {
+        result = sKeyShiftMap.value(keyCode, Qt::Key_unknown);
+    }
+    return result;
+}
+
+Qt::KeyboardModifier QOhKeys::ohKeyboardModifier2QtKeyboardModifier(int32_t keyCode)
+{
+    static QHash<int32_t, Qt::KeyboardModifier> sKeyModifers{
+        { KEY_SHIFT_LEFT, Qt::ShiftModifier },
+        { KEY_SHIFT_RIGHT, Qt::ShiftModifier },
+        { KEY_CTRL_LEFT, Qt::ControlModifier },
+        { KEY_CTRL_RIGHT, Qt::ControlModifier },
+        { KEY_ALT_LEFT, Qt::AltModifier },
+        { KEY_ALT_RIGHT, Qt::AltModifier },
+        { KEY_META_LEFT, Qt::MetaModifier },
+        { KEY_META_RIGHT, Qt::MetaModifier }
+        /*,
+        { KEY_NUM_LOCK, Qt::KeypadModifier },
+        { KEY_NUMPAD_0, Qt::KeypadModifier },
+        { KEY_NUMPAD_1, Qt::KeypadModifier },
+        { KEY_NUMPAD_2, Qt::KeypadModifier },
+        { KEY_NUMPAD_3, Qt::KeypadModifier },
+        { KEY_NUMPAD_4, Qt::KeypadModifier },
+        { KEY_NUMPAD_5, Qt::KeypadModifier },
+        { KEY_NUMPAD_6, Qt::KeypadModifier },
+        { KEY_NUMPAD_7, Qt::KeypadModifier },
+        { KEY_NUMPAD_8, Qt::KeypadModifier },
+        { KEY_NUMPAD_9, Qt::KeypadModifier },
+        { KEY_NUMPAD_DIVIDE, Qt::KeypadModifier },
+        { KEY_NUMPAD_MULTIPLY, Qt::KeypadModifier },
+        { KEY_NUMPAD_SUBTRACT, Qt::KeypadModifier },
+        { KEY_NUMPAD_ADD, Qt::KeypadModifier },
+        { KEY_NUMPAD_DOT, Qt::KeypadModifier },
+        { KEY_NUMPAD_COMMA, Qt::KeypadModifier },
+        { KEY_NUMPAD_ENTER, Qt::KeypadModifier },
+        { KEY_NUMPAD_EQUALS, Qt::KeypadModifier },
+        { KEY_NUMPAD_LEFT_PAREN, Qt::KeypadModifier },
+        { KEY_NUMPAD_RIGHT_PAREN, Qt::KeypadModifier},
+        */
+    };
+    return sKeyModifers.value(keyCode, Qt::NoModifier);
+}
+
+bool QOhKeys::autoRepeat(int32_t type, int32_t code)
+{
+    /* 长按判断
+     * 记录按下的字符,判断字符是否已经按下
+     * 如果字符已经按下则认为是长按状态
+     */
+    bool result = false;
+    // 0 for down
+    if (0 == type) {
+        KeyRecord *rec = key_recorder.findKey(int(code), false);
+        if (rec) {
+            result = true;
+        } else {
+            key_recorder.storeKey(int(code), 0, 0, QString());
+        }
+    } else {
+        key_recorder.findKey(int(code), true);
+    }
+    return result;
+}
+
+QString QOhKeys::key2String(Qt::Key key, Qt::KeyboardModifiers modifiers)
+{
+    static QHash<Qt::Key, QString> sKeyTextMap{
+        { Qt::Key_Home, QString() },
+        { Qt::Key_Back, QString() },
+        { Qt::Key_MediaTogglePlayPause, "MediaTogglePlayPause" },
+        { Qt::Key_MediaStop, "MediaStop" },
+        { Qt::Key_MediaNext, "MediaNext" },
+        { Qt::Key_MediaPrevious, "MediaPrevious" },
+        { Qt::Key_AudioRewind, "AudioRewind" },
+        { Qt::Key_AudioForward, "AudioForward" },
+        { Qt::Key_VolumeUp, "VolumeUp" },
+        { Qt::Key_VolumeDown, "VolumeDown" },
+        { Qt::Key_PowerDown, "PowerDown" },
+        { Qt::Key_Camera, "Camera" },
+        { Qt::Key_VolumeMute, "VolumeMute" },
+        { Qt::Key_MicMute, "MicMute" },
+        { Qt::Key_MonBrightnessUp, "MonBrightnessUp" },
+        { Qt::Key_MonBrightnessDown, "MonBrightnessDown" },
+        { Qt::Key_0, "0" },
+        { Qt::Key_1, "1" },
+        { Qt::Key_2, "2" },
+        { Qt::Key_3, "3" },
+        { Qt::Key_4, "4" },
+        { Qt::Key_5, "5" },
+        { Qt::Key_6, "6" },
+        { Qt::Key_7, "7" },
+        { Qt::Key_8, "8" },
+        { Qt::Key_9, "9" },
+        { Qt::Key_Asterisk, "Asterisk" },
+        { Qt::Key_NumberSign, "NumberSign" },
+        { Qt::Key_Up, QString() },
+        { Qt::Key_Down, QString() },
+        { Qt::Key_Left, QString() },
+        { Qt::Key_Right, QString() },
+        //{ Qt::Key_, QString() },
+        { Qt::Key_A, "A" },
+        { Qt::Key_B, "B" },
+        { Qt::Key_C, "C" },
+        { Qt::Key_D, "D" },
+        { Qt::Key_E, "E" },
+        { Qt::Key_F, "F" },
+        { Qt::Key_G, "G" },
+        { Qt::Key_H, "H" },
+        { Qt::Key_I, "I" },
+        { Qt::Key_J, "J" },
+        { Qt::Key_K, "K" },
+        { Qt::Key_L, "L" },
+        { Qt::Key_M, "M" },
+        { Qt::Key_N, "N" },
+        { Qt::Key_O, "O" },
+        { Qt::Key_P, "P" },
+        { Qt::Key_Q, "Q" },
+        { Qt::Key_R, "R" },
+        { Qt::Key_S, "S" },
+        { Qt::Key_T, "T" },
+        { Qt::Key_U, "U" },
+        { Qt::Key_V, "V" },
+        { Qt::Key_W, "W" },
+        { Qt::Key_X, "X" },
+        { Qt::Key_Y, "Y" },
+        { Qt::Key_Z, "Z" },
+        { Qt::Key_Comma, "," },
+        { Qt::Key_Period, "." },
+        { Qt::Key_Alt, QString() },
+        { Qt::Key_Shift, QString() },
+        { Qt::Key_Tab, "\t"  },
+        { Qt::Key_Space, QString(" ") },
+        //{ Qt::KEY_, QString() },
+        { Qt::Key_Explorer, "Explorer" },
+        //{ Qt::Key_, QString() },
+        { Qt::Key_Enter, "\r" },
+        { Qt::Key_Backspace, "\b" },
+        { Qt::Key_QuoteLeft, "`" },
+        { Qt::Key_Apostrophe, "'" },
+        { Qt::Key_Minus, "-" },
+        { Qt::Key_Equal, "=" },
+        { Qt::Key_BracketLeft, "[" },
+        { Qt::Key_BracketRight, "]" },
+        { Qt::Key_Backslash, "\\" },
+        { Qt::Key_Semicolon, ";" },
+        { Qt::Key_Slash, "/" },
+        { Qt::Key_At, "At" },
+        { Qt::Key_Plus, "+" },
+        { Qt::Key_Menu, "Menu" },
+        { Qt::Key_PageUp, QString() },
+        { Qt::Key_PageDown, QString() },
+        { Qt::Key_Escape, QString() },
+        { Qt::Key_Delete, QString() },
+        { Qt::Key_Control, QString() },
+        { Qt::Key_CapsLock, QString() },
+        { Qt::Key_ScrollLock, "ScrollLock" },
+        { Qt::Key_Meta, QString() },
+        { Qt::Key_SysReq, "SysReq" },
+        { Qt::Key_Pause, "Pause" },
+        { Qt::Key_End, QString() },
+        { Qt::Key_Insert, QString() },
+        { Qt::Key_Forward, "Forward" },
+        { Qt::Key_MediaPlay, "MediaPlay" },
+        { Qt::Key_MediaPause, "MediaPause" },
+        { Qt::Key_MediaRecord, "MediaRecord," },
+        { Qt::Key_F1, QString() },
+        { Qt::Key_F2, QString() },
+        { Qt::Key_F3, QString() },
+        { Qt::Key_F4, QString() },
+        { Qt::Key_F5, QString() },
+        { Qt::Key_F6, QString() },
+        { Qt::Key_F7, QString() },
+        { Qt::Key_F8, QString() },
+        { Qt::Key_F9, QString() },
+        { Qt::Key_F10, QString() },
+        { Qt::Key_F11, QString() },
+        { Qt::Key_F12, QString() },
+        { Qt::Key_NumLock, QString() },
+        { Qt::Key_ParenLeft, QString() },
+        { Qt::Key_ParenRight, QString() },
+        { Qt::Key_Sleep, "Sleep" },
+        { Qt::Key_Zenkaku_Hankaku, "Zenkaku_Hankaku" },
+        { Qt::Key_Katakana, "Katakana," },
+        { Qt::Key_Hiragana, "Hiragana" },
+        { Qt::Key_Henkan, "Henkan" },
+        { Qt::Key_Hiragana_Katakana, "Hiragana_Katakana" },
+        { Qt::Key_Muhenkan, "Muhenkan" },
+        { Qt::Key_Return, "\r" },
+        { Qt::Key_Hangul, "Hangul" },
+        { Qt::Key_Hangul_Hanja, "Hangul_Hanja" },
+        { Qt::Key_yen, "yen" },
+        { Qt::Key_Stop, "Stop" },
+        { Qt::Key_Undo, "Undo" },
+        { Qt::Key_Copy, "Copy" },
+        { Qt::Key_Open, "Open" },
+        { Qt::Key_Paste, "Paste" },
+        { Qt::Key_Find, "Find" },
+        { Qt::Key_Cut, "Cut" },
+        { Qt::Key_Help, "Help" },
+        { Qt::Key_Refresh, "Refresh" },
+        { Qt::Key_Exit, "Exit" },
+        { Qt::Key_New, "New" },
+        { Qt::Key_Redo, "Redo" },
+        { Qt::Key_Close, "Close" },
+        { Qt::Key_Play, "Play" },
+        { Qt::Key_Print, "Print" },
+        { Qt::Key_Finance, "Finance" },
+        { Qt::Key_Cancel, "Cancel" },
+        { Qt::Key_KeyboardBrightnessDown, "KeyboardBrightnessDown" },
+        { Qt::Key_KeyboardBrightnessUp, "KeyboardBrightnessUp" },
+        { Qt::Key_Send, "Send" },
+        { Qt::Key_Reply, "Reply" },
+        { Qt::Key_Save, "Save" },
+        { Qt::Key_Documents, "Documents" },
+        { Qt::Key_Go, "Go" },
+        { Qt::Key_Info, "Info" },
+        { Qt::Key_Subtitle, "Subtitle" },
+        { Qt::Key_CD, "CD" },
+        { Qt::Key_Video, "Video" },
+        { Qt::Key_Memo, "Memo" },
+        { Qt::Key_Calendar, "Calendar" },
+        { Qt::Key_Red, "Red" },
+        { Qt::Key_Green, "Green" },
+        { Qt::Key_Yellow, "Yellow" },
+        { Qt::Key_Blue, "Blue" },
+        { Qt::Key_ChannelUp, "ChannelUp" },
+        { Qt::Key_ChannelDown, "ChannelDown" },
+        { Qt::Key_Game, "Game" },
+        { Qt::Key_ZoomIn, "ZoomIn" },
+        { Qt::Key_ZoomOut, "ZoomOut" },
+        { Qt::Key_News, "News" },
+        { Qt::Key_Messenger, "Messenger" },
+        { Qt::Key_ScreenSaver, "ScreenSaver" },
+        { Qt::Key_WakeUp, "WakeUp" },
+        { Qt::Key_Xfer, "Xfer" },
+        { Qt::Key_Eject, "Eject" },
+        { Qt::Key_F13, "F13" },
+        { Qt::Key_F14, "F14" },
+        { Qt::Key_F15, "F15" },
+        { Qt::Key_F16, "F16" },
+        { Qt::Key_F17, "F17" },
+        { Qt::Key_F18, "F18" },
+        { Qt::Key_F19, "F19" },
+        { Qt::Key_F20, "F20" },
+        { Qt::Key_F21, "F21" },
+        { Qt::Key_F22, "F22" },
+        { Qt::Key_F23, "F23" },
+        { Qt::Key_F24, "F24" },
+        { Qt::Key_Suspend, "Suspend" },
+        { Qt::Key_Question, "Question" },
+        { Qt::Key_Shop, "Shop" },
+        { Qt::Key_Battery, "Battery" },
+        { Qt::Key_Bluetooth, "Bluetooth" },
+        { Qt::Key_WLAN, "WLAN" },
+        { Qt::Key_UWB, "UWB" },
+        { Qt::Key_AsciiTilde, "~"},
+        { Qt::Key_Exclam, "!" },
+        { Qt::Key_At, "@" },
+        { Qt::Key_NumberSign, "#" },
+        { Qt::Key_Dollar, "$" },
+        { Qt::Key_Percent, "%" },
+        { Qt::Key_AsciiCircum, "^" },
+        { Qt::Key_Ampersand, "&" },
+        { Qt::Key_Asterisk, "*" },
+        { Qt::Key_ParenLeft, "(" },
+        { Qt::Key_ParenRight, ")" },
+        { Qt::Key_Underscore, "_" },
+        { Qt::Key_Plus, "+" },
+        { Qt::Key_BraceLeft, "{"},
+        { Qt::Key_BraceRight, "}"},
+        { Qt::Key_Colon, ":" },
+        { Qt::Key_QuoteDbl, R"(")" },
+        { Qt::Key_Bar, "|" },
+        { Qt::Key_Less, "<" },
+        { Qt::Key_Greater, ">" },
+        { Qt::Key_Question, "?" },
+        { Qt::Key_Clear, QString()}
+    };
+    auto result = QString();
+    /* Ctril按下*/
+    if (modifiers.testFlag(Qt::ControlModifier) && (key == Qt::Key_Return
+                                                    || key == Qt::Key_Enter)) {
+        result = "\n";
+    } else {
+        result = sKeyTextMap.value(key, QString());
+        bool bPressedShift = modifiers.testFlag(Qt::ShiftModifier);
+        /* 字符键盘 && 小写 */
+        if (Qt::Key_A <= key && (Qt::Key_Z >= key)) {
+            /* KEY_CAPS_LOCK打开 - KEY_SHIFT_LEFT按下 || 都没打开 */
+            if ((isKeyLockActive(KEY_CAPS_LOCK) && bPressedShift) ||
+                (!isKeyLockActive(KEY_CAPS_LOCK) && (!bPressedShift))) {
+                /* 小写 */
+                result = result.toLower();
+            }
+        }
+    }
+    return result;
+}
+
+Qt::KeyboardModifiers QOhKeys::keyboardModifiers()
+{
+    Qt::KeyboardModifiers mods(Qt::NoModifier);
+
+    if (isKeyPressed(KEY_SHIFT_LEFT) || isKeyPressed(KEY_SHIFT_RIGHT)) {
+        mods |= Qt::ShiftModifier;
+    }
+
+    if (isKeyPressed(KEY_CTRL_LEFT) || isKeyPressed(KEY_CTRL_RIGHT)) {
+        mods |= Qt::ControlModifier;
+    }
+
+    if (isKeyPressed(KEY_ALT_LEFT) || isKeyPressed(KEY_ALT_RIGHT)) {
+        mods |= Qt::AltModifier;
+    }
+
+    if (isKeyPressed(KEY_META_LEFT) || isKeyPressed(KEY_META_RIGHT)) {
+        mods |= Qt::MetaModifier;
+    }
+    return mods;
+}
+
+Qt::KeyboardModifiers QOhKeys::metaModifier()
+{
+    Qt::KeyboardModifiers mods(Qt::NoModifier);
+    if (isKeyPressed(KEY_META_LEFT) || isKeyPressed(KEY_META_RIGHT)) {
+        mods |= Qt::MetaModifier;
+    }
+    return mods;
+}
+
+Qt::KeyboardModifiers QOhKeys::ohKeys2Qt(int64_t keys)
+{
+    Qt::KeyboardModifiers km = Qt::NoModifier;
+    if (keys & ARKUI_MODIFIER_KEY_CTRL) {
+        km |= Qt::ControlModifier;
+    }
+    if (keys & ARKUI_MODIFIER_KEY_SHIFT) {
+        km |= Qt::ShiftModifier;
+    }
+    if (keys & ARKUI_MODIFIER_KEY_ALT) {
+        km |= Qt::AltModifier;
+    }
+    return km;
+}
+
+bool QOhKeys::isKeypad(int32_t keyCode)
+{
+    return keyCode >= KEY_NUM_LOCK && keyCode <= KEY_NUMPAD_RIGHT_PAREN;
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/openharmony/qohkeys.h b/src/plugins/platforms/openharmony/qohkeys.h
new file mode 100644
index 00000000000..1dfe3b816ab
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohkeys.h
@@ -0,0 +1,38 @@
+#ifndef QOHKEYS_H
+#define QOHKEYS_H
+
+#include <ace/xcomponent/native_xcomponent_key_event.h>
+#include <multimodalinput/oh_input_manager.h>
+
+#include <qnamespace.h>
+#include "qohevent.h"
+
+QT_BEGIN_NAMESPACE
+
+class QOhKeys
+{
+public:
+    static bool isKeyPressed(int32_t keyCode);
+
+    static bool isKeyLockActive(int32_t keyCode);
+
+    static Qt::Key ohCode2QtKey(int32_t keyCode, Qt::KeyboardModifiers modifiers);
+
+    static Qt::KeyboardModifier ohKeyboardModifier2QtKeyboardModifier(int32_t keyCode);
+
+    static bool autoRepeat(int32_t type, int32_t code);
+
+    static QString key2String(Qt::Key key, Qt::KeyboardModifiers modifiers);
+
+    static Qt::KeyboardModifiers keyboardModifiers();
+
+    static Qt::KeyboardModifiers metaModifier();
+
+    static Qt::KeyboardModifiers ohKeys2Qt(int64_t keys);
+
+    static bool isKeypad(int32_t keyCode);
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHKEYS_H
diff --git a/src/plugins/platforms/openharmony/qohmain.cpp b/src/plugins/platforms/openharmony/qohmain.cpp
new file mode 100644
index 00000000000..6b367466ad8
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohmain.cpp
@@ -0,0 +1,227 @@
+#include <dlfcn.h>
+#include <QString>
+#include <QDir>
+#include <qnapi.h>
+#include <qos/qos.h>
+#include <QByteArray>
+#include <qopenharmony.h>
+#include <QVarLengthArray> /* Qt 6 only modify */
+#include <napi/native_api.h>
+#include <private/qopenharmony_p.h>
+#include <QtCore/qopenharmonydefines.h>
+#include <qpa/qwindowsysteminterface_p.h>
+
+
+#include "qohmain.h"
+#include "qjswant.h"
+#include "qjscontext.h"
+#include "qjsability.h"
+#include "qohauxiliary.h"
+#include "qjsabilitystage.h"
+#include "qjsabilityfactory.h"
+#include "qohsystemtrayicon.h"
+#include "qohnativewindowmanager.h"
+
+Q_LOGGING_CATEGORY(openharmonyQPA, "openharmony.qpa");
+
+extern "C" typedef int (*Main)(int, char **); //use the standard main method to start the application
+pthread_t m_qtAppThread = 0;
+static QList<QByteArray> m_applicationParams;
+
+static void *startMainMethod(void *arg)
+{
+    Q_UNUSED(arg);
+    OH_QoS_SetThreadQoS(QOS_USER_INTERACTIVE);
+    QoS_Level level;
+    OH_QoS_GetThreadQoS(&level);
+    if (level != QOS_USER_INTERACTIVE)
+        LOGW("set qt main thread level failed");
+
+    QByteArray fileName = m_applicationParams.first();
+    LOGI("load qt application %{public}s", fileName.constData());
+
+    //look for main()
+    // Obtain a handle to the main library (the library that contains the main() function).
+    void *mainLibraryHnd = dlopen(fileName.constData(), 0);
+    if (Q_UNLIKELY(!mainLibraryHnd)) {
+        QString error = QString("Failed to load QT application '%1': %2")
+            .arg(fileName.constData())
+            .arg(dlerror());
+        LOGE("%{public}s", error.toUtf8().constData());
+        return nullptr;
+    }
+    static Main mainMethod = nullptr;
+    mainMethod = (Main)dlsym(mainLibraryHnd, "main");
+    if (Q_UNLIKELY(!mainMethod)) {
+        QString error = QString("Failed to find main function: %1").arg(dlerror());
+        LOGE("%{public}s", error.toUtf8().constData());
+        return nullptr;
+    }
+
+    QVarLengthArray<const char *> params(m_applicationParams.size());
+
+    for (int i = 0; i < m_applicationParams.size(); i++)
+        params[i] = static_cast<const char *>(m_applicationParams[i].constData());
+
+    int ret = mainMethod(m_applicationParams.length(), const_cast<char **>(params.data()));
+    Q_UNUSED(ret);
+    if (mainLibraryHnd) {
+        int res = dlclose(mainLibraryHnd);
+        if (res < 0)
+            LOGE("dlclose failed: %{public}s", dlerror());
+    }
+
+    //非gui程序退出
+    qNativeWindowManager->destoryAllAbility();
+    return nullptr;
+}
+
+static bool parseModule(const Napi::CallbackInfo &info)
+{
+    if (info.Length() < 1)
+        return false;
+    auto ability = QNapi::getFirst<Napi::Object>(info);
+    if (ability.IsEmpty() || ability.IsUndefined())
+        return false;
+    auto want = QNapi::get<Napi::Object>(ability, "launchWant");
+    if (want.IsEmpty() || want.IsUndefined())
+        return false;
+    auto bundleName = QNapi::get<QString>(want, "bundleName");
+    auto moduleName = QNapi::get<QString>(want, "moduleName");
+    auto abilityName = QNapi::get<QString>(want, "abilityName");
+    QtOh::setBundleName(bundleName);
+    QtOh::setModuleName(moduleName);
+    QtOh::setAbilityName(abilityName);
+    return true;
+}
+
+static Napi::Value startQtApplication(const Napi::CallbackInfo& info)
+{
+    static bool firstStart = true;
+    if (firstStart) {
+        if (!parseModule(info))
+            return QNapi::create(false);
+    }
+    QJsAbility *ability = QJsAbilityFactory::create(info);
+    if (ability == nullptr)
+        return QNapi::create(false);
+    qNativeWindowManager->handleTopWindowCreated(ability);
+    if (!firstStart) {
+        return QNapi::create(true);
+    }
+    firstStart = false;
+
+    QJsContext *context = ability->context();
+    if (context == nullptr) {
+        LOGE("context is null");
+        return QNapi::create(false);
+    }
+    QByteArray bundle = context->bundleCodeDir().toLatin1();
+    if (bundle.isEmpty()) {
+        LOGE("args is vaild");
+        return QNapi::create(false);
+    }
+
+#if defined(Q_PROCESSOR_ARM_64)
+    QByteArray libDir = bundle + "/libs/arm64";
+#elif defined(Q_PROCESSOR_ARM_32)
+    QByteArray libDir = bundle + "/libs/arm";
+#elif defined(Q_PROCESSOR_X86_64)
+    QByteArray libDir = bundle + "/libs/x86_64";
+#elif defined(Q_PROCESSOR_X86)
+    QByteArray libDir = bundle + "/libs/x86";
+#endif
+    QDir::setCurrent(libDir);
+    QByteArrayList qmlPluginsDirs = { libDir + "/qml" };
+    QByteArrayList qmls = { bundle + "/" + ability->launchWant()->moduleName().toLocal8Bit() + "/resources/rawfile" };
+    QString qmlfilesDir = context->qmlDir();
+    if (!qmlfilesDir.isEmpty())
+        qmls << qmlfilesDir.toLocal8Bit();
+
+    // Helper function to set environment variables
+    auto setEnv = [](const char *name, const QByteArray &value) {
+        if (::setenv(name, value.constData(), 1) != 0) {
+            LOGE("Can't set environment for %{public}s", name);
+        }
+    };
+
+    setEnv("QT_HARMONY_QML_FILE_DIR", qPrintable(qmlfilesDir));
+    setEnv("QT_QPA_PLATFORM_PLUGIN_PATH", libDir);
+    //setEnv("QML_DISABLE_DISK_CACHE", "1");
+    setEnv("QT_PLUGIN_PATH", libDir);
+    setEnv("QT_HARMONY_QML_PLUGINS_PATH", qmlPluginsDirs.join(":"));
+    setEnv("QML2_IMPORT_PATH", qmls.join(":"));
+#if 0
+    setEnv("QT_DEBUG_PLUGINS", "1");
+#endif
+    qputenv("TMPDIR", context->applicationContext()->tempDir().toLatin1());
+    ability->launchWant()->saveParamsToEnv();
+
+    m_applicationParams = QList<QByteArray>() << ability->launchQtApplication();
+    QList<QByteArray> params = ability->launchQtParams();
+    params.removeAll(" ");
+    params.removeAll("");
+    m_applicationParams << params;
+
+    if (m_applicationParams.empty()) {
+        LOGE("No QT application specified");
+        return QNapi::create(false);
+    }
+    QByteArray fileName = m_applicationParams.first();
+    m_applicationParams[0] = libDir + "/" + fileName;
+
+    QJsContext *applicationContext = context->applicationContext();
+    QtOh::setDir("DIRECTORY_CACHE", applicationContext->cacheDir());
+    QtOh::setDir("DIRECTORY_TEMP", applicationContext->tempDir());
+    QtOh::setDir("DIRECTORY_BUNDLE", applicationContext->bundleCodeDir());
+    QtOh::setDir("DIRECTORY_FILES", applicationContext->filesDir());
+    QtOh::setDir("DIRECTORY_RESOURCE", context->resourceDir());
+    QtOh::setDir("DIRECTORY_HAP_FILES", context->filesDir());
+
+    pthread_create(&m_qtAppThread, nullptr, startMainMethod, nullptr);
+
+    return QNapi::create(true);
+}
+
+static Napi::Value handleOnNewWant(const Napi::CallbackInfo& info)
+{
+    if (info.Length() < 2)
+        return QNapi::create(false);
+
+    QList<QByteArray> fileUris;
+    Napi::Object jsWant = QNapi::getFirst<Napi::Object>(info);
+    QJsWant want(jsWant);
+    fileUris << want.launchParams();
+    for (QByteArray fileName : fileUris) {
+        if (fileName.isEmpty())
+            continue;
+        QString path = QString::fromUtf8(fileName);
+        if (!path.isEmpty()) {
+            QUrl result = QUrl::fromLocalFile(path);
+            QtOh::runOnQtMainThread([](const QUrl &url){
+                QWindowSystemInterface::handleFileOpenEvent(url);
+            }, result);
+        }
+    }
+
+    return QNapi::create(true);
+}
+
+Napi::Object Init(Napi::Env env, Napi::Object exports) {
+    static bool inited = false;
+    if (!inited) {
+        QtOh::setUIEnv(env);
+        QJsAbilityStage::init(env, exports);
+        QOhSystemTrayIcon::init(env, exports);
+        QNapi::set(exports, "handleOnNewWant", handleOnNewWant);
+        QNapi::set(exports, "startQtApplication", startQtApplication);
+        /* NOTE QGuiApplication根据tabletEvent合成鼠标事件 */
+        QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
+        inited = true;
+    }
+
+    QOhNativeWindowManager::init(env, exports);
+    return exports;
+}
+
+NODE_API_MODULE(plugins_platforms_qopenharmony, Init)
diff --git a/src/plugins/platforms/openharmony/qohmain.h b/src/plugins/platforms/openharmony/qohmain.h
new file mode 100644
index 00000000000..ff357d817fe
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohmain.h
@@ -0,0 +1,25 @@
+#ifndef QOHMAIN_H
+#define QOHMAIN_H
+
+#include <QLoggingCategory>
+#include <arkui/native_node.h>
+QT_BEGIN_NAMESPACE
+
+struct Node {
+    ArkUI_NodeType nodeType; // Type of the node. The value can be ARKUI_NODE_XCOMPONENT or other types supported in later versions.
+    ArkUI_NodeHandle node; // ARKUI_NODE_XCOMPONENT type or other.
+    ArkUI_NodeHandle container; // Must be of type ARKUI_NODE_STACK.
+    char nodeOwner[8]; // Describes the body of the Node structure to be created, such as "QT," "CEF," "SDL2," "FLUT".
+    void* nodePrivate; // Structure used for the definition of the nodeOwner body record itself.
+};
+
+struct WindowNode : Node
+{
+    void *window;
+};
+
+Q_DECLARE_LOGGING_CATEGORY(openharmonyQPA)
+
+QT_END_NAMESPACE
+
+#endif //QOHMAIN_H
diff --git a/src/plugins/platforms/openharmony/qohnativenodeapi.cpp b/src/plugins/platforms/openharmony/qohnativenodeapi.cpp
new file mode 100644
index 00000000000..9125cba6cdb
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohnativenodeapi.cpp
@@ -0,0 +1,115 @@
+#include "qohnativenodeapi.h"
+#include <arkui/native_interface.h>
+
+QT_BEGIN_NAMESPACE
+
+ArkUI_NativeNodeAPI_1 *QOhNativeNodeAPI::m_nativeNodeAPI = []{
+    return reinterpret_cast<ArkUI_NativeNodeAPI_1 *>(
+            OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1"));
+}();
+
+ArkUI_NativeNodeAPI_1 *QOhNativeNodeAPI::nativeNodeAPI()
+{
+    return m_nativeNodeAPI;
+}
+
+QSharedPointer<QOhNativeNodeAPI> QOhNativeNodeAPI::getOrCreateForNode(QOhWindowNode *node)
+{
+    if (node == nullptr)
+        return nullptr;
+    if (m_apiForNode.contains(node))
+        return m_apiForNode.value(node);
+    QSharedPointer<QOhNativeNodeAPI> api(new QOhNativeNodeAPI());
+    m_apiForNode.insert(node, api);
+    return api;
+}
+
+ArkUI_NodeHandle QOhNativeNodeAPI::createNode(ArkUI_NodeType type)
+{
+    if (m_nativeNodeAPI->createNode == nullptr)
+        return nullptr;
+    if (type == ARKUI_NODE_XCOMPONENT) {
+        m_xcomponent = m_nativeNodeAPI->createNode(type);
+        return m_xcomponent;
+    } else if (type == ARKUI_NODE_STACK) {
+        m_stack = m_nativeNodeAPI->createNode(type);
+        return m_stack;
+    }
+    return nullptr;
+}
+
+QOhNativeNodeAPI::QOhNativeNodeAPI()
+    : m_stack(nullptr)
+    , m_xcomponent(nullptr)
+{
+
+}
+
+bool QOhNativeNodeAPI::setAttribute(ArkUI_NodeHandle node, ArkUI_NodeAttributeType attribute, const ArkUI_AttributeItem *item)
+{
+    if (!has(&ArkUI_NativeNodeAPI_1::setAttribute)) {
+        LOGE("node napi setAttribute nullptr error");
+        return false;
+    }
+    LOGI("QOhNativeNodeAPI::setAttribute %{public}s", QtOhArkUI::nodeAttributeTypeToString(attribute).data());
+    auto code = m_nativeNodeAPI->setAttribute(node, attribute, item);
+    if (!QtOhArkUI::ErrorCode::checkCode(code)) {
+        QtOhArkUI::ErrorCode::printErrorCode(QString("QOhNativeNodeAPI::setAttribute %1 failed:").arg(QtOhArkUI::nodeAttributeTypeToString(attribute).data()), code);
+        return false;
+    }
+    return true;
+}
+
+bool QOhNativeNodeAPI::addChild(ArkUI_NodeHandle parent, ArkUI_NodeHandle child)
+{
+    if (!has(&ArkUI_NativeNodeAPI_1::addChild)) {
+        LOGE("node napi addChild nullptr error");
+        return false;
+    }
+    auto code = m_nativeNodeAPI->addChild(parent, child);
+    if (!QtOhArkUI::ErrorCode::checkCode(code)) {
+        QtOhArkUI::ErrorCode::printErrorCode("addChild failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+bool QOhNativeNodeAPI::removeChild(ArkUI_NodeHandle parent, ArkUI_NodeHandle child)
+{
+    if (!has(&ArkUI_NativeNodeAPI_1::removeChild)) {
+        LOGE("node napi removeChild nullptr error");
+        return false;
+    }
+    auto code = m_nativeNodeAPI->removeChild(parent, child);
+    if (!QtOhArkUI::ErrorCode::checkCode(code)) {
+        QtOhArkUI::ErrorCode::printErrorCode("removeChild failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+ArkUI_NodeHandle QOhNativeNodeAPI::parent(ArkUI_NodeHandle handle)
+{
+    if (!has(&ArkUI_NativeNodeAPI_1::getParent)) {
+        LOGE("node napi getParent nullptr error");
+        return nullptr;
+    }
+    return m_nativeNodeAPI->getParent(handle);
+}
+
+bool QOhNativeNodeAPI::setLengthMetricUnit(ArkUI_NodeHandle handle, ArkUI_LengthMetricUnit unit)
+{
+    if (!has(&ArkUI_NativeNodeAPI_1::setLengthMetricUnit)) {
+        LOGE("node napi setLengthMetricUnit nullptr error");
+        return false;
+    }
+    auto code = m_nativeNodeAPI->setLengthMetricUnit(m_stack, unit);
+    if (!QtOhArkUI::ErrorCode::checkCode(code)) {
+        QtOhArkUI::ErrorCode::printErrorCode("setLengthMetricUnit failed: ", code);
+        return false;
+    }
+    return true;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/openharmony/qohnativenodeapi.h b/src/plugins/platforms/openharmony/qohnativenodeapi.h
new file mode 100644
index 00000000000..d3193738aa4
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohnativenodeapi.h
@@ -0,0 +1,241 @@
+#ifndef QOHNATIVENODEAPI_H
+#define QOHNATIVENODEAPI_H
+
+#include <QHash>
+#include <arkui/native_node.h>
+#include <cstdint>
+#include <utility>
+#include <type_traits>
+#include <qopenharmonydefines.h>
+#include <QSharedPointer>
+
+#include "qoharkui.h"
+
+QT_BEGIN_NAMESPACE
+class QOhWindowNode;
+
+template<typename... Args>
+ArkUI_NumberValue* createValue(Args&&... args) {
+    ArkUI_NumberValue* values = new ArkUI_NumberValue[sizeof...(Args)];
+    size_t index = 0;
+
+    auto initValue = [&](auto&& arg) {
+        using ArgType = std::decay_t<decltype(arg)>;
+
+        if constexpr (std::is_same_v<ArgType, float>) {
+            values[index].f32 = static_cast<float>(arg);
+        } else if constexpr (std::is_same_v<ArgType, int32_t>) {
+            values[index].i32 = static_cast<int32_t>(arg);
+        } else if constexpr (std::is_same_v<ArgType, uint32_t>) {
+            values[index].u32 = static_cast<uint32_t>(arg);
+        } else if constexpr (std::is_enum_v<ArgType>) {
+            values[index].i32 = static_cast<std::underlying_type_t<ArgType>>(arg);
+        } else if constexpr (std::is_same_v<ArgType, bool>) {
+            values[index].i32 = arg ? 1 : 0;
+        } else if constexpr (std::is_same_v<ArgType, double>) {
+            values[index].f32 = static_cast<float>(arg);
+        } else {
+            values[index].i32 = static_cast<int32_t>(arg);
+        }
+        index++;
+    };
+
+    (initValue(std::forward<Args>(args)), ...);
+    return values;
+}
+
+struct OhArkUIAttributeItem
+{
+    OhArkUIAttributeItem(ArkUI_AttributeItem item): _item(item) {}
+    ~OhArkUIAttributeItem() { if ( _item.value != nullptr) delete[] _item.value; }
+    ArkUI_AttributeItem _item;
+};
+
+template<typename... Args>
+OhArkUIAttributeItem createAttributeItem(Args&&... args) {
+    return OhArkUIAttributeItem(ArkUI_AttributeItem {
+        .value = createValue(std::forward<Args>(args)...),
+        .size = static_cast<int32_t>(sizeof...(Args)),
+        .string = nullptr,
+        .object = nullptr
+    });
+}
+
+inline OhArkUIAttributeItem createAttributeItem(const char* str) {
+    return OhArkUIAttributeItem(ArkUI_AttributeItem {
+        .value = nullptr,
+        .size = 0,
+        .string = str,
+        .object = nullptr
+    });
+}
+
+template<typename T>
+OhArkUIAttributeItem createAttributeItem(T* obj) {
+    return OhArkUIAttributeItem(ArkUI_AttributeItem {
+        .value = nullptr,
+        .size = 0,
+        .string = nullptr,
+        .object = static_cast<void*>(obj)
+    });
+}
+
+class QOhNativeNodeAPI
+{
+public:
+    struct XCompoentType {};
+    struct StackType {};
+    static ArkUI_NativeNodeAPI_1 *nativeNodeAPI();
+    static QSharedPointer<QOhNativeNodeAPI> getOrCreateForNode(QOhWindowNode *node);
+
+    template<typename Type = StackType>
+    void attach(ArkUI_NodeHandle handle) {
+        if constexpr (std::is_same_v<Type, XCompoentType>) {
+            m_xcomponent = handle;
+            return;
+        }
+        m_stack = handle;
+    }
+
+    template<typename Type = StackType>
+    static QOhNativeNodeAPI *createForHandle(ArkUI_NodeHandle handle) {
+        QOhNativeNodeAPI *api = new QOhNativeNodeAPI;
+        if constexpr (std::is_same_v<Type, XCompoentType>) {
+            api->m_xcomponent = handle;
+            return api;
+        }
+        api->m_stack = handle;
+        return api;
+    }
+
+    ArkUI_NodeHandle createNode(ArkUI_NodeType type);
+
+    template<typename Type = StackType, typename... Args>
+    bool setAttribute(ArkUI_NodeAttributeType attribute, Args&&... args)
+    {
+        OhArkUIAttributeItem item = createAttributeItem(args...);
+        return setAttribute(handle<Type>(), attribute, &item._item);
+    }
+
+    template<typename Type = StackType>
+    const ArkUI_AttributeItem *getAttribute(ArkUI_NodeAttributeType attribute)
+    {
+        if (!has(&ArkUI_NativeNodeAPI_1::getAttribute)) {
+            LOGE("node napi getAttribute nullptr error");
+            return nullptr;
+        }
+        return m_nativeNodeAPI->getAttribute(handle<Type>(), attribute);
+    }
+
+    bool addChild(ArkUI_NodeHandle parent, ArkUI_NodeHandle child);
+    bool removeChild(ArkUI_NodeHandle parent, ArkUI_NodeHandle child);
+
+    template<typename Type = StackType>
+    bool registerNodeEvent(ArkUI_NodeEventType eventType,
+                           int32_t targetId, void* userData) {
+        if (!has(&ArkUI_NativeNodeAPI_1::registerNodeEvent)) {
+            LOGE("node napi registerNodeEvent nullptr error");
+            return false;
+        }
+        auto code = m_nativeNodeAPI->registerNodeEvent(handle<Type>(), eventType, targetId, userData);
+        if (!QtOhArkUI::ErrorCode::checkCode(code)) {
+            QtOhArkUI::ErrorCode::printErrorCode("registerNodeEvent failed: ", code);
+            return false;
+        }
+        return true;
+    }
+
+    template<typename Type = StackType>
+    bool addNodeEventReceiver(void (*eventReceiver)(ArkUI_NodeEvent* event)) {
+        if (!has(&ArkUI_NativeNodeAPI_1::addNodeEventReceiver)) {
+            LOGE("node napi addNodeEventReceiver nullptr error");
+            return false;
+        }
+        auto code = m_nativeNodeAPI->addNodeEventReceiver(handle<Type>(), eventReceiver);
+        if (!QtOhArkUI::ErrorCode::checkCode(code)) {
+            QtOhArkUI::ErrorCode::printErrorCode("addNodeEventReceiver failed: ", code);
+            return false;
+        }
+        return true;
+    }
+
+    template<typename Type = StackType>
+    void unregisterNodeEvent(ArkUI_NodeEventType eventType) {
+        if (!has(&ArkUI_NativeNodeAPI_1::unregisterNodeEvent)) {
+            LOGE("node napi unregisterNodeEvent nullptr error");
+            return;
+        }
+        m_nativeNodeAPI->unregisterNodeEvent(handle<Type>(), eventType);
+    }
+
+    template<typename Type = StackType>
+    bool removeNodeEventReceiver(void (*eventReceiver)(ArkUI_NodeEvent* event)) {
+        if (!has(&ArkUI_NativeNodeAPI_1::removeNodeEventReceiver)) {
+            LOGE("node napi removeNodeEventReceiver nullptr error");
+            return false;
+        }
+        auto code = m_nativeNodeAPI->removeNodeEventReceiver(handle<Type>(), eventReceiver);
+        if (!QtOhArkUI::ErrorCode::checkCode(code)) {
+            QtOhArkUI::ErrorCode::printErrorCode("removeNodeEventReceiver failed: ", code);
+            return false;
+        }
+        return true;
+    }
+
+    template<typename Type = StackType>
+    uint32_t totalChildCount() {
+        if (!has(&ArkUI_NativeNodeAPI_1::getTotalChildCount)) {
+            LOGE("node napi getTotalChildCount nullptr error");
+            return 0;
+        }
+        return m_nativeNodeAPI->getTotalChildCount(handle<Type>());
+    }
+
+    template<typename Type = StackType>
+    ArkUI_NodeHandle childAt(int32_t position) {
+        if (!has(&ArkUI_NativeNodeAPI_1::getChildAt)) {
+            LOGE("node napi getChildAt nullptr error");
+            return nullptr;
+        }
+        return m_nativeNodeAPI->getChildAt(handle<Type>(), position);
+    }
+
+    ArkUI_NodeHandle parent(ArkUI_NodeHandle handle);
+
+    template <typename T, typename Member>
+    static bool has(Member T::*member) {
+        return (m_nativeNodeAPI != nullptr) && ((m_nativeNodeAPI->*member) != nullptr);
+    }
+
+    template<typename Type = StackType>
+    void disposeNode() {
+        m_nativeNodeAPI->disposeNode(handle<Type>());
+    }
+
+    template<typename Type = StackType>
+    bool setLengthMetricUnit(ArkUI_LengthMetricUnit unit) {
+        return setLengthMetricUnit(handle<Type>(), unit);
+    }
+    bool setLengthMetricUnit(ArkUI_NodeHandle handle, ArkUI_LengthMetricUnit unit);
+
+private:
+    QOhNativeNodeAPI();
+    bool setAttribute(ArkUI_NodeHandle node, ArkUI_NodeAttributeType attribute, const ArkUI_AttributeItem* item);
+    template<typename Type>
+    ArkUI_NodeHandle handle() {
+        ArkUI_NodeHandle target = m_stack;
+        if constexpr (std::is_same_v<Type, XCompoentType>) {
+            target = m_xcomponent;
+        }
+        return target;
+    }
+private:
+    ArkUI_NodeHandle m_stack = nullptr;
+    ArkUI_NodeHandle m_xcomponent = nullptr;
+    static ArkUI_NativeNodeAPI_1 *m_nativeNodeAPI;
+    static inline QHash<QOhWindowNode *, QSharedPointer<QOhNativeNodeAPI>> m_apiForNode = {};
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHNATIVENODEAPI_H
diff --git a/src/plugins/platforms/openharmony/qohnativevsync.cpp b/src/plugins/platforms/openharmony/qohnativevsync.cpp
new file mode 100644
index 00000000000..5d56197fafc
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohnativevsync.cpp
@@ -0,0 +1,136 @@
+#include "qohnativevsync.h"
+#include "qohmain.h"
+#include "qohauxiliary.h"
+#include <native_window/external_window.h>
+#include <qopenharmony.h>
+
+#include <QWindow>
+#include <qpa/qplatformbackingstore.h>
+
+QT_BEGIN_NAMESPACE
+
+QOhNativeVSync::QOhNativeVSync(QWindow *window, QPlatformBackingStore *backingStore)
+    : m_window(window)
+    , m_backingStore(backingStore)
+{
+    if (m_window.isNull())
+        return;
+    WId id = window->winId();
+    WindowNode *node = reinterpret_cast<WindowNode *>(id);
+
+    if (node == nullptr) {
+        return;
+    }
+
+    QtOh::runOnJsUIThreadAndWait([this, node]{
+        OHNativeWindow *nativeWindow = reinterpret_cast<OHNativeWindow *>(node->window);
+        if (nativeWindow == nullptr) {
+            return;
+        }
+        uint64_t surfaceId = 0;
+        int32_t error = OH_NativeWindow_GetSurfaceId(nativeWindow, &surfaceId);
+        if (error != 0)
+            return;
+
+    //    OH_NativeVSync_Create_ForAssociatedWindow 系统bug, 参数名称中包含"_WM"时会导致电脑重启进入锁屏状态, Qt规避
+    //    std::string name_ = window->objectName().toStdString();
+        static int index = 0;
+        std::string name_ = QString("qt_ohos_vsync_%1").arg(index++).toStdString();
+        m_vsync.reset(new QOhObjectHolder<OH_NativeVSync>(OH_NativeVSync_Create_ForAssociatedWindow,
+                                                          OH_NativeVSync_Destroy, surfaceId, name_.data(), name_.length()));
+        if (Q_UNLIKELY(m_vsync->object() == nullptr)) {
+            qWarning() << "create vsync failed.";
+            return;
+        }
+        OH_NativeVSync_RequestFrame(m_vsync->object(), nativeVSyncFrameCallback, this);
+    });
+}
+
+void QOhNativeVSync::saveFrame(QWindow *wnd, const QRegion &region, const QPoint &offset)
+{
+    if (m_window.data() == wnd) {
+        m_pendingFlush = true;
+        m_region = m_region.united(region);
+        if (m_offset.has_value()) {
+            const QPoint &old = m_offset.value();
+            m_offset = QPoint(qMin(old.x(), offset.x()), qMin(old.y(), offset.y()));
+        } else {
+            m_offset = offset;
+        }
+    }
+}
+
+bool QOhNativeVSync::isValid() const
+{
+    return m_vsync->object() != nullptr;
+}
+
+bool QOhNativeVSync::isReady() const
+{
+    return m_ready.load();
+}
+
+void QOhNativeVSync::clearFlag()
+{
+    m_ready.store(false);
+}
+
+bool QOhNativeVSync::isPendingFlush() const
+{
+    return m_pendingFlush;
+}
+
+void QOhNativeVSync::setDeleted(bool deleted)
+{
+    m_backingStore = nullptr;
+    m_deleted = deleted;
+}
+
+void QOhNativeVSync::nativeVSyncFrameCallback(long long timestamp, void *data)
+{
+    //    this callback will be invoked in other thread
+    Q_UNUSED(timestamp);
+    QOhNativeVSync *vsync = reinterpret_cast<QOhNativeVSync *>(data);
+    if (vsync->m_deleted) {
+        QtOh::runOnQtMainThread([vsync] {
+            delete vsync;
+        });
+        return;
+    }
+    vsync->m_ready.store(true);
+    if (vsync->m_pendingFlush) {
+        vsync->requestFlush();
+    }
+    OH_NativeVSync_RequestFrame(vsync->m_vsync->object(), &QOhNativeVSync::nativeVSyncFrameCallback, vsync);
+}
+
+void QOhNativeVSync::requestFlush()
+{
+    if (m_window.isNull())
+        return;
+
+    // this should invoked in qt thread, ensure QOhNativeVSync is alived in Qt thread.
+    QMetaObject::invokeMethod(m_window.data(), [this]() {
+        if (m_deleted)
+            return;
+        if (isReady() && isPendingFlush()) {
+            flush();
+        }
+    }, Qt::QueuedConnection);
+}
+
+void QOhNativeVSync::flush()
+{
+    if (m_window.isNull() || m_backingStore == nullptr)
+        return;
+
+    m_pendingFlush = false;
+    auto region = m_region;
+    auto offset = m_offset.value_or(QPoint());
+    m_region = {};
+    m_offset = std::nullopt;
+    m_backingStore->flush(m_window.data(), region, offset);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/openharmony/qohnativevsync.h b/src/plugins/platforms/openharmony/qohnativevsync.h
new file mode 100644
index 00000000000..1e5ed10f93f
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohnativevsync.h
@@ -0,0 +1,44 @@
+#ifndef QOHNATIVEVSYNC_H
+#define QOHNATIVEVSYNC_H
+
+#include "qohobjectholder.h"
+#include <QScopedPointer>
+#include <QRegion>
+#include <QPoint>
+#include <QPointer>
+#include <QWindow>
+
+#include <native_vsync/native_vsync.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPlatformBackingStore;
+
+class QOhNativeVSync
+{
+public:
+    QOhNativeVSync(QWindow *window, QPlatformBackingStore *backingStore);
+    void saveFrame(QWindow *wnd, const QRegion &region, const QPoint &offset);
+    bool isValid() const;
+    bool isReady() const;
+    void clearFlag();
+    bool isPendingFlush() const;
+    void setDeleted(bool deleted);
+    void flush();
+
+private:
+    static void nativeVSyncFrameCallback(long long timestamp, void *data);
+    void requestFlush();
+    QScopedPointer<QOhObjectHolder<OH_NativeVSync>> m_vsync;
+    QPointer<QWindow> m_window;
+    QPlatformBackingStore *m_backingStore;
+    std::atomic_bool m_ready = ATOMIC_VAR_INIT(true);
+    bool m_pendingFlush = false;
+    bool m_deleted = false;
+    QRegion m_region;
+    std::optional<QPoint> m_offset;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHNATIVEVSYNC_H
diff --git a/src/plugins/platforms/openharmony/qohnativewindow.cpp b/src/plugins/platforms/openharmony/qohnativewindow.cpp
new file mode 100644
index 00000000000..7a1db3a3bbd
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohnativewindow.cpp
@@ -0,0 +1,1118 @@
+#include <QDebug>
+#include <QMargins>
+#include <QBitArray>
+#include <QTimer>
+#include <QJsModule>
+#include <QScopeGuard>
+#include <QSharedPointer>
+#include <QLoggingCategory>
+#include <qpa/qplatformscreen.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <private/qguiapplication_p.h>
+#include <private/qwindow_p.h>
+#include <window_manager/oh_window_comm.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
+#include <window_manager/oh_window_event_filter.h>
+#include <ace/xcomponent/native_interface_xcomponent.h>
+
+#include "qohplatforminputcontext.h"
+#include "qohevent.h"
+#include "qoheventdispatcher.h"
+#include "qohmain.h"
+#include "qohutility.h"
+#include "qjsability.h"
+#include "qjscontext.h"
+#include "qohauxiliary.h"
+#include "qopenharmony.h"
+#include "qohnormalwindow.h"
+#include "qjswindowstage.h"
+#include "qopenharmonydefines.h"
+#include "qohnativewindow.h"
+#include "qohnativewindowmanager.h"
+#include "qohjsonlistener.h"
+#include "qohplatformopenglwindow.h"
+#include "qohplatformscreen.h"
+#include "qohwindowcontext.h"
+#include "qjssettings.h"
+#if OHOS_SDK_VERSION > 13
+#include "qohdisplay.h"
+#include "qohdisplaymanager.h"
+#endif
+#include <multimedia/image_framework/image/pixelmap_native.h>
+#include <private/qopenharmony_p.h>
+#include <private/qjspromise_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QOhNativeWindow::AvoidArea QOhNativeWindow::jsAvoidArea2Qt(Napi::Object result)
+{
+    QOhNativeWindow::AvoidArea area;
+    area.visible = result.Get("visible").ToBoolean();
+    Napi::Object jsRect = result.Get("leftRect").As<Napi::Object>();
+    area.leftRect = QtOh::jsRect2QRect(jsRect);
+    jsRect = result.Get("topRect").As<Napi::Object>();
+    area.topRect = QtOh::jsRect2QRect(jsRect);
+    jsRect = result.Get("rightRect").As<Napi::Object>();
+    area.rightRect = QtOh::jsRect2QRect(jsRect);
+    jsRect = result.Get("bottomRect").As<Napi::Object>();
+    area.bottomRect = QtOh::jsRect2QRect(jsRect);
+    return area;
+}
+
+QOhNativeWindow::QOhNativeWindow(QOhNativeWindow *parent)
+    : QJsObject(Napi::Object())
+    , m_ability(nullptr)
+    , m_parentNativeWindow(parent)
+    , m_window(nullptr)
+    , m_touchOutsideListener(nullptr)
+    , m_windowModule(nullptr)
+{
+    m_isWindowDestroyed.storeRelease(false);
+    m_expectedWindowStatus.storeRelease(static_cast<int32_t>(QtOh::WindowStatusType::FLOATING));
+
+    s_allWindows << this;
+}
+
+QOhNativeWindow::~QOhNativeWindow()
+{
+    qDeleteAll(m_listeners);
+    m_listeners.clear();
+    if (m_touchOutsideListener != nullptr) {
+        delete m_touchOutsideListener;
+        m_touchOutsideListener = nullptr;
+    }
+
+    s_allWindows.removeAll(this);
+}
+
+void QOhNativeWindow::attachAbility(QJsAbility *ability)
+{
+    m_ability = ability;
+}
+
+QJsAbility *QOhNativeWindow::ability() const
+{
+    if (m_ability)
+        return m_ability;
+    // 子窗口没有ability,查找父窗口的
+    QOhNativeWindow *p = m_parentNativeWindow;
+    while (p) {
+        if (p->m_ability)
+            return p->m_ability;
+        p = p->m_parentNativeWindow;
+    }
+
+    return nullptr;
+}
+
+QOhNativeWindow *QOhNativeWindow::createSubWindow(QOhPlatformOpenGLWindow *window)
+{
+    QScopedPointer<QOhNativeWindow> nativeWindow(new QOhNormalWindow(this));
+    QOhNativeWindow *resultWindow = nativeWindow.data();
+    auto geo = window->geometry();
+    auto *platformScreen = QOhDisplayManager::instance()->screenAt(geo.center());
+    if (platformScreen) {
+        window->window()->setScreen(platformScreen->screen());
+    }
+    if (!this->ability())
+        return nullptr;
+    auto stage = this->ability()->context()->windowStage();
+    bool result = safeExecWithPromise<bool>([this, window, stage, resultWindow](auto p) {
+        Napi::Object option = Napi::Object::New(env());
+        option.Set("title", window->windowTitle().toStdString());
+        option.Set("isModal", window->isModal());
+        option.Set("decorEnabled", window->hasFrame());
+        if (QtOh::apiVersion() >= 14) {
+            Qt::WindowModality m = window->modality();
+            if (Qt::WindowModal == m) {
+                option.Set("modalityType", Napi::Number::New(env(), WINDOW_MODALITY));
+            } else if (Qt::ApplicationModal == m) {
+                auto type = ((QtOh::isTabletDevice() || QtOh::isPhoneDevice()) && !QtOh::isFreeWindowEnable()) ?
+                        WINDOW_MODALITY : APPLICATION_MODALITY;
+                option.Set("modalityType", Napi::Number::New(env(), type));
+            }
+        }
+
+        Q_UNUSED(stage)
+        Napi::Value result = call("createSubWindowWithOptions",
+                                  { Napi::String::New(env(), window->windowName().toStdString()), option });
+        if (!result.IsPromise()) {
+            p->set_value(false);
+            return;
+        }
+
+        QJsPromise promise(result.As<Napi::Promise>());
+        promise.onThen([this, resultWindow, window, p](const Napi::CallbackInfo& info) {
+            if (info.Length() < 1 || !resultWindow->attachNativeWindow(info[0].As<Napi::Object>())) {
+                p->set_value(false);
+                return ;
+            }
+
+            p->set_value(true);
+        }).onCatch([this, p](const Napi::CallbackInfo& info) {
+            Napi::Object error = info[0].As<Napi::Object>();
+            int code = (int)error.Get("code").ToNumber();
+            if (code != 0) {
+                LOGW("create window failed, code is %{public}d, message is %{public}s",
+                     code, error.Get("message").ToString().Utf8Value().c_str());
+            }
+            p->set_value(false);
+        });
+    });
+    return result ? nativeWindow.take() : nullptr;
+}
+
+QOhNativeWindow *QOhNativeWindow::createFloatSubWindow(QOhPlatformOpenGLWindow *window)
+{
+    QScopedPointer<QOhNativeWindow> nativeWindow(new QOhNormalWindow(this));
+    QOhNativeWindow *resultWindow = nativeWindow.data();
+
+    auto geo = window->geometry();
+    auto *platformScreen = QOhDisplayManager::instance()->screenAt(geo.center());
+    if (platformScreen) {
+        window->window()->setScreen(platformScreen->screen());
+    }
+
+    bool result = safeExecWithPromise<bool>([this, window, resultWindow](auto p) {
+        QJsAbility *ability = this->ability();
+        Q_ASSERT(ability != nullptr);
+        QJsContext *context = ability->context();
+
+        if (m_windowModule.isNull())
+            m_windowModule.reset(new QJsModule("@ohos.window"));
+
+        Napi::Object config = Napi::Object::New(env());
+        config.Set("name", Napi::String::New(env(), window->windowName().toStdString()));
+        config.Set("windowType", 8);
+        config.Set("ctx", context->object());
+
+        Napi::Value result = m_windowModule->call("createWindow",{config});
+        if (!result.IsPromise()) {
+            p->set_value(false);
+            return;
+        }
+
+        QJsPromise promise(result.As<Napi::Promise>());
+        promise.onThen([this, resultWindow, window, p](const Napi::CallbackInfo& info) {
+            if (info.Length() > 0 && resultWindow->attachNativeWindow(info[0].As<Napi::Object>())){
+                resultWindow->setWindowFocusable(!window->showWithoutActive());
+                p->set_value(true);
+            } else {
+                p->set_value(false);
+            }
+        }).onCatch([p](const Napi::CallbackInfo& info){ Q_UNUSED(info); p->set_value(false); });
+    });
+    return result ? nativeWindow.take() : nullptr;
+}
+
+void QOhNativeWindow::setParentNativeWindow(QOhNativeWindow *parent)
+{
+    m_parentNativeWindow = parent;
+}
+
+void QOhNativeWindow::setWindowTitleVisible(bool visible)
+{
+    m_titleVisible = visible;
+
+    if (!QtOh::isSupportFreeWindow()) {
+        LOGW("setWindowDecorVisible can only be used in the free multi window mode of "
+             "2in1 devices or tablet devices");
+        return;
+    }
+
+    safeExec([this, visible] { call("setWindowDecorVisible", visible); });
+}
+
+void QOhNativeWindow::setWindowFocusable(bool focusable)
+{
+    m_focusable = focusable;
+    safeExec([this] { call("setWindowFocusable", m_focusable); });
+}
+
+void QOhNativeWindow::setWindowTitleButtonVisible(bool hasMaxButton, bool hasMinButton, bool hasCloseButton)
+{
+    /* 只有主窗口才能设置 */
+    if (m_parentNativeWindow || m_isSplashWindow)
+        return;
+
+    if (!QtOh::isSupportFreeWindow()) {
+        qCWarning(openharmonyQPA, "setWindowTitleButtonVisible This interface is only "
+                                  "available in Free Multi-Window Mode on 2-in-1 devices or tablet devices.");
+        return;
+    }
+
+    safeExec([&] {
+        if (QtOh::apiVersion() < 14) {
+            call("setWindowTitleButtonVisible", {Napi::Boolean::New(env(), hasMaxButton),
+                                                 Napi::Boolean::New(env(), hasMinButton)});
+        } else {
+            call("setWindowTitleButtonVisible", {Napi::Boolean::New(env(), hasMaxButton),
+                                                 Napi::Boolean::New(env(), hasMinButton),
+                                                 Napi::Boolean::New(env(), hasCloseButton)});
+        }
+    });
+}
+
+/**
+ * @note need permission: ohos.permission.WINDOW_TOPMOST
+ */
+void QOhNativeWindow::setWindowTopmost(bool isWindowTopmost)
+{
+    if (!QtOh::isSupportFreeWindow()) {
+        qCWarning(openharmonyQPA, "setWindowTopmost This interface is only "
+                                  "available in Free Multi-Window Mode on 2-in-1 devices or tablet devices.");
+        return;
+    }
+
+    // 只有主窗口才能设置
+    if (m_parentNativeWindow || m_isSplashWindow)
+        return;
+
+    safeExec([this, isWindowTopmost] { call("setWindowTopmost", {Napi::Boolean::New(env(), isWindowTopmost)}); });
+}
+
+static QString colorToHexRgbaString(const QColor &color) {
+    QString hexRgbString = color.name();
+    int alpha = color.alpha();
+    QString alphaHex = QString("%1").arg(alpha, 2, 16, QLatin1Char('0'));
+    QString hexRgbaString = hexRgbString + alphaHex;
+    return hexRgbaString;
+}
+
+void QOhNativeWindow::setWindowContainterColor(const QColor &activeColor, const QColor &inactiveColor)
+{
+    if (QtOh::Utility::type() != QtOh::Utility::PC) {
+        qCWarning(openharmonyQPA, "setWindowContainterColor This interface is only available in 2-in-1 devices.");
+        return;
+    }
+
+    asynSafeExec([=, this] {
+        call("setWindowContainterColor", colorToHexRgbaString(activeColor),
+                                         colorToHexRgbaString(inactiveColor));
+    });
+}
+
+void QOhNativeWindow::raise()
+{
+    HiTracer tracer("QOhNativeWindow::raise");
+    bool visible = isVisible();
+
+    if (!visible) {
+        return;
+    }
+    raiseNativeWindow();
+}
+
+void QOhNativeWindow::lower()
+{
+
+}
+
+void QOhNativeWindow::setVisible(bool visible)
+{
+    if (visible) {
+        safeExec([this] {
+            if (isVisible())
+                return;
+
+            Napi::Function showCallback = Napi::Function::New(env(), [](const Napi::CallbackInfo& info) {
+                if (info.Length() < 1)
+                    return;
+                Napi::Object error = info[0].As<Napi::Object>();
+                int code = (int)error.Get("code").ToNumber();
+                if (code != 0)
+                    LOGW("showWindow failed, code is %{public}d, message is %{public}s",
+                         code, error.Get("message").ToString().Utf8Value().c_str());
+            });
+            call("showWindow", {showCallback});
+        });
+    } else {
+        showMinimized();
+    }
+}
+
+void QOhNativeWindow::showFullScreen()
+{
+    if (!isTopWindow() || !canShowWindow())
+        return;
+
+    safeExec([this] {
+        auto s = windowStatus();
+        if (s == QtOh::WindowStatusType::FULL_SCREEN)
+            return;
+        if (s == QtOh::WindowStatusType::MINIMIZE) {
+            call("restore");
+        }
+        if (QtOh::apiVersion() < 14) {
+            call("maximize", {Napi::Number::New(env(), ENTER_IMMERSIVE)});
+        } else {
+            if (QtOh::isFreeWindowEnable()) {
+                call("setWindowLayoutFullScreen", {Napi::Value::From(env(), true)} );
+                call("maximize", {Napi::Number::New(env(), FOLLOW_APP_IMMERSIVE_SETTING)});
+                call("setSpecificSystemBarEnabled", {Napi::String::New(env(), "status"),
+                     Napi::Value::From(env(), false)});
+                call("setSpecificSystemBarEnabled", {Napi::String::New(env(), "navigationIndicator"),
+                     Napi::Value::From(env(), false)});
+            } else {
+                call("maximize", {Napi::Number::New(env(), ENTER_IMMERSIVE_DISABLE_TITLE_AND_DOCK_HOVER)});
+                call("setSpecificSystemBarEnabled", {Napi::String::New(env(), "status"),
+                     Napi::Value::From(env(), false)});
+                call("setSpecificSystemBarEnabled", {Napi::String::New(env(), "navigationIndicator"),
+                     Napi::Value::From(env(), false)});
+            }
+        }
+        m_expectedWindowStatus.storeRelease(static_cast<int32_t>(QtOh::WindowStatusType::FULL_SCREEN));
+    });
+}
+
+void QOhNativeWindow::showMaximized()
+{
+    HiTracer tracer("QOhNativeWindow::showMaximized");
+    if (!canShowWindow())
+        return;
+
+    safeExec([this] {
+        auto s = windowStatus();
+        if (s == QtOh::WindowStatusType::MAXIMIZE)
+            return;
+        if (s == QtOh::WindowStatusType::MINIMIZE) {
+            if (isTopWindow()) {
+                call("restore");
+            } else {
+                call("showWindow");
+            }
+        }
+        call("maximize", {Napi::Number::New(env(), EXIT_IMMERSIVE)});
+        m_expectedWindowStatus.storeRelease(static_cast<int32_t>(QtOh::WindowStatusType::MAXIMIZE));
+    });
+}
+
+void QOhNativeWindow::showMinimized()
+{
+    HiTracer tracer("QOhNativeWindow::showMinimized");
+    if (!canShowWindow())
+        return;
+
+    safeExecWithPromise<void>([this](auto p) {
+        /* 子窗口的状态会跟随父窗口的状态,如果父窗口显示,子窗口没有最小化,会跟着一起显示 */
+        Napi::Value result = call("minimize");
+        m_expectedWindowStatus.storeRelease(static_cast<int32_t>(QtOh::WindowStatusType::MINIMIZE));
+        QJsPromise promise(result.As<Napi::Promise>());
+        promise.onThen([&, p](const Napi::CallbackInfo&) {
+            p->set_value();
+        }).onCatch([p](const Napi::CallbackInfo& info) {
+            Q_UNUSED(info)
+            p->set_value();
+        });
+    });
+}
+
+void QOhNativeWindow::requestFocusable()
+{
+
+}
+
+void QOhNativeWindow::setMask(const QRegion &region, const QRect &rect)
+{
+    if (region.isEmpty()) {
+        LOGW("set mask failed: region is empty");
+        return;
+    }
+
+    if (rect.isEmpty()) {
+        LOGW("set mask failed: rect is empty");
+        return;
+    }
+
+    auto func = [this, rect, region = region] {
+        const int width = rect.width();
+        const int height = rect.height();
+        std::vector<uint8_t> maskData(height * width, 0);
+
+        for (const QRect& area : region) {
+            const int yStart = std::clamp(area.top(), 0, height-1);
+            const int yEnd = std::clamp(area.bottom(), 0, height-1);
+            const int xStart = std::clamp(area.left(), 0, width-1);
+            const int xEnd = std::clamp(area.right(), 0, width-1);
+            for (int y = yStart; y <= yEnd; ++y) {
+                auto* rowStart = maskData.data() + y * width + xStart;
+                std::fill_n(rowStart, xEnd - xStart + 1, 1);
+            }
+        }
+
+        napi_value jsArray;
+        napi_create_array_with_length(env(), height, &jsArray);
+        napi_value jsZero = Napi::Number::New(env(), 0);
+        napi_value jsOne = Napi::Number::New(env(), 1);
+
+        for (int y = 0; y < height; ++y) {
+            napi_value rowArray;
+            napi_create_array_with_length(env(), width, &rowArray);
+
+            const int rowOffset = y * width;
+            for (int x = 0; x < width; ++x) {
+                const napi_value value = maskData[rowOffset + x] ? jsOne : jsZero;
+                napi_set_element(env(), rowArray, x, value);
+            }
+            napi_set_element(env(), jsArray, y, rowArray);
+        }
+        call("setWindowMask", {jsArray});
+    };
+
+    asynSafeExec(func);
+}
+
+void QOhNativeWindow::showNormal()
+{
+    HiTracer tracer("QOhNativeWindow::showNormal");
+    if (!canShowWindow())
+        return;
+
+    safeExec([this] {
+        QtOh::WindowStatusType type = windowStatus();
+        if (type == QtOh::WindowStatusType::FULL_SCREEN ||
+            type == QtOh::WindowStatusType::MAXIMIZE ||
+            type == QtOh::WindowStatusType::SPLIT_SCREEN) {
+            call("recover");
+        } else if (type == QtOh::WindowStatusType::MINIMIZE) {
+            if (!m_parentNativeWindow && !m_isSplashWindow) {
+                if (QtOh::apiVersion() < 14) {
+                    qNativeWindowManager->show(this);
+                } else {
+                    call("restore");
+                    call("recover");
+                }
+            } else {
+                setVisible(true);
+            }
+        } else {
+            setVisible(true);
+        }
+        m_expectedWindowStatus.storeRelease(static_cast<int32_t>(QtOh::WindowStatusType::FLOATING));
+    });
+}
+
+void QOhNativeWindow::setWindowModal(bool isModal)
+{
+    if (QtOh::apiVersion() < 14)
+        return;
+
+    if (!QtOh::isSupportFreeWindow()) {
+        qCWarning(openharmonyQPA, "setWindowModal This interface is only"
+                                  " available in Free Multi-Window Mode on 2-in-1 devices or tablet devices.");
+        return;
+    }
+
+    asynSafeExec([=, this] {
+        QJsWindowStage *stage = windowStage();
+        if (stage) {
+            stage->call("setWindowModal", { Napi::Value::From(env(), isModal) });
+        }
+    });
+}
+
+QJsWindowStage *QOhNativeWindow::windowStage()
+{
+    if (m_ability && m_ability->context())
+        return m_ability->context()->windowStage();
+
+    return nullptr;
+}
+
+void QOhNativeWindow::stopListener()
+{
+    for (int i = 0; i < m_listeners.count(); ++i) {
+        if (isDestroyed())
+            return;
+        m_listeners.at(i)->off();
+    }
+}
+
+void QOhNativeWindow::startListener()
+{
+    m_listeners << new QOhJsOnListener(this, "avoidAreaChange", [this](const Napi::CallbackInfo& info) {
+        if (info.Length() < 1)
+            return;
+
+        QRect gtr = geometry();
+        if (gtr.isValid())
+            reportWindowGeometry();
+
+        Napi::Object avoidAreaOptions = info[0].As<Napi::Object>();
+        int t = avoidAreaOptions.Get("type").ToNumber();
+        QOhNativeWindow::AvoidAreaType type = (QOhNativeWindow::AvoidAreaType)t;
+        Napi::Object area = avoidAreaOptions.Get("area").As<Napi::Object>();
+        auto qtAvoidArea = jsAvoidArea2Qt(area);
+        m_avoidAreas.insert(type, qtAvoidArea);
+        if (type == TYPE_KEYBOARD) {
+            QtOh::runOnQtMainThread([this, qtAvoidArea]{
+                if (m_window == nullptr || !QOhNativeWindowManager::instance()->exist(this))
+                    return;
+                auto rect = QHighDpi::fromNativePixels(qtAvoidArea.bottomRect, m_window->window());
+                QOhPlatformInputContext::ohInputContext()->setKeyboardRect(rect);
+            });
+        }
+    });
+
+    for (int i = 0; i < m_listeners.count(); ++i) {
+        m_listeners.at(i)->on();
+    }
+}
+
+void QOhNativeWindow::setWindowConerRadius(qreal radius)
+{
+    if (QtOh::apiVersion() < 17) {
+        return;
+    } else if (QtOh::apiVersion() < 20) {
+        if (!QtOh::isSupportFreeWindow()) {
+            qCWarning(openharmonyQPA,
+                      "setWindowCornerRadius This interface is only available in Free Multi-Window "
+                      "Mode on 2-in-1 devices or tablet devices.");
+            return;
+        }
+    } else {
+        if (!QtOh::checkDeviceType(QtOh::Utility::Phone | QtOh::Utility::PC
+                                   | QtOh::Utility::Tablet)) {
+            qCWarning(openharmonyQPA,
+                      "setWindowCornerRadius This interface is not support on this device");
+            return;
+        }
+    }
+
+    asynSafeExec([this, radius] { call("setWindowCornerRadius", { Napi::Number::New(env(), radius) }); });
+}
+
+void QOhNativeWindow::setWindowShadowRadius(qreal radius)
+{
+    if (!QtOh::checkDeviceType(QtOh::Utility::PC | QtOh::Utility::Tablet)) {
+        qCWarning(openharmonyQPA, "setWindowShadowRadius This interface is not support on this device");
+        return;
+    }
+
+    if (QtOh::apiVersion() >= 17){
+        asynSafeExec([this, radius] { call("setWindowShadowRadius", { Napi::Number::New(env(), radius) }); });
+    }
+}
+
+void QOhNativeWindow::setWindowBackgroundColor(const QColor &color)
+{
+    QString colorStr = color.name(QColor::HexArgb);
+    asynSafeExec([this, colorStr] {
+        call("setWindowBackgroundColor", { Napi::String::New(env(), colorStr.toStdString()) });
+    });
+}
+
+void QOhNativeWindow::setWindowTouchable(bool isTouchable)
+{
+    asynSafeExec([this, isTouchable] { call("setWindowTouchable", { Napi::Boolean::New(env(), isTouchable) }); });
+}
+
+void QOhNativeWindow::destroy()
+{
+    if (isDestroyed())
+        return;
+
+    stopListener();
+    m_window = nullptr;
+    setDestroyed();
+
+    if (m_ability) {
+        m_ability->terminateSelf();
+        delete m_ability;
+        m_ability = nullptr;
+    } else {
+        QtOh::runOnJsUIThreadWithPromise<void>([this](auto p) {
+            Napi::Promise ret = call("destroyWindow").As<Napi::Promise>();
+            QJsPromise promise(ret);
+            promise.onThen([p](const Napi::CallbackInfo &) {
+                LOGI("succeeded in destroying the window.");
+                p->set_value();
+            }).onCatch([p](const Napi::CallbackInfo &info) {
+                Napi::Object error = info[0].As<Napi::Object>();
+                int code = (int)error.Get("code").ToNumber();
+                LOGW("Failed to destroy the window. Cause code: %{public}d, message: %{public}s",
+                     code, error.Get("message").ToString().Utf8Value().c_str());
+                p->set_value();
+            });
+        });
+    }
+}
+
+void QOhNativeWindow::setDestroyed()
+{
+    m_isWindowDestroyed.storeRelease(true);
+}
+
+void QOhNativeWindow::handleFreeWindowEnableChanged(bool isFreeWindowEnable)
+{
+    if (!isTopWindow())
+        return;
+
+    if (isFreeWindowEnable && m_window && m_window->window()) {
+        Qt::WindowFlags flags = m_window->window()->flags();
+        m_window->setWindowFlags(flags);
+    }
+
+    safeExec([this, isFreeWindowEnable] {
+        if (isFreeWindowEnable) {
+            call("setWindowDecorVisible", {Napi::Boolean::New(env(), m_titleVisible)});
+        } else {
+            if (isVisible())
+                showFullScreen();
+        }
+        auto extraHandler = get("pcModeChangedListener");
+        if (extraHandler.IsEmpty() || !extraHandler.IsFunction())
+            return;
+        call("pcModeChangedListener", { Napi::Boolean::New(env(), isFreeWindowEnable) });
+    });
+}
+
+void QOhNativeWindow::checkForScreenChanged(uint32_t displayId)
+{
+#if OHOS_SDK_VERSION > 13
+    if (m_window == nullptr)
+        return;
+    m_displayId = displayId;
+    QPlatformScreen *currentScreen = m_window->screen();
+    QOhDisplayManager *displayManager = QOhDisplayManager::instance();
+    auto *platformScreen = displayManager->platformScreenOrNull((QOhDisplayId)displayId);
+
+    if (platformScreen && currentScreen != platformScreen) {
+        QWindowSystemInterface::handleWindowScreenChanged(m_window->window(), platformScreen->screen());
+    }
+#else
+    // Todo
+#endif
+}
+
+bool QOhNativeWindow::isVisible() const
+{
+    return safeExec([this] { return call<bool>("isWindowShowing"); });
+}
+
+bool QOhNativeWindow::isDestroyed() const
+{
+    return m_isWindowDestroyed.loadAcquire();
+}
+
+void QOhNativeWindow::reportWindowGeometry(const QRect &rectIn)
+{
+    Q_UNUSED(rectIn)
+}
+
+void QOhNativeWindow::raiseNativeWindow()
+{
+    if (isTopWindow()) {
+        //FIXME:分屏状态下调用showWindow会退出分屏
+        QtOh::WindowStatusType type = windowStatus();
+        if (QtOh::WindowStatusType::SPLIT_SCREEN != type) {
+            asynSafeExec([this] { call("showWindow"); });
+        }
+    } else {
+        if (QtOh::apiVersion() >= 14) {
+            asynSafeExec([&]() {
+                Napi::Promise promise = this->call("raiseToAppTop").As<Napi::Promise>();
+                if (!promise.IsNull()) {
+                    QJsPromise p(promise);
+                    p.onThen([&](const Napi::CallbackInfo &info){
+                         Q_UNUSED(info)
+                         LOGW("Succeeded in raising window to app top.");
+                     }).onCatch([&](const Napi::CallbackInfo &info){
+                        Napi::Object error = info[0].As<Napi::Object>();
+                        Napi::Number code = error.Get("code").ToNumber();
+                        Napi::String message = error.Get("message").ToString();
+                        LOGW("raiseToAppTop failed, result code: %{public}d message: %{public}s", code.Int32Value(),
+                             message.Utf8Value().c_str());
+                    });
+                }
+            });
+        } else {
+            asynSafeExec([this] { call("showWindow"); });
+        }
+    }
+}
+
+
+QRect QOhNativeWindow::adjustRect(QWindow *window, const QRect &rectIn, const QMargins &effectiveMargins)
+{
+    QRect rect = rectIn;
+    if (rect.isValid()) {
+        int frameX = rect.x();
+        int frameY = rect.y();
+        int frameWidth = effectiveMargins.left() + rect.width() + effectiveMargins.right();
+        int frameHeight = effectiveMargins.top() + rect.height() + effectiveMargins.bottom();
+        const bool isDefaultPosition = !frameX && !frameY && window->isTopLevel();
+        const bool includeFrame = qt_window_private(const_cast<QWindow *>(window))->positionPolicy
+                == QWindowPrivate::WindowFrameInclusive;
+        if (!includeFrame && !isDefaultPosition) {
+            frameX -= effectiveMargins.left();
+            frameY -= effectiveMargins.top();
+        }
+        rect = QRect(frameX, frameY, frameWidth, frameHeight);
+    }
+    return rect;
+}
+
+uint32_t QOhNativeWindow::displayId() const
+{
+    return m_displayId;
+}
+
+QList<QOhNativeWindow *> QOhNativeWindow::allWindows()
+{
+    return s_allWindows;
+}
+
+QOhNativeWindow::AvoidArea QOhNativeWindow::windowAvoidArea(QOhNativeWindow::AvoidAreaType type) const
+{
+    return safeExec([this, type] {
+        Napi::Object result = call("getWindowAvoidArea", {Napi::Number::New(env(), type) }).As<Napi::Object>();
+        return jsAvoidArea2Qt(result);
+    });
+}
+
+void QOhNativeWindow::attachRootComponent(void *component)
+{
+    m_attachedComponent = component;
+    if (qNativeWindowManager->exist(this) && m_window != nullptr)
+        m_window->attachRootComponent(component);
+}
+
+void QOhNativeWindow::handleWindowEvent(QtOh::WindowState event)
+{
+    HiTracer tracer("QOhNativeWindow::handleWindowEvent");
+    if (!qNativeWindowManager->exist(this) || m_window == nullptr)
+        return;
+    QWindow *window = m_window->window();
+#if OHOS_SDK_VERSION < 18
+    if (event == QtOh::WindowState::WINDOW_DESTROYED) {
+        QOhEventDispatcher::instance()->handleWindowHidden(window);
+        QWindowSystemInterface::handleCloseEvent(window);
+    } else if (event == QtOh::WindowState::WINDOW_HIDDEN) {
+        QOhEventDispatcher::instance()->handleWindowHidden(window);
+#else
+    if (event == QtOh::WindowState::WINDOW_DESTROYED) {
+        QWindowSystemInterface::handleCloseEvent(window);
+        //QWindowSystemInterface::flushWindowSystemEvents();
+    } else if (event == QtOh::WindowState::WINDOW_HIDDEN) {
+        //fireExpose();
+#endif
+    } else if (event == QtOh::WindowState::WINDOW_SHOWN) {
+        auto wp = qt_window_private(m_window->window());
+        /*可能引起widget隐藏导致m_window被析构置null*/
+        if (!m_isShowSys && wp && !m_window->window()->isVisible() && isVisible()) {
+            wp->setVisible(true);
+        }
+        clearShowSysFlag();
+
+        if (m_window)
+            m_window->fireExpose(QRect(QPoint(), m_window->geometry().size()));
+
+    } else if (event == QtOh::WindowState::WINDOW_ACTIVE) {
+        handleFocusEvent(true, m_window);
+    } else if (event == QtOh::WindowState::WINDOW_INACTIVE) {
+        handleFocusEvent(false, m_window);
+    }
+}
+
+void QOhNativeWindow::handleWindowStatusEvent(QtOh::WindowStatusType event)
+{
+    if (qNativeWindowManager->exist(this) && m_window != nullptr) {
+        if (m_lastReportedStatusEvent != event) {
+            m_window->handleWindowStatusEvent(event);
+            m_lastReportedStatusEvent = event;
+        }
+    }
+}
+
+void QOhNativeWindow::updateWindowAvoidArea()
+{
+    asynSafeExec([this] {
+        Napi::Object result = call("getWindowAvoidArea", {Napi::Number::New(env(), TYPE_SYSTEM) }).As<Napi::Object>();
+        if (result.IsEmpty() || result.IsNull())
+            return;
+
+        m_avoidAreas.insert(TYPE_SYSTEM, jsAvoidArea2Qt(result));
+        result = call("getWindowAvoidArea", {Napi::Number::New(env(), TYPE_CUTOUT) }).As<Napi::Object>();
+        m_avoidAreas.insert(TYPE_CUTOUT, jsAvoidArea2Qt(result));
+        result = call("getWindowAvoidArea", {Napi::Number::New(env(), TYPE_SYSTEM_GESTURE) }).As<Napi::Object>();
+        m_avoidAreas.insert(TYPE_SYSTEM_GESTURE, jsAvoidArea2Qt(result));
+        result = call("getWindowAvoidArea", {Napi::Number::New(env(), TYPE_KEYBOARD) }).As<Napi::Object>();
+        m_avoidAreas.insert(TYPE_KEYBOARD, jsAvoidArea2Qt(result));
+        result = call("getWindowAvoidArea", {Napi::Number::New(env(), TYPE_NAVIGATION_INDICATOR) }).As<Napi::Object>();
+        m_avoidAreas.insert(TYPE_NAVIGATION_INDICATOR, jsAvoidArea2Qt(result));
+    });
+}
+
+void QOhNativeWindow::handleFocusEvent(bool focusIn, QOhPlatformWindow *platformWindow)
+{
+    QWindow *nextActiveWindow = nullptr;
+    if (focusIn) {
+        QWindow *topWindow = platformWindow->window();
+        // QFileDialog选择文件和取消之后,主窗口的激活事件会被先发送导致下面的检查isWindowBlocked
+        // 返回true,从而焦点切换失败 modalWindow是QFileDialogClassWindow,系统又没有重新发送激活事件
+//        QWindow *modalWindow = nullptr;
+//        if (QGuiApplicationPrivate::instance()->isWindowBlocked(topWindow, &modalWindow) && topWindow != modalWindow) {
+//            modalWindow->requestActivate();
+//            return;
+//        }
+        nextActiveWindow = topWindow;
+    } else {
+        QOhNativeWindow *focusNativeWindow = qNativeWindowManager->focusWindow();
+        if (focusNativeWindow != nullptr && focusNativeWindow->m_window != nullptr)
+            nextActiveWindow = focusNativeWindow->m_window->window();
+    }
+    QOhWindowContext::setFocusWindow(nextActiveWindow);
+}
+
+OH_PixelmapNative *QOhNativeWindow::grab()
+{
+    return safeExecWithPromise<OH_PixelmapNative *>([this](auto p) {
+        QJsPromise promise(call("snapshot").As<Napi::Promise>());
+        promise.onThen([&, p](const Napi::CallbackInfo& info) {
+            if (info.Length() < 1) {
+                p->set_value(nullptr);
+                return ;
+            }
+            OH_PixelmapNative *result = nullptr;
+            OH_PixelmapNative_ConvertPixelmapNativeFromNapi(env(), info[0], &result);
+            p->set_value(result);
+        }).onCatch([p](const Napi::CallbackInfo& info){
+            Q_UNUSED(info)
+            p->set_value(nullptr);
+        });
+    });
+}
+
+bool QOhNativeWindow::setMouseGrabEnabled(bool grab)
+{
+    // 如果不判断,右键菜单连续点击时,会导致右键菜单显示后又隐藏
+    static QList<QWindow *> s_hasTouchOutsideEvent;
+
+    if (!grab && m_window) {
+        s_hasTouchOutsideEvent.removeOne(m_window->window());
+    }
+    safeExec([this, grab] {
+        if (grab) {
+            if (m_touchOutsideListener == nullptr) {
+                m_touchOutsideListener = new QOhJsOnListener(this, "touchOutside", [this](const Napi::CallbackInfo& info) {
+                    Q_UNUSED(info);
+                    if (m_window == nullptr)
+                        return ;
+                    auto window = QPointer<QWindow>(m_window->window());
+                    s_hasTouchOutsideEvent << window;
+                    QtOh::runOnQtMainThread([window]{
+                        QWindow *findWindow = QGuiApplication::topLevelAt(QCursor::pos());
+                        if (findWindow && findWindow->type() == Qt::Popup)
+                            return;
+                        // 让Qt内部处理pupup窗口的关闭,如果500ms之后还有popup窗口,在发送事件
+                        QTimer::singleShot(500, [window]{
+                            // 暂时只给popup窗口发送
+                            if (window.isNull() || !s_hasTouchOutsideEvent.contains(window) || (window->type() != Qt::Popup)
+                                || !QGuiApplicationPrivate::instance()->popupActive())
+                                return;
+
+                            QSharedPointer<QtOh::MouseEvent> event(new QtOh::MouseEvent());
+                            QPoint screenPoint(0xFFFFFFF, 0xFFFFFFF);
+                            event->scPos = screenPoint;
+                            QPoint localPos = screenPoint;
+                            event->xcPos = localPos;
+                            event->window = window;
+                            event->mouseButton = Qt::RightButton;
+                            event->mouseEventType = QEvent::MouseButtonPress;
+                            QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance();
+                            dispatcher->appendOhEvent(event);
+                        });
+                    });
+                });
+            }
+            m_touchOutsideListener->on();
+        } else {
+            if (m_touchOutsideListener != nullptr) {
+                m_touchOutsideListener->off();
+            }
+        }
+    });
+    return true;
+}
+
+bool QOhNativeWindow::startSystemMove()
+{
+    if (QtOh::apiVersion() < 14) {
+        qCWarning(openharmonyQPA) << "only api great than 13 supported.";
+        return false;
+    }
+
+    if (!QtOh::checkDeviceType(QtOh::Utility::Phone | QtOh::Utility::PC | QtOh::Utility::Tablet)) {
+        qCWarning(openharmonyQPA, "startMoving This interface is not support on this device");
+        return false;
+    }
+
+    asynSafeExec([&] {
+        Napi::Value ret = call("startMoving");
+        if (ret.IsPromise()) {
+            QJsPromise promise(ret.As<Napi::Promise>());
+            promise.onThen([](const Napi::CallbackInfo &){
+                       LOGI("Succeeded in starting moving window.");
+                   }).onCatch([](const Napi::CallbackInfo &info){
+                        Napi::Object error = info[0].As<Napi::Object>();
+                        int code = (int)error.Get("code").ToNumber();
+                        LOGW("Failed to start moving window. Cause code: %{public}d, message: %{public}s",
+                             code, error.Get("message").ToString().Utf8Value().c_str());
+                    });
+        }
+    });
+    return true;
+}
+
+void QOhNativeWindow::setWindowTitleMoveEnabled(bool isEnabled)
+{
+    if (!QtOh::isSupportFreeWindow()) {
+        qCWarning(openharmonyQPA, "setWindowTitleMoveEnabled This interface is only"
+                                  " available in Free Multi-Window Mode on 2-in-1 devices or tablet devices.");
+        return;
+    }
+
+    safeExec([=, this] { call("setWindowTitleMoveEnabled", { Napi::Boolean::New(env(), isEnabled)}); });
+}
+
+void QOhNativeWindow::setWindowTitle(const QString &title)
+{
+    if (!QtOh::isSupportFreeWindow()) {
+        qCWarning(openharmonyQPA, "setWindowTitle This interface is only"
+                                  " available in Free Multi-Window Mode on 2-in-1 devices or tablet devices.");
+        return;
+    }
+
+    safeExec([=, this] {
+        if (QtOh::apiVersion() >= 15) {
+            call("setWindowTitle", { Napi::String::New(env(), title.toStdString())});
+        } else {
+            if (isTopWindow() && m_ability != nullptr && m_ability->context()) {
+                m_ability->context()->call("setMissionLabel", title);
+            }
+        }
+    });
+}
+
+bool QOhNativeWindow::loadContent(const QString &name)
+{
+    m_name = name;
+    return true;
+}
+
+void QOhNativeWindow::attachPlatformWindow(QOhPlatformWindow *window)
+{
+    m_window = window;
+    if (m_window != nullptr) {
+        if (m_attachedComponent != nullptr)
+            m_window->attachRootComponent(m_attachedComponent);
+        qDeleteAll(m_listeners);
+        m_listeners.clear();
+        startListener();
+        updateWindowAvoidArea();
+    }
+}
+
+QString QOhNativeWindow::name() const
+{
+    return m_name;
+}
+
+bool QOhNativeWindow::isTopWindow() const
+{
+    return m_parentNativeWindow == nullptr;
+}
+
+void QOhNativeWindow::setSplashWindow()
+{
+    m_isSplashWindow = true;
+}
+
+bool QOhNativeWindow::attachNativeWindow(Napi::Object window)
+{
+    if (window.IsEmpty())
+        return false;
+    setObject(window);
+    return true;
+}
+
+/**
+ * @brief class QOhNativeWindow::WindowLimits::WindowLimits Start
+ */
+const QStringList windowLimitsKeys = {"minWidth", "minHeight", "maxWidth", "maxHeight"};
+
+QOhNativeWindow::WindowLimits::WindowLimits(QSize minimumSize, QSize maximumSize)
+{
+    qDebug() << "WindowLimits::WindowLimits"<< minimumSize << maximumSize;
+    if (windowLimitsKeys.size() != 4)
+        return;
+    /*
+     * 定义全局最小和最大尺寸
+     */
+    const QSize globalMinSize(1, 1);
+    const QSize globalMaxSize(3600, 3600);
+
+    /*
+     * 约束最小尺寸在全局范围内,约束最大尺寸在全局范围内
+     */
+    minimumSize = minimumSize.expandedTo(globalMinSize).boundedTo(globalMaxSize);
+    maximumSize = maximumSize.expandedTo(minimumSize).boundedTo(globalMaxSize);
+    m_values.clear();
+    m_values.append(minimumSize.width());
+    m_values.append(minimumSize.height());
+    m_values.append(maximumSize.width());
+    m_values.append(maximumSize.height());
+    qDebug() << *this;
+}
+
+QOhNativeWindow::WindowLimits::WindowLimits(Napi::Object value)
+{
+    if (windowLimitsKeys.size() != 4)
+        return;
+    for(int i = 0; i < 4; ++i) {
+        m_values[i] = int(value.Get(windowLimitsKeys[i].toStdString()).ToNumber());
+    }
+}
+
+QOhNativeWindow::WindowLimits &QOhNativeWindow::WindowLimits::intersect(const WindowLimits &other)
+{
+    if (m_values.size() == 4)
+        for (int i = 0; i < 4; ++i) {
+             m_values[i] = (i < 2) ? qMax(m_values[i], other.m_values[i]) : qMin(m_values[i], other.m_values[i]);
+        }
+    return *this;
+}
+
+QOhNativeWindow::WindowLimits &QOhNativeWindow::WindowLimits::operator +=(const QSize &size)
+{
+    if (windowLimitsKeys.size() == 4)
+        for (int i = 0; i < 4; ++i) {
+            m_values[i] += (i % 2 ? size.height() : size.width());
+        }
+    return *this;
+}
+
+Napi::Object QOhNativeWindow::WindowLimits::toObject(napi_env env)
+{
+    Napi::Object result = Napi::Object::New(env);
+    for (int i = 0; i < 4; ++i) {
+        result.Set(windowLimitsKeys[i].toStdString(), Napi::Number::New(env, m_values[i]));
+    }
+    return result;
+}
+
+QDebug operator<<(QDebug debug, const QOhNativeWindow::WindowLimits &limits)
+{
+    debug << "WindowLimits(";
+    for (int i = 0; i < 4; ++i) {
+        debug << windowLimitsKeys[i] << ":" << limits.m_values[i] << ",";
+    }
+    debug << ")";
+    return debug;
+}
+/**
+ * @brief class QOhNativeWindow::WindowLimits::WindowLimits End
+ */
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohnativewindow.h b/src/plugins/platforms/openharmony/qohnativewindow.h
new file mode 100644
index 00000000000..e5945daebc1
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohnativewindow.h
@@ -0,0 +1,265 @@
+#ifndef QOHNATIVEWINDOW_H
+#define QOHNATIVEWINDOW_H
+
+#include "qohplatformwindow.h"
+#include <qjsobject.h>
+#include <QPointer>
+#include <QSet>
+#include "qohauxiliary.h"
+#include <private/qopenharmony_p.h>
+struct OH_PixelmapNative;
+
+#if defined(OHOS_SDK_VERSION) && (OHOS_SDK_VERSION >= 15)
+#include <window_manager/oh_window_event_filter.h>
+#endif
+QT_BEGIN_NAMESPACE
+class QJsAbility;
+class QJsWindowStage;
+class QOhJsOnListener;
+class QOhPlatformOpenGLWindow;
+
+class QOhNativeWindow : public QJsObject
+{
+protected:
+    enum MaximizePresentation{
+        FOLLOW_APP_IMMERSIVE_SETTING,
+        EXIT_IMMERSIVE,
+        ENTER_IMMERSIVE,
+        ENTER_IMMERSIVE_DISABLE_TITLE_AND_DOCK_HOVER    /*api14*/
+    };
+
+    enum WindowModality {
+        WINDOW_MODALITY = 0,
+        APPLICATION_MODALITY
+    };
+
+    enum class WindowChangeReason {
+        UNDEFINED = 0,  /* 默认值 */
+        MAXIMIZE,       /* 窗口最大化 */
+        RECOVER,        /* 窗口恢复到上一次的状态 */
+        MOVE,           /* 窗口拖拽移动 */
+        DRAG,           /* 窗口拖拽缩放 */
+        DRAG_START,     /* 窗口开始拖拽缩放 */
+        DRAG_END        /* 窗口结束拖拽缩放 */
+    };
+
+public:
+    enum AvoidAreaType {
+        TYPE_SYSTEM,
+        TYPE_CUTOUT,
+        TYPE_SYSTEM_GESTURE,
+        TYPE_KEYBOARD,
+        TYPE_NAVIGATION_INDICATOR
+    };
+    struct AvoidArea {
+        bool visible;
+        QRect leftRect;
+        QRect topRect;
+        QRect rightRect;
+        QRect bottomRect;
+    };
+
+    enum WindowType {
+        NORMAL_WINDOW,
+        EXTENSION_WINDOW
+    };
+
+    enum HitTest {
+        Client,
+        SystemButton
+    };
+
+    /**
+     * @brief The WindowLimits class
+     * 窗口尺寸限制
+     */
+    class WindowLimits
+    {
+    public:
+        WindowLimits(QSize minimumSize = QSize(1, 1), QSize maximumSize = QSize(3600, 3600));
+        WindowLimits(Napi::Object value);
+        /**
+         * @brief intersect
+         * 两个窗口限制的交集
+         * @param other
+         * @return 返回交集
+         */
+        WindowLimits &intersect(const WindowLimits &other);
+        /**
+         * @brief operator +=
+         * 窗口限制加上一个尺寸
+         * @param size 尺寸
+         * @return 返回加上尺寸后的窗口限制
+         */
+        WindowLimits& operator += (const QSize &size);
+        Napi::Object toObject(napi_env);
+        friend QDebug operator<<(QDebug, const WindowLimits &);
+    private:
+        QVector<int> m_values = {1, 1, 3600, 3600};
+    };
+
+    explicit QOhNativeWindow(QOhNativeWindow *parent = nullptr);
+    virtual ~QOhNativeWindow();
+
+    virtual WindowType nativeWindowType() const = 0;
+    QString name() const;
+
+    bool isTopWindow() const;
+    void setSplashWindow();
+
+    bool attachNativeWindow(Napi::Object window);
+
+    virtual void attachAbility(QJsAbility *ability);
+
+    virtual QJsAbility *ability() const;
+
+    virtual QOhNativeWindow *createSubWindow(QOhPlatformOpenGLWindow *window);
+
+    virtual QOhNativeWindow *createFloatSubWindow(QOhPlatformOpenGLWindow *window);
+
+    void setParentNativeWindow(QOhNativeWindow *parent);
+
+    virtual int32_t id() const = 0;
+    void attachPlatformWindow(QOhPlatformWindow *window);
+    virtual void stopListener();
+    virtual void startListener();
+
+    void setWindowConerRadius(qreal radius);
+    void setWindowShadowRadius(qreal radius);
+    void setWindowBackgroundColor(const QColor &color);
+    void setWindowTouchable(bool isTouchable);
+    void setWindowTitleVisible(bool visible);
+    void setWindowFocusable(bool focusable);
+    void setWindowTitleButtonVisible(bool hasMaxButton, bool hasMinButton, bool hasCloseButton);
+    void setWindowTopmost(bool isWindowTopmost);
+    void setWindowContainterColor(const QColor &activeColor, const QColor &inactiveColor);
+    virtual void requestFocus() = 0;
+    void raise();
+    void lower();
+    void setVisible(bool visible);
+    void showFullScreen();
+    void showMaximized();
+    void showMinimized();
+    void showNormal();
+    void setWindowModal(bool isModal = true);
+    QJsWindowStage *windowStage();
+    void requestFocusable();
+    virtual bool isFocused() = 0;
+    void setMask(const QRegion &region, const QRect &rect);
+    virtual bool setGeometry(const QRect &rectIn) = 0;
+    bool setMouseGrabEnabled(bool grab);
+    bool startSystemMove();
+    virtual QMargins frameMargins() const = 0;
+
+    OH_PixelmapNative *grab();
+
+    virtual QRect geometry() const = 0;
+    virtual QRect normalGeometry() const { return geometry(); }
+    void setWindowTitleMoveEnabled(bool isEnabled);
+    void setWindowTitle(const QString &title);
+    inline void setShowSysFlag()   { m_isShowSys = true; }
+    inline void clearShowSysFlag() { m_isShowSys = false; }
+
+    virtual void setWindowLimits(WindowLimits &, bool force = true) = 0;
+    virtual WindowLimits getWindowLimits() = 0;
+    virtual bool loadContent(const QString &name);
+    void destroy();
+    void setDestroyed();
+    bool isDestroyed() const;
+    AvoidArea windowAvoidArea(AvoidAreaType type) const;
+    void handleFreeWindowEnableChanged(bool isFreeWindowEnable);
+
+    void attachRootComponent(void *component);
+    virtual QtOh::WindowStatusType windowStatus() const { return QtOh::WindowStatusType::FLOATING; }
+    bool isVisible() const;
+    virtual bool canShowWindow() const { return true; }
+    virtual QRect titleButtonRect() const { return QRect(); }
+    virtual HitTest hitTest(const QPoint &point, qreal scale) const { Q_UNUSED(point) Q_UNUSED(scale) return Client; }
+    virtual void reportWindowGeometry(const QRect &rectIn = QRect());
+    void raiseNativeWindow();
+    static QRect adjustRect(QWindow *window, const QRect &rectIn, const QMargins &effectiveMargins);
+    static QList<QOhNativeWindow *> allWindows();
+    uint32_t displayId() const;
+
+protected:
+    void handleWindowEvent(QtOh::WindowState event);
+    void handleWindowStatusEvent(QtOh::WindowStatusType event);
+    void checkForScreenChanged(uint32_t displayId);
+
+private:
+    void updateWindowAvoidArea();
+    void handleFocusEvent(bool focusIn, QOhPlatformWindow *platformWindow);
+
+protected:
+    static AvoidArea jsAvoidArea2Qt(Napi::Object result);
+    static inline QList<QOhNativeWindow *> s_allWindows = {};
+    QJsAbility *m_ability = nullptr;
+    QOhNativeWindow *m_parentNativeWindow;
+    QOhPlatformWindow *m_window = nullptr;
+    QHash<AvoidAreaType, AvoidArea> m_avoidAreas;
+    QList<QOhJsOnListener *> m_listeners;
+    QOhJsOnListener *m_touchOutsideListener = nullptr;
+    QString m_name;
+    QScopedPointer<QJsModule> m_windowModule;
+    uint32_t m_displayId = 0;
+    QtOh::WindowStatusType m_lastReportedStatusEvent = QtOh::WindowStatusType::UNDEFINED;
+    QAtomicInteger<int32_t> m_expectedWindowStatus;
+    void *m_attachedComponent = nullptr;
+    bool m_isSplashWindow = false;
+    bool m_focusable = false;
+    bool m_titleVisible = true;
+    bool m_isShowSys = false;
+
+private:
+    QAtomicInteger<bool> m_isWindowDestroyed;
+
+protected:
+    template <typename Function, typename... Args>
+    auto safeExec(Function &&func, Args&&... args) const
+            -> decltype(std::invoke(std::forward<Function>(func), std::forward<Args>(args)...)) {
+
+        using ReturnType = decltype(std::invoke(std::forward<Function>(func), std::forward<Args>(args)...));
+        if constexpr (std::is_same_v<ReturnType, void>) {
+            QtOh::runOnJsUIThreadAndWait([this, func = std::forward<Function>(func)] {
+                if (isDestroyed())
+                    return;
+
+                func();
+            });
+        } else {
+            return QtOh::runOnJsUIThreadWithResult(
+                    [this, func = std::forward<Function>(func), ...args = std::forward<Args>(args)]() mutable {
+                        if (isDestroyed())
+                            return ReturnType{};
+
+                        return std::invoke(std::forward<Function>(func), std::forward<Args>(args)...);
+                    });
+        }
+    }
+
+    template <typename ReturnType, typename Function, typename... Args>
+    auto safeExecWithPromise(Function &&func, Args&&... args) const ->ReturnType {
+        return QtOh::runOnJsUIThreadWithPromise<ReturnType>(
+                [this, func = std::forward<Function>(func), ...args = std::forward<Args>(args)](auto&& p) mutable {
+                    if (isDestroyed()) {
+                        if constexpr (std::is_void_v<ReturnType>) {
+                            p->set_value();
+                        } else {
+                            p->set_value(ReturnType{});
+                        }
+                        return;
+                    }
+
+                    std::invoke(std::forward<Function>(func), p, std::forward<Args>(args)...);
+                });
+    }
+
+    void asynSafeExec(const std::function<void()> &func) const {
+        QtOh::runOnJsUIThreadNoWait([=, this]{
+            if (!isDestroyed())
+                func();
+        });
+    }
+};
+QT_END_NAMESPACE
+#endif // QOHNATIVEWINDOW_H
diff --git a/src/plugins/platforms/openharmony/qohnativewindowmanager.cpp b/src/plugins/platforms/openharmony/qohnativewindowmanager.cpp
new file mode 100644
index 00000000000..8b66fb7c6ac
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohnativewindowmanager.cpp
@@ -0,0 +1,411 @@
+#include "qdebug.h"
+#include "qohmain.h"
+#include "qohnativewindow.h"
+#include "qohnormalwindow.h"
+#include "qohnativewindowmanager.h"
+#include "qohextensionwindow.h"
+#include "qohplatformopenglwindow.h"
+#include "qjsaccessmanager.h"
+#include <qpa/qwindowsysteminterface_p.h>
+#include "qohwindownode.h"
+#include "qjsuiability.h"
+#include "qohauxiliary.h"
+#include "qjsuiabilitycontext.h"
+#include "qjswindowstage.h"
+#include "qjswant.h"
+#include "qjsabilityfactory.h"
+#include "qohwindowcontext.h"
+#include "qohplatformscreen.h"
+
+#include <QTimer>
+#include <QWindow>
+#include <QThread>
+#include <QScopeGuard>
+#include <QReadLocker>
+#include <QWriteLocker>
+#include <QElapsedTimer>
+#include <QLoggingCategory>
+#include <QGuiApplication>
+#include <qpa/qplatformnativeinterface.h>
+#include <private/qopenharmony_p.h>
+#include <private/qjspromise_p.h>
+#include <qopenharmonydefines.h>
+#include <ace/xcomponent/native_interface_xcomponent.h>
+#include "qohdisplaymanager.h"
+#include "qjsuiextensionability.h"
+#include "qjsuiextensioncontextsession.h"
+
+Q_GLOBAL_STATIC(QOhNativeWindowManager, manager)
+
+QOhNativeWindowManager::QOhNativeWindowManager()
+    : m_firstTopWindow(nullptr)
+{
+
+}
+
+QOhNativeWindowManager::~QOhNativeWindowManager()
+{
+
+}
+
+QOhNativeWindow *QOhNativeWindowManager::createNativeWindow(QOhPlatformOpenGLWindow *platformWindow, const QRect &rect)
+{
+    QOhPlatformOpenGLWindow::Kind kind = platformWindow->windowKind();
+    qCWarning(openharmonyQPA) << "create js window, kind: " << int(kind);
+    Q_ASSERT(kind != QOhPlatformOpenGLWindow::Kind::NativeNode);
+
+    QOhNativeWindow *window = nullptr;
+    /* FIXME SplashScreen暂时做特殊处理 */
+    if ((kind == QOhPlatformOpenGLWindow::Kind::SubWindow) ||
+        (kind == QOhPlatformOpenGLWindow::Kind::SplashWindow)) {
+        window = createSubWindow(platformWindow);
+    } else if (kind == QOhPlatformOpenGLWindow::Kind::MainWindow) {
+        window = createTopWindow(platformWindow, rect);
+    }
+    if (window != nullptr && (kind == QOhPlatformOpenGLWindow::Kind::SplashWindow)) {
+        window->setSplashWindow();
+    }
+    return window;
+}
+
+QOhNativeWindow *QOhNativeWindowManager::focusWindow()
+{
+    // 是否提供系统接口直接获取?
+    return find([](QOhNativeWindow *w){
+        return w->isFocused();
+    });
+}
+
+bool QOhNativeWindowManager::exist(QOhNativeWindow *window)
+{
+    if (window == nullptr)
+        return false;
+    QReadLocker readLocker(&m_windowsLock);
+    return m_windows.contains(window);
+}
+
+void QOhNativeWindowManager::destroyWindow(QOhNativeWindow *window)
+{
+    if (window == nullptr || !m_windows.contains(window))
+        return;
+    {
+        QWriteLocker writeLocker(&m_windowsLock);
+        m_windows.removeOne(window);
+    }
+    window->destroy();
+    delete window;
+    window = nullptr;
+}
+
+QOhNativeWindowManager *QOhNativeWindowManager::instance()
+{
+    return manager();
+}
+
+QJsAbility *QOhNativeWindowManager::defaultAbility() const
+{
+    if (m_windows.isEmpty())
+        return nullptr;
+    return m_windows.first()->ability();
+}
+
+void QOhNativeWindowManager::destoryAllAbility()
+{
+    for (auto &w : m_windows) {
+        if (w->isTopWindow())
+            w->ability()->terminateSelf();
+    }
+}
+
+NativeResourceManager *QOhNativeWindowManager::resourceManager()
+{
+    if (m_windows.isEmpty())
+        return nullptr;
+    QJsAbility *ability = m_windows.first()->ability();
+    QJsContext *context = ability->context();
+    return context->resourceManager();
+}
+
+Napi::Value QOhNativeWindowManager::jsResourceManager()
+{
+    if (m_windows.isEmpty())
+        return Napi::Value();
+    QJsAbility *ability = m_windows.first()->ability();
+    QJsContext *context = ability->context();
+    return context->get("resourceManager");
+}
+
+QJsContext *QOhNativeWindowManager::context(QWindow *window) const
+{
+    if (m_windows.isEmpty())
+        return nullptr;
+    QJsContext *result = m_windows.last()->ability()->context();
+    if (window == nullptr) {
+        return result;
+    }
+    QOhWindowNode *node = QOhWindowNode::fromId(window->winId());
+    if (node == nullptr)
+        return result;
+    QOhNativeWindow *nativeWindow = node->ownerWindow();
+    if (nativeWindow == nullptr)
+        return result;
+    result =  nativeWindow->ability()->context();
+    return result;
+}
+
+QOhNativeWindow *QOhNativeWindowManager::window(const QString &name) const
+{
+    return find([name](QOhNativeWindow *w){
+        return w->name() == name;
+    });
+}
+
+QOhNativeWindow *QOhNativeWindowManager::find(std::function<bool (QOhNativeWindow *)> function) const
+{
+    QReadLocker readLocker(&m_windowsLock);
+    auto it = std::find_if(m_windows.constBegin(), m_windows.constEnd(), function);
+    return it == m_windows.constEnd() ? nullptr : *it;
+}
+
+QOhNativeWindow *QOhNativeWindowManager::createSubWindow(QOhPlatformOpenGLWindow *platformWindow)
+{
+    auto qWindow = platformWindow->window();
+    auto parent = dynamic_cast<QOhPlatformOpenGLWindow *>(platformWindow->parent());
+    QOhNativeWindow *parentNativeWindow = nullptr;
+    if (parent != nullptr) {
+        parentNativeWindow = parent->nativeWindow();
+    }
+    if (parentNativeWindow == nullptr) {
+        auto transientParent = qWindow->transientParent();
+        if (transientParent != nullptr) {
+            if (QOhPlatformOpenGLWindow *p = dynamic_cast<QOhPlatformOpenGLWindow*>(transientParent->handle())) {
+                parentNativeWindow = p->nativeWindow();
+            }
+        }
+    }
+    if (parentNativeWindow == nullptr && !m_windows.empty()) {
+        parentNativeWindow = m_windows.first();
+    }
+    if (parentNativeWindow == nullptr)
+        return nullptr;
+
+    Qt::WindowFlags flags = qWindow->flags();
+    QOhNativeWindow *nativeWindow = nullptr;
+
+    if (flags.testFlag(Qt::Floating)) {
+        static bool hasPermission = (QJsAccessManager::instance()->checkPermission("ohos.permission.SYSTEM_FLOAT_WINDOW") == 0);
+
+        qCInfo(openharmonyQPA) << "QOhJsWindowManager::createFloatSubWindow"
+                               << "parent:" << qWindow->parent()
+                               << "transientParent:" << qWindow->transientParent();
+        if (!hasPermission) {
+            qCWarning(openharmonyQPA) << "No floating window permission.";
+            return nullptr;
+        }
+        nativeWindow = parentNativeWindow->createFloatSubWindow(platformWindow);
+    } else {
+        qCInfo(openharmonyQPA) << "QOhJsWindowManager::createSubWindow "
+                               << "parent:" << qWindow->parent()
+                               << "transientParent:" << qWindow->transientParent();
+        nativeWindow = parentNativeWindow->createSubWindow(platformWindow);
+    }
+    if (nativeWindow != nullptr) {
+        m_windows << nativeWindow;
+
+        platformWindow->nativeWindowNode()->setOwnerWindow(nativeWindow);
+        nativeWindow->attachPlatformWindow(platformWindow);
+        nativeWindow->loadContent(platformWindow->windowName());
+    }
+    return nativeWindow;
+}
+
+QOhNativeWindow *QOhNativeWindowManager::createTopWindow(QOhPlatformOpenGLWindow *platformWindow, const QRect &rect)
+{
+    QOhNativeWindow *window = nullptr;
+    if (m_firstTopWindow != nullptr) {
+        window = m_firstTopWindow;
+        m_firstTopWindow = nullptr;
+        platformWindow->setWindowName(window->name());
+        // 第一个窗口系统创建,监听不到ACTIVE事件,自动触发
+        QOhWindowContext::setFocusWindow(platformWindow->window());
+    } else {
+        QString name = platformWindow->windowName();
+        m_topWindowPromise = std::make_shared<std::promise<QOhNativeWindow *>>();
+        auto feature = m_topWindowPromise->get_future();
+        if(m_windows.isEmpty()) {
+            return nullptr;
+        }
+        QJsAbility *ability = m_windows.first()->ability();
+        if (ability == nullptr) {
+            qWarning() << "Not find valid ability to create top window";
+            return nullptr;
+        }
+        QtOh::runOnJsUIThreadAndWait([this, ability, platformWindow, rect, name]{
+            QJsContext *context = ability->context();
+            QJsWant *want = ability->launchWant();
+        Want startWant = { want->bundleName(), want->moduleName() ,want->abilityName(), {
+                                                           name,
+                                                           name}
+            };
+            QOhPlatformScreen *platformScreen = static_cast<QOhPlatformScreen*>(platformWindow->screen());
+            StartOptions options = {
+                                     .windowMode = -1,
+                                     .windowLeft = rect.x(),
+                                     .windowTop = rect.y(),
+                                     .windowWidth = rect.width(),
+                                     .windowHeight = rect.height(),
+                                     .displayId = platformScreen->displayId(),
+                                     .withAnimation = false};
+
+            Napi::Function callback = Napi::Function::New(ability->env(), [](const Napi::CallbackInfo& info) {
+                if (info.Length() < 1) {
+                    LOGW("startAbility failed, error unkonwn");
+                    return;
+                }
+                Napi::Object error = QNapi::get<Napi::Object>(info[0]);
+                int code = QNapi::get<int>(error, "code");
+                if (code != 0)
+                    LOGW("startAbility failed, code is %{public}d, message is %{public}s", code, error.Get("message").ToString().Utf8Value().c_str());
+            });
+            context->startAbility(startWant, options, callback);
+        });
+        auto status = feature.wait_for(std::chrono::seconds(3));
+        if (status == std::future_status::timeout) {
+            qCWarning(openharmonyQPA) << "wait for create top window time out";
+            return nullptr;
+        }
+        window = feature.get();
+        m_topWindowPromise.reset();
+    }
+    if (window != nullptr) {
+        platformWindow->nativeWindowNode()->setOwnerWindow(window);
+        window->attachPlatformWindow(platformWindow);
+    }
+    return window;
+}
+
+void QOhNativeWindowManager::handleTopWindowCreated(QJsAbility *ability)
+{
+    QJsWindowProxy *proxy = nullptr;
+    QOhNativeWindow *window = nullptr;
+    switch (ability->abilityType()) {
+    case QJsAbility::UIAbility: {
+        QJsContext *context = ability->context();
+        proxy = context->windowStage();
+        window = new QOhNormalWindow();
+        }
+        break;
+    case QJsAbility::UIExtensionAbility:
+        proxy = dynamic_cast<QJsUIExtensionAbility *>(ability)->session();
+        window = new QOhExtensionWindow();
+        break;
+    default:
+        break;
+    }
+    Q_ASSERT(proxy != nullptr);
+    Q_ASSERT(window != nullptr);
+    bool result = window->attachNativeWindow(proxy->mainwindow());
+    Q_ASSERT(result);
+    window->attachAbility(ability);
+    m_windows << window;
+    window->loadContent(ability->name());
+    if (m_topWindowPromise) {
+        m_topWindowPromise->set_value(window);
+    } else {
+        m_firstTopWindow = window;
+    }
+    if (qApp && (ability->abilityType() == QJsAbility::UIExtensionAbility))
+        Q_EMIT qApp->newNativeWindowCreated(ability->name());
+}
+
+void QOhNativeWindowManager::handleTopWindowDestroyed(const QString &name)
+{
+    QOhNativeWindow *window = qNativeWindowManager->window(name);
+    if (window) {
+        window->setDestroyed();
+    }
+}
+
+void QOhNativeWindowManager::setWindowXComponent(OH_NativeXComponent *component)
+{
+    QOhNativeWindow *w = window(getName(component));
+    if (w != nullptr) {
+        w->attachRootComponent(component);
+    }
+}
+
+QString QOhNativeWindowManager::getName(OH_NativeXComponent *component)
+{
+    char id[OH_XCOMPONENT_ID_LEN_MAX + 1] = { };
+    uint64_t id_length = OH_XCOMPONENT_ID_LEN_MAX + 1;
+    OH_NativeXComponent_GetXComponentId(component, id, &id_length);
+    QString name = QString::fromLatin1(id);
+    return name;
+}
+
+void QOhNativeWindowManager::init(Napi::Env env, Napi::Object exports)
+{
+    Napi::Object exportInstance = exports.Get(OH_NATIVE_XCOMPONENT_OBJ).As<Napi::Object>();
+    if (exportInstance.IsNull() ||
+        exportInstance.IsUndefined()) {
+        return;
+    }
+
+    OH_NativeXComponent *nativeXComponent = Napi::ObjectWrap<OH_NativeXComponent>::Unwrap(exportInstance);
+    if (nullptr == nativeXComponent) {
+        LOGE("unwrap OH_NATIVE_XCOMPONENT_OBJ failed.");
+        return;
+    }
+
+    qNativeWindowManager->setWindowXComponent(nativeXComponent);
+}
+
+QString QOhNativeWindowManager::getAbilityName()
+{
+    if (m_windows.isEmpty())
+        return QString("");
+
+    QJsAbility *ability = m_windows.first()->ability();
+    QJsWant *want = ability->launchWant();
+    return want->abilityName();
+}
+
+QString QOhNativeWindowManager::getModuleName()
+{
+    if (m_windows.isEmpty())
+        return QString("");
+
+    QJsAbility *ability = m_windows.first()->ability();
+    QJsWant *want = ability->launchWant();
+    return want->moduleName();
+}
+
+void QOhNativeWindowManager::show(QOhNativeWindow *window)
+{
+    if (window == nullptr) {
+        return;
+    }
+    QtOh::runOnJsUIThreadAndWait([window]{
+        QJsAbility *ability = window->ability();
+        if (!ability)
+            return;
+
+        QJsContext *context = ability->context();
+        QJsWant *want = ability->launchWant();
+        Want startWant = { want->bundleName(), want->moduleName(), want->abilityName(), {
+                               "",
+                               window->name()}
+                           };
+        Napi::Function callback = Napi::Function::New(ability->env(), [](const Napi::CallbackInfo& info) {
+            if (info.Length() < 1) {
+                LOGW("startAbility failed, error unkonwn");
+                return;
+            }
+            Napi::Object error = info[0].As<Napi::Object>();
+            int code = (int)error.Get("code").ToNumber();
+            if (code != 0)
+                LOGW("startAbility failed, code is %{public}d, message is %{public}s", code, error.Get("message").ToString().Utf8Value().c_str());
+        });
+        dynamic_cast<QJsUIAbilityContext *>(context)->startAbility(startWant, callback);
+    });
+}
diff --git a/src/plugins/platforms/openharmony/qohnativewindowmanager.h b/src/plugins/platforms/openharmony/qohnativewindowmanager.h
new file mode 100644
index 00000000000..30a041bc363
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohnativewindowmanager.h
@@ -0,0 +1,70 @@
+#ifndef QOHNATIVEWINDOWMANAGER_H
+#define QOHNATIVEWINDOWMANAGER_H
+
+#include <QList>
+#include <QReadWriteLock>
+#include <future>
+#include <QWaitCondition>
+#include <QtCore/QJsObject>
+#include <napi/native_api.h>
+
+class QWindow;
+class QOhNativeWindow;
+struct OH_NativeXComponent;
+class QOhPlatformOpenGLWindow;
+class QJsAbility;
+class QJsContext;
+
+#define qNativeWindowManager QOhNativeWindowManager::instance()
+struct NativeResourceManager;
+
+class QOhNativeWindowManager
+{
+public:
+    QOhNativeWindowManager();
+    virtual ~QOhNativeWindowManager();
+
+    static QOhNativeWindowManager *instance();
+
+    QJsAbility *defaultAbility() const;
+    void destoryAllAbility();
+
+    NativeResourceManager *resourceManager();
+    Napi::Value jsResourceManager();
+
+    QJsContext *context(QWindow *window = nullptr) const;
+
+    QOhNativeWindow *createNativeWindow(QOhPlatformOpenGLWindow *platformWindow, const QRect &rect);
+
+    QOhNativeWindow *focusWindow();
+
+    bool exist(QOhNativeWindow *window);
+
+    void destroyWindow(QOhNativeWindow *window);
+
+    static void init(Napi::Env env, Napi::Object exports);
+
+    QString getAbilityName();
+    QString getModuleName();
+
+    void show(QOhNativeWindow *window);
+
+    QOhNativeWindow *window(const QString &name) const;
+    void handleTopWindowCreated(QJsAbility *ability);
+    void handleTopWindowDestroyed(const QString &name);
+    const QList<QJsAbility *> &allAbilities() const;
+private:
+    void setWindowXComponent(OH_NativeXComponent *component);
+private:
+    static QString getName(OH_NativeXComponent *component);
+    QOhNativeWindow *find(std::function<bool (QOhNativeWindow *)> function) const;
+    QOhNativeWindow *createSubWindow(QOhPlatformOpenGLWindow *platformWindow);
+    QOhNativeWindow *createTopWindow(QOhPlatformOpenGLWindow *platformWindow, const QRect &rect);
+private:
+    QList<QOhNativeWindow *> m_windows;
+    QOhNativeWindow *m_firstTopWindow;
+    std::shared_ptr<std::promise<QOhNativeWindow *>> m_topWindowPromise;
+    mutable QReadWriteLock m_windowsLock;
+};
+
+#endif // QOHNATIVEWINDOWMANAGER_H
diff --git a/src/plugins/platforms/openharmony/qohnormalwindow.cpp b/src/plugins/platforms/openharmony/qohnormalwindow.cpp
new file mode 100644
index 00000000000..977f65de13b
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohnormalwindow.cpp
@@ -0,0 +1,863 @@
+#include <QTimer>
+#include <QCloseEvent>
+#include <QGuiApplication>
+#include <qpa/qplatformscreen.h>
+#include <private/qohhiappevent_p.h>
+
+#include <qnapi.h>
+#include "qohkeys.h"
+#include "qohmain.h"
+#include "qjscontext.h"
+#include "qjswindowstage.h"
+#include "qloggingcategory.h"
+#include "qohevent.h"
+#include "qjsability.h"
+#include "qjsmodule.h"
+#include "qohwindowcontext.h"
+#include "qohnormalwindow.h"
+#include "qoheventdispatcher.h"
+#include "qohdisplay.h"
+#include "qohplatformscreen.h"
+#include "qohplatformopenglwindow.h"
+#include "qjsability.h"
+#include "qopenharmonydefines.h"
+#include "qohdisplaymanager.h"
+#include "qohnativewindowmanager.h"
+#include "qohjsonlistener.h"
+#include "qjsabilityinfo.h"
+#include "qjsuiabilitycontext.h"
+#include "qohplatforminputcontext.h"
+#include "qohplatformcursor.h"
+#include <private/qopenharmony_p.h>
+#include <private/qjspromise_p.h>
+#include <QtGui/private/qwindow_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformcursor.h>
+
+QOhNormalWindow::QOhNormalWindow(QOhNativeWindow *parent)
+    : QOhNativeWindow(parent)
+{
+
+}
+
+QOhNormalWindow::~QOhNormalWindow()
+{
+
+}
+
+QOhNormalWindow::WindowProperties QOhNormalWindow::getWindowProperties(const Napi::Object &window)
+{
+    static const QStringList windowPropertiesKeys = { "id", "windowRect", "drawableRect", "isFullScreen","focusable", "displayId"
+                                                      /* 未使用的属性 */
+                                                  #if 0
+                                                      , "type", "isLayoutFullScreen",
+                                                      "touchable", "brightness", "isKeepScreenOn",
+                                                      "isPrivacyMode", "isTransparent"
+                                                  #endif
+                                                    };
+    return QtOh::runOnJsUIThreadWithResult([window] {
+        QJsObject obj(window);
+        Napi::Object ret = obj.call("getWindowProperties").As<Napi::Object>();
+        if (ret.IsEmpty() || ret.IsNull())
+            return WindowProperties{};
+
+        QVariantList values;
+        values.append(QNapi::get<int>(ret, windowPropertiesKeys[0]));
+        values.append(QtOh::jsRect2QRect(QNapi::get<Napi::Object>(ret, windowPropertiesKeys[1])));
+        values.append(QtOh::jsRect2QRect(QNapi::get<Napi::Object>(ret, windowPropertiesKeys[2])));
+        values.append(QNapi::get<bool>(ret, windowPropertiesKeys[3]));
+        values.append(QNapi::get<bool>(ret, windowPropertiesKeys[4]));
+        values.append(QNapi::get<int>(ret, windowPropertiesKeys[5]));
+        /* 未使用的属性 */
+#if 0
+        values.append(QNapi::get<int>(ret, windowPropertiesKeys[6]));
+        values.append(QNapi::get<bool>(ret, windowPropertiesKeys[7]));
+        values.append(QNapi::get<bool>(ret, windowPropertiesKeys[8]));
+        values.append(QNapi::get<bool>(ret, windowPropertiesKeys[9]));
+        values.append(QNapi::get<bool>(ret, windowPropertiesKeys[10]));
+        values.append(QNapi::get<bool>(ret, windowPropertiesKeys[11]));
+        values.append(QNapi::get<bool>(ret, windowPropertiesKeys[12]));
+#endif
+        WindowProperties windowProperties;
+        windowProperties.update(values);
+        return windowProperties;
+    });
+}
+
+QOhNativeWindow::WindowType QOhNormalWindow::nativeWindowType() const
+{
+    return QOhNativeWindow::NORMAL_WINDOW;
+}
+
+void QOhNormalWindow::attachAbility(QJsAbility *ability)
+{
+    QOhNativeWindow::attachAbility(ability);
+    safeExec([this, ability] {
+        if (m_ability != nullptr) {
+            if (15 <= QtOh::apiVersion() && !QtOh::isTabletDevice() && !QtOh::isPhoneDevice()) {
+                /* NOTE 该接口需要配置PREPARE_APP_TERMINATE权限(module.json5) */
+                Napi::Function prepareToTerminateAsync = Napi::Function::New(env(), [this, ability](const Napi::CallbackInfo& info){
+                    Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(info.Env());
+                    if (!m_window || QGuiApplicationPrivate::instance()->isWindowBlocked(m_window->window())) {
+                        if (m_window)
+                            qCWarning(openharmonyQPA) << m_window->window() << "is blocked";
+                        deferred.Resolve(Napi::Boolean::New(deferred.Env(), true));
+                        return deferred.Promise();
+                    }
+                    QString name = ability->name();
+                    const QString &tag = QString("pt_begin_%1").arg(name);
+                    QtOhosWatchdog::QOhHiAppEvent::instance()->writeDataTag(tag.toStdString());
+                    qCWarning(openharmonyQPA) << "arkui ability prepareToTerminateAsync: " << m_window->window();
+#if 1
+                    QWindowSystemInterface::handleCloseEvent(m_window->window(), QCloseEvent::AbilityClose, [name, deferred](bool accept){
+                        QtOh::runOnJsUIThreadNoWait([name, deferred, accept] {
+                            const QString &tag = QString("pt_end_%1").arg(name);
+                            QtOhosWatchdog::QOhHiAppEvent::instance()->writeDataTag(tag.toStdString());
+
+                            /* NOTE 鸿蒙窗口关闭和Qt-Accept相反 */
+                            deferred.Resolve(Napi::Boolean::New(deferred.Env(), !accept));
+                        });
+                    });
+#else
+                    QWindowSystemInterface::handleApplicationTermination([name, deferred](bool accept){
+                        QtOh::runOnJsUIThreadNoWait([name, deferred, accept]{
+                            const QString &tag = QString("pt_end_%1").arg(name);
+                            QtOhosWatchdog::QOhHiAppEvent::instance()->writeDataTag(tag.toStdString());
+                            deferred.Resolve(Napi::Boolean::New(deferred.Env(), !accept));
+                        });
+                    });
+#endif
+                    return deferred.Promise();
+                });
+                m_ability->set("onPrepareToTerminateAsync", prepareToTerminateAsync);
+            }
+            /* NOTE 该接口需要配置PREPARE_APP_TERMINATE权限(module.json5) */
+            /* NOTE PAD设备需要使用同步接口 */
+            Napi::Function closeAbilityListener = Napi::Function::New(env(), [this](const Napi::CallbackInfo& info) {
+                Q_UNUSED(info);
+                //m_isWindowDestroyed.storeRelease(true);
+                QtOh::runOnQtMainThread(&QOhNormalWindow::handleWindowEvent, this, QtOh::WindowState::WINDOW_DESTROYED);
+                return Napi::Boolean::New(env(), true);
+            });
+
+            m_ability->set("onPrepareToTerminate", closeAbilityListener);
+        }
+    });
+}
+
+int32_t QOhNormalWindow::id() const
+{
+    if (m_windowId != -1)
+        return m_windowId;
+
+    m_windowId = properties().id();
+    return m_windowId;
+}
+
+void QOhNormalWindow::setWindowLimits(WindowLimits &limits, bool force)
+{
+    qCInfo(openharmonyQPA) << "setWindowLimits" << force;
+
+    if (m_window != nullptr && m_window->hasFrame()) {
+        QMargins m = frameMargins();
+        QSize off(m.left() + m.right(), m.top() + m.bottom());
+        limits += off;
+    }
+    // limits.intersect(getWindowLimits());
+
+    safeExec([this, &limits, force] {
+#if OHOS_SDK_VERSION >= 15
+        Napi::HandleScope scope(env());
+        Napi::Value retValue = force
+                                ? call("setWindowLimits", {limits.toObject(env()), Napi::Boolean::New(env(),force)})
+                                : call("setWindowLimits", {limits.toObject(env())});
+        if (retValue.IsEmpty() || retValue.IsNull())
+            return;
+
+        Napi::Promise ret = retValue.As<Napi::Promise>();
+#else
+        Q_UNUSED(force);
+        Napi::Promise ret = call("setWindowLimits", {limits.toObject(env())}).As<Napi::Promise>();
+#endif
+        QJsPromise promise(ret);
+        promise.onThen([](const Napi::CallbackInfo &info) {
+            qCInfo(openharmonyQPA) << "Actual window limit:" << WindowLimits(info[0].ToObject());
+        });
+    });
+}
+
+QOhNativeWindow::WindowLimits QOhNormalWindow::getWindowLimits()
+{
+    return safeExec([this] {
+        return WindowLimits(Napi::Object(env(), call("getWindowLimits").As<Napi::Object>()));
+    });
+}
+
+bool QOhNormalWindow::isFocused()
+{
+    return safeExec([this] { return call<bool>("isFocused"); });
+}
+
+bool QOhNormalWindow::setGeometry(const QRect &rectIn)
+{
+    QRect actualRect(rectIn);
+    if (m_isSplashWindow && m_parentNativeWindow) {
+        /* 限制启动窗口大小 */
+        QSize miniSize = m_parentNativeWindow->geometry().size();
+        QSize maxSize = QSize(0xFFF, 0xFFF);
+        auto displayId = m_parentNativeWindow->displayId();
+        auto platformScreen = QOhDisplayManager::instance()->platformScreenOrNull(displayId);
+        if (platformScreen) {
+            actualRect.translate(platformScreen->geometry().topLeft());
+            maxSize = platformScreen->availableGeometry().size();
+        }
+        actualRect.setSize(QSize(qBound(miniSize.width(), rectIn.width(), maxSize.width()), \
+                                 qBound(miniSize.height(), rectIn.height(), maxSize.height())));
+        actualRect.moveCenter(m_parentNativeWindow->geometry().center());
+        if (actualRect != rectIn) {
+            /* 实际窗口大小与上层不同,在此处更新 */
+            QOhPlatformOpenGLWindow *platformWindow = dynamic_cast<QOhPlatformOpenGLWindow *>(m_window);
+            if (platformWindow)
+                platformWindow->setNativeGeometry(actualRect);
+            QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(m_window->window(), actualRect);
+        }
+    }
+
+    /* 如果是第一次设置,查询窗口是否保存了坐标尺寸 */
+    if (m_firstSetGeometry) {
+        m_firstSetGeometry = false;
+        if (handleFirstSetGeometry())
+            return true;
+    }
+
+    return safeExecWithPromise<bool>([this, actualRect](auto p) {
+        QRect jsRect = adjustRect(m_window->window(), actualRect, frameMargins());
+        qCInfo(openharmonyQPA) << "QOhNormalWindow::setGeometry set window geometry: " << m_name << jsRect;
+        QtOh::WindowStatusType status = windowStatus();
+        if ( QtOh::WindowStatusType::FULL_SCREEN == status ||
+            QtOh::WindowStatusType::MAXIMIZE == status ||
+            QtOh::WindowStatusType::SPLIT_SCREEN == status) {
+            call("recover");
+        }
+        Napi::Promise result = call("resize", { Napi::Number::New(env(), MAX(1, jsRect.width())), Napi::Number::New(env(), MAX(1, jsRect.height())) }).As<Napi::Promise>();
+        QJsPromise promise(result);
+        promise.onThen([this, jsRect, p](const Napi::CallbackInfo &info) {
+            Q_UNUSED(info)
+            if (QtOh::apiVersion() > 13) {
+                QOhPlatformScreen *current = dynamic_cast<QOhPlatformScreen*>(m_window->screen());
+                Q_ASSERT(current != nullptr);
+                QOhPlatformScreen *ps = current;
+                auto *targetPlatformScreen = QOhDisplayManager::instance()->screenAt(jsRect.topLeft());
+                if (!targetPlatformScreen) {
+                    targetPlatformScreen = QOhDisplayManager::instance()->screenAt(jsRect.topLeft());
+                }
+                if (targetPlatformScreen) {
+                    ps = targetPlatformScreen;
+                }
+                auto x = jsRect.x() - ps->geometry().x();
+                auto y = jsRect.y() - ps->geometry().y();
+                auto displayId = ps->displayId();
+                if (ps != current) {
+                    //change displayId will lead to displayIdChange
+                    QWindowSystemInterface::handleWindowScreenChanged(m_window->window(), ps->screen());
+                    qCInfo(openharmonyQPA) << "switch window display: " << ps;
+                }
+                auto optional = Napi::Object::New(env());
+                optional.Set("displayId", Napi::Number::New(env(), displayId));
+                call("moveWindowToGlobal", { Napi::Number::New(env(), x), Napi::Number::New(env(), y), optional });
+                p->set_value(true);
+            } else {
+                call("moveWindowTo", { Napi::Number::New(env(), jsRect.x()), Napi::Number::New(env(), jsRect.y()) });
+                p->set_value(true);
+            }
+        }).onCatch([p](const Napi::CallbackInfo &info) {
+            Q_UNUSED(info);
+            Napi::Object error = info[0].As<Napi::Object>();
+            if (!error.IsNull()) {
+                Napi::Number code = error.Get("code").ToNumber();
+                Napi::String message = error.Get("message").ToString();
+                LOGW("set window geometry failed code: %{public}d message: %{public}s",
+                     code.Int32Value(),
+                     message.Utf8Value().c_str());
+            }
+            p->set_value(false);
+        });
+    });
+}
+
+QRect QOhNormalWindow::geometry() const
+{
+    return properties().windowRect();
+}
+
+QRect QOhNormalWindow::normalGeometry() const
+{
+    return m_normalGeometry;
+}
+
+QMargins QOhNormalWindow::frameMargins() const
+{
+    QMargins m;
+    QtOh::WindowStatusType winStatus = windowStatus();
+    if ((QtOh::isTabletDevice() || QtOh::isPhoneDevice()) && !QtOh::isFreeWindowEnable()) {
+        if (QtOh::WindowStatusType::FLOATING == winStatus) {
+            m = QMargins(0, titleHeight(), 0, 0);
+        } else if (QtOh::WindowStatusType::MAXIMIZE == winStatus) {
+            QOhNativeWindow::AvoidArea area = windowAvoidArea(AvoidAreaType::TYPE_SYSTEM);
+            if (area.visible)
+                m.setTop(qMax(m.top(), area.topRect.height()));
+
+            area = windowAvoidArea(AvoidAreaType::TYPE_NAVIGATION_INDICATOR);
+            if (area.visible)
+                m.setBottom(qMax(m.bottom(), area.bottomRect.height()));
+        }
+    } else if ((QtOh::isTabletDevice() || QtOh::isPhoneDevice()) && QtOh::isFreeWindowEnable()) {
+        if (QtOh::WindowStatusType::FULL_SCREEN == winStatus) {
+            return m;
+        }
+        m = QMargins(0, titleHeight(), 0, 0);
+        if (QtOh::WindowStatusType::MAXIMIZE == winStatus) {
+            /* pad 自由多窗模式,最大化时 显示区域要减去导航栏高度的规避区域 */
+            QOhNativeWindow::AvoidArea area = windowAvoidArea(AvoidAreaType::TYPE_NAVIGATION_INDICATOR);
+            if (area.visible)
+                m.setBottom(m.bottom() + area.bottomRect.height());
+        }
+    } else {
+        if ((QtOh::WindowStatusType::FULL_SCREEN == winStatus)) {
+            m = QMargins();
+        } else {
+            m = QMargins(0, titleHeight(), 0, 0);
+        }
+    }
+    return m;
+}
+
+void QOhNormalWindow::requestFocus()
+{
+    safeExec([this] {
+        if (this->isFocused())
+            return;
+        bool focusable = properties().focusable();
+
+        if (!focusable) {
+            m_focusable = true;
+            call("setWindowFocusable", {Napi::Boolean::New(env(), true)});
+        }
+
+        int preActiveId = 0;
+        if (QWindow *w = qApp->focusWindow()) {
+            if (QOhPlatformOpenGLWindow *pw = dynamic_cast<QOhPlatformOpenGLWindow*>(w->handle()))
+                preActiveId = pw->nativeWindowId();
+        }
+        if (m_windowModule.isNull())
+            m_windowModule.reset(new QJsModule("@ohos.window"));
+
+        m_windowModule->call("shiftAppWindowFocus", preActiveId, this->id());
+    });
+}
+
+QtOh::WindowStatusType QOhNormalWindow::windowStatus() const
+{
+    return safeExec([this] {
+        //NOTE:可能还有状态更新操作未完成(如连续showMinimized,showNormal),手机设备不支持getWindowStatus接口
+        // int32_t status = call("getWindowStatus").ToNumber();
+        int32_t status = m_expectedWindowStatus.loadAcquire();
+        QtOh::WindowStatusType result = static_cast<QtOh::WindowStatusType>(status);
+
+        if (!QtOh::isSupportFreeWindow() && isTopWindow() && QtOh::WindowStatusType::FLOATING == result) {
+            result = QtOh::WindowStatusType::FULL_SCREEN;
+        }
+
+        if (result == QtOh::WindowStatusType::FULL_SCREEN) {
+            bool immersiveModeEnabledState = call<bool>("getImmersiveModeEnabledState", {});
+            if (!immersiveModeEnabledState)
+                result = QtOh::WindowStatusType::MAXIMIZE;
+        }
+        return result;
+    });
+}
+
+QtOh::WindowStatusType QOhNormalWindow::windowStatusFromSystem() const
+{
+    return safeExec([this] {
+        int32_t status = call("getWindowStatus").ToNumber();
+        QtOh::WindowStatusType result = QtOh::WindowStatusType(status);
+        if (result == QtOh::WindowStatusType::FULL_SCREEN) {
+            bool immersiveModeEnabledState = call<bool>("getImmersiveModeEnabledState", {});
+            if (!immersiveModeEnabledState)
+                result = QtOh::WindowStatusType::MAXIMIZE;
+        }
+        return result;
+    });
+}
+
+void QOhNormalWindow::stopListener()
+{
+    QOhNativeWindow::stopListener();
+#if OHOS_SDK_VERSION >= 15
+    auto winId = id();
+//    OH_NativeWindowManager_UnregisterTouchEventFilter(winId);
+    OH_NativeWindowManager_UnregisterMouseEventFilter(winId);
+#endif
+}
+
+void QOhNormalWindow::startListener()
+{
+    m_displayId = properties().displayId();
+    asynSafeExec([&] {
+        m_listeners << new QOhJsOnListener(this, "windowRectChange", [this](const Napi::CallbackInfo& info) {
+            if (isDestroyed())
+                return;
+            Napi::Object opt = QNapi::getFirst<Napi::Object>(info);
+            QRect qtRect(QtOh::jsRect2QRect(QNapi::get<Napi::Object>(opt, "rect")));
+            auto changeReason = QNapi::get<WindowChangeReason>(opt, "reason");
+            QMargins m = frameMargins();
+            if (changeReason != WindowChangeReason::MAXIMIZE)
+                m_normalGeometry = qtRect - m;
+            bool sizeChanged = qtRect.size() != m_lastReportedGeometry.size();
+            bool positionChanged = qtRect.topLeft() != m_lastReportedGeometry.topLeft();
+            // 如果只是坐标变化,发送geometryChanged event,如果尺寸也变化,xcompoent的尺寸也会发生
+            // 变化,在xcompoent的surfaceChanged中处理geometryChanged
+            bool send = (positionChanged && !sizeChanged) || m_lastReportedGeometry.isEmpty();
+            m_lastReportedGeometry = qtRect;
+            LOGI("window rect changed windowRectChange-(%{public}p): Rect(%{public}d, %{public}d %{public}dX%{public}d)",
+                 m_window ? m_window->window() : nullptr, qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height());
+            if (m_window && send) {
+                handleGeometryChanged(qtRect, m);
+            }
+        });
+
+        m_listeners << new QOhJsOnListener(this, "windowStatusChange", [this](const Napi::CallbackInfo& info) {
+            if (isDestroyed() || m_isSplashWindow)
+                return ;
+            auto event = QNapi::getFirst<QtOh::WindowStatusType>(info);
+            if (event == QtOh::WindowStatusType::MAXIMIZE || event == QtOh::WindowStatusType::FULL_SCREEN) {
+                bool immersiveModeEnabledState = QNapi::get<bool>(call("getImmersiveModeEnabledState"));
+                if (immersiveModeEnabledState)
+                    event = QtOh::WindowStatusType::FULL_SCREEN;
+                else
+                    event = QtOh::WindowStatusType::MAXIMIZE;
+            }
+            m_expectedWindowStatus.storeRelease(static_cast<int32_t>(event));
+            QtOh::runOnQtMainThread(&QOhNormalWindow::handleWindowStatusEvent, this, event);
+        });
+
+        if (QtOh::apiVersion() > 13) {
+            m_listeners << new QOhJsOnListener(this, "displayIdChange", [this](const Napi::CallbackInfo& info) {
+                if (isDestroyed())
+                    return;
+
+                // 8指键盘弹出关闭会时触发的窗口位置变换在坐标一样的时候不会发windowrectchange,
+                // 只会发一个displayidchange, 在此更新窗口尺寸
+                handleGeometryChanged();
+
+                uint32_t displayId = QNapi::getFirst<uint32_t>(info);
+                QtOh::runOnQtMainThread(&QOhNormalWindow::checkForScreenChanged, this, displayId);
+            });
+        }
+#if OHOS_SDK_VERSION >= 15
+        m_listeners << new QOhJsOnListener(this, "windowWillClose", [this](const Napi::CallbackInfo &info) {
+            QString name = this->name();
+            const QString &tag = QString("wc_begin_%1").arg(name);
+            QtOhosWatchdog::QOhHiAppEvent::instance()->writeDataTag(tag.toStdString());
+
+            Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(info.Env());
+            QWindowSystemInterface::handleCloseEvent(m_window->window(), QCloseEvent::WindowClose, [name, deferred](bool accept){
+                QtOh::runOnJsUIThreadNoWait([name, deferred, accept]{
+                    const QString &tag = QString("wc_end_%1").arg(name);
+                    QtOhosWatchdog::QOhHiAppEvent::instance()->writeDataTag(tag.toStdString());
+
+                    /* NOTE 鸿蒙窗口关闭和Qt-Accept相反 */
+                    deferred.Resolve(Napi::Boolean::New(deferred.Env(), !accept));
+                });
+            });
+            return deferred.Promise();
+        });
+
+        m_listeners << new QOhJsOnListener(this, "windowTitleButtonRectChange", [this](const Napi::CallbackInfo& info){
+            m_titleButtonRect = QtOh::jsRect2QRect(info[0].As<Napi::Object>());
+        });
+#endif
+
+        m_listeners << new QOhJsOnListener(this, "windowEvent", [this](const Napi::CallbackInfo& info) {
+            if (isDestroyed())
+                return;
+
+            QtOh::WindowState type = QNapi::getFirst<QtOh::WindowState>(info);
+            if (type == QtOh::WindowState::WINDOW_DESTROYED)
+                setDestroyed();
+
+            if (type == QtOh::WindowState::WINDOW_SHOWN && m_handleGeometryChangedPending) {
+                handleGeometryChanged();
+            }
+            QtOh::runOnQtMainThread(&QOhNormalWindow::handleWindowEvent, this, type);
+        });
+
+        if (!isTopWindow()) {
+            m_listeners << new QOhJsOnListener(this, "subWindowClose", [this](const Napi::CallbackInfo& info) {
+                Q_UNUSED(info)
+                QtOh::runOnQtMainThread(&QOhNormalWindow::handleWindowEvent, this, QtOh::WindowState::WINDOW_DESTROYED);
+                return QNapi::create(true);
+            });
+        }
+
+        QOhNativeWindow::startListener();
+    });
+
+#if OHOS_SDK_VERSION >= 15
+    // NOTE:openharmony5.0.3报错2000
+    if (!QtOh::isOpenHarmonyDevice()) {
+        registerMouseAndTouchEventFilter();
+    }
+#endif
+}
+
+bool QOhNormalWindow::canShowWindow() const
+{
+    if (m_firstShowWindow) {
+        m_firstShowWindow = false;
+        if (isWindowRectAutoSave())
+            return false;
+    }
+    return true;
+}
+
+void QOhNormalWindow::reportWindowGeometry(const QRect &rectIn)
+{
+    /* 获取windowRect传给Qt */
+    safeExec([this, rectIn] { handleGeometryChanged(rectIn); });
+}
+
+bool QOhNormalWindow::loadContent(const QString &name)
+{
+    QOhNativeWindow::loadContent(name);
+    return safeExec([this](const QString &name) {
+        QJsAbility *ability = this->ability();
+        Q_ASSERT(ability != nullptr);
+        QJsObject store(ability->newLocalStorage().As<Napi::Object>());
+        store.call("setOrCreate", "idName", name);
+        call("loadContent", { Napi::String::New(env(), "pages/Index"), store.object()});
+        return true;
+    }, name);
+}
+
+QOhNormalWindow::WindowProperties QOhNormalWindow::properties() const
+{
+    return safeExec([this] { return getWindowProperties(object()); });
+}
+
+int QOhNormalWindow::titleHeight() const
+{
+    if (m_window == nullptr || !m_window->hasFrame() || (!QtOh::isSupportFreeWindow() && isTopWindow()))
+        return 0;
+    return safeExec([this] {
+        Napi::Value value = call("getWindowDecorHeight");
+        int height = value.IsEmpty() ? 0 : value.ToNumber();
+        if(!m_window)
+            return qreal(0.0);
+        return QtOh::densityPixels(m_window->screen()) * height;
+    });
+}
+
+QRect QOhNormalWindow::titleButtonRect() const
+{
+    return safeExec([this] {
+        Napi::Object result = call("getTitleButtonRect").As<Napi::Object>();
+        return QtOh::jsRect2QRect(result);
+    });
+}
+
+QOhNativeWindow::HitTest QOhNormalWindow::hitTest(const QPoint &point, qreal scale) const
+{
+    QRect tbr = m_titleButtonRect;
+    // titleButtonRect相对于窗口的右上角坐标,转换成全局坐标
+    QRect geo = m_lastReportedGeometry;
+    int tbrWidth = tbr.width() * scale;
+    int tbrHeight = tbr.height() * scale;
+    int x = geo.x() + geo.width() - tbrWidth;
+    int y = geo.y();
+    static const int marginvp = 18;
+    qreal marginpx = marginvp * scale;
+    QRect systemButtonRect = QRect(x + marginpx, y, qMax(0, static_cast<int>(tbrWidth - marginpx * 2)), tbrHeight);
+    auto platformScreen = QOhDisplayManager::instance()->platformScreenOrNull(m_displayId);
+    if (platformScreen) {
+        systemButtonRect.translate(platformScreen->geometry().topLeft());
+    }
+    if (systemButtonRect.contains(point))
+        return SystemButton;
+    return Client;
+}
+
+bool QOhNormalWindow::isWindowRectAutoSave() const
+{
+    if (!isDestroyed() && m_ability) {
+        if (QJsContext *context = m_ability->context()) {
+            if (QJsWindowStage *ws = context->windowStage()) {
+                return ws->isWindowRectAutoSave();
+            }
+        }
+    }
+    return false;
+}
+
+bool QOhNormalWindow::handleFirstSetGeometry()
+{
+    if (!isTopWindow())
+        return false;
+    if (!isDestroyed() && !isWindowRectAutoSave()) {
+        if (m_ability != nullptr) {
+            if (QJsUIAbilityContext *context = dynamic_cast<QJsUIAbilityContext *>(m_ability->context())) {
+                QJsAbilityInfo *info = context->abilityInfo();
+                if (!info->isInitGeometrySetted())
+                    return false;
+            }
+        }
+        return false;
+    }
+    reportWindowGeometry();
+    QtOh::WindowStatusType type = windowStatusFromSystem();
+    m_expectedWindowStatus.storeRelease(static_cast<int32_t>(type));
+    handleWindowStatusEvent(type);
+    return true;
+}
+
+void QOhNormalWindow::handleGeometryChanged(const QRect &rectIn, const QMargins &margins)
+{
+    QMargins m = margins;
+    if (m.isNull())
+        m = frameMargins();
+    QRect rect = rectIn;
+    if (!rect.isValid()) {
+        if (isVisible()) {
+            rect = geometry();
+        } else {
+            // 窗口在隐藏时获取不到窗口大小
+            m_handleGeometryChangedPending = true;
+            return;
+        }
+    }
+    if (m_handleGeometryChangedPending) {
+        m_handleGeometryChangedPending = false;
+        m_lastReportedGeometry = rect;
+    }
+    if (!rect.isValid())
+        return;
+
+    auto displayId = properties().displayId();
+    rect = rect - m;
+
+    /* 由屏幕局部坐标系,换算成虚拟屏幕坐标系 */
+    auto platformScreen = QOhDisplayManager::instance()->platformScreenOrNull(displayId);
+    if (platformScreen) {
+        rect.translate(platformScreen->geometry().topLeft());
+    }
+
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+        QSharedPointer<QtOh::GeometryChangeEvent> e(new QtOh::GeometryChangeEvent());
+        e->rect = rect;
+//        e->reason = (int)reason;
+        e->window = m_window->window();
+        dispatcher->appendOhEvent(e);
+    }
+}
+
+#if OHOS_SDK_VERSION >= 15
+void QOhNormalWindow::registerMouseAndTouchEventFilter()
+{
+    auto winId = id();
+    if (winId == 0)
+        return;
+    auto errCode = OH_NativeWindowManager_RegisterMouseEventFilter(winId, &QOhNormalWindow::windowMouseEventFilter);
+    if (errCode != WindowManager_ErrorCode::OK) {
+        LOGW("%s registerMouseEventFilter failed: %{public}d", Q_FUNC_INFO, errCode);
+    }
+    errCode = OH_NativeWindowManager_RegisterTouchEventFilter(winId,
+                                                              &QOhNormalWindow::windowTouchEventFilter);
+    if (errCode != WindowManager_ErrorCode::OK) {
+        LOGW("%s registerTouchEventFilter failed: %{public}d", Q_FUNC_INFO, errCode);
+    }
+}
+
+bool QOhNormalWindow::windowMouseEventFilter(Input_MouseEvent *mouseEvent)
+{
+    auto winId = OH_Input_GetMouseEventWindowId(mouseEvent);
+    auto action = (Input_MouseEventAction)OH_Input_GetMouseEventAction(mouseEvent);
+    auto btn = (Input_MouseEventButton)OH_Input_GetMouseEventButton(mouseEvent);
+    auto displayX = OH_Input_GetMouseEventDisplayX(mouseEvent);
+    auto displayY = OH_Input_GetMouseEventDisplayY(mouseEvent);
+    auto displayId = OH_Input_GetMouseEventDisplayId(mouseEvent);
+
+    QtOh::runOnQtMainThread([displayId, winId, action, btn, displayX, displayY]{
+        auto platformScreen = QOhDisplayManager::instance()->platformScreenOrNull(displayId);
+        auto screenTopLeft = QPoint();
+        if (platformScreen) {
+            screenTopLeft = platformScreen->geometry().topLeft();
+        }
+
+        QOhPlatformWindow *pw = QOhWindowContext::getByWindowId(winId);
+        if (!pw) {
+            return;
+        }
+
+        auto globalPos = QPoint { displayX, displayY };
+        globalPos += screenTopLeft;
+        bool isClientArea = pw->geometry().contains(globalPos);
+
+        static bool isClientAreaPressed = false;
+        /* 客户区域内点击后鼠标移动期间,鼠标移动到非客户区内node也会触发鼠标移动事件 */
+        if (MOUSE_ACTION_BUTTON_DOWN == action && isClientArea)
+            isClientAreaPressed = true;
+
+        if (isClientAreaPressed) {
+            if (MOUSE_ACTION_BUTTON_UP == action)
+                isClientAreaPressed = false;
+            return;
+        }
+
+        static bool enterClient = false;
+        if (isClientArea) {
+            // 客户区点击使用node事件处理,在此处只处理非客户区的鼠标事件
+            enterClient = true;
+            return;
+        }
+
+        if (enterClient && !QOhWindowContext::underMouseWindow()) {
+            QOhPlatformCursor::setDefaultCursor(pw->nativeWindowId());
+            enterClient = false;
+        }
+
+        QSharedPointer<QtOh::MouseEvent> event(new QtOh::MouseEvent());
+        switch (action) {
+        //QDocWidge拖入hover效果需要MouseMove事件
+        case MOUSE_ACTION_MOVE:
+            event->mouseEventType = QEvent::NonClientAreaMouseMove;
+            break;
+        case MOUSE_ACTION_BUTTON_DOWN:
+            event->mouseEventType = QEvent::NonClientAreaMouseButtonPress;
+            break;
+        case MOUSE_ACTION_BUTTON_UP:
+            event->mouseEventType = QEvent::NonClientAreaMouseButtonRelease;
+            break;
+        default:
+            return;
+        }
+
+        switch (btn) {
+        case MOUSE_BUTTON_NONE:
+            event->mouseButton = Qt::NoButton;
+            break;
+        case MOUSE_BUTTON_LEFT:
+            event->mouseButton = Qt::LeftButton;
+            break;
+        case MOUSE_BUTTON_MIDDLE:
+            event->mouseButton = Qt::MiddleButton;
+            break;
+        case MOUSE_BUTTON_RIGHT:
+            event->mouseButton = Qt::RightButton;
+            break;
+        case MOUSE_BUTTON_FORWARD:
+            event->mouseButton = Qt::ForwardButton;
+            break;
+        case MOUSE_BUTTON_BACK:
+            event->mouseButton = Qt::BackButton;
+            break;
+        }
+        QWindow *window = pw->window();
+        while (window && (window->flags() & Qt::WindowTransparentForInput))
+            window = window->parent();
+        if (!window)
+            return;
+        auto localPos = window->handle()->mapFromGlobal(globalPos);
+        event->window = pw->window();
+        event->xcPos = QPointF(localPos);
+        event->scPos = QPointF(globalPos);
+        event->keyboardModifiers = QOhKeys::keyboardModifiers();
+
+        QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance();
+        dispatcher->appendOhEvent(event);
+    });
+    return false;
+}
+
+bool QOhNormalWindow::windowTouchEventFilter(Input_TouchEvent *touchEvent)
+{
+    auto winId = OH_Input_GetTouchEventWindowId(touchEvent);
+    auto displayId = OH_Input_GetTouchEventDisplayId(touchEvent);
+    auto displayX= OH_Input_GetTouchEventDisplayX(touchEvent);
+    auto displayY = OH_Input_GetTouchEventDisplayY(touchEvent);
+    QtOh::runOnQtMainThread([displayId, winId, displayX, displayY]{
+        auto platformScreen = QOhDisplayManager::instance()->platformScreenOrNull(displayId);
+        auto screenTopLeft = QPoint();
+        if (platformScreen) {
+            screenTopLeft = platformScreen->geometry().topLeft();
+        }
+
+        bool isNonClientArea = false;
+        QOhPlatformWindow *pw = QOhWindowContext::getByWindowId(winId);
+        if (!pw) {
+            return;
+        }
+        auto globalPos = QPoint { displayX, displayY };
+        globalPos += screenTopLeft;
+        isNonClientArea = !pw->geometry().contains(globalPos);
+        if (isNonClientArea) {
+            auto screens = QGuiApplication::screens();
+            for (int i = 0; i < screens.count(); ++i) {
+                if (QPlatformCursor *cursor = screens.at(i)->handle()->cursor())
+                    cursor->setPos(QPoint(displayX, displayY));
+            }
+        }
+    });
+    return false;
+}
+
+#endif
+
+/**
+ * @brief class QOhNormalWindow::WindowProperties::WindowProperties Start
+ */
+#define safeGetValue(values, index) ((values).size() > (index) ? (values).at(index) : QVariant())
+QOhNormalWindow::WindowProperties::WindowProperties()
+{
+    // for (int i = 0; i < windowPropertiesKeys.size(); i++) {
+    //     m_values.append(QVariant());
+    // }
+}
+
+void QOhNormalWindow::WindowProperties::update(const QVariantList &value)
+{
+    m_values = value;
+}
+
+int32_t QOhNormalWindow::WindowProperties::id()
+{
+    return safeGetValue(m_values, 0).toInt();
+}
+
+uint32_t QOhNormalWindow::WindowProperties::displayId()
+{
+    return safeGetValue(m_values, 5).toInt();
+}
+
+QRect QOhNormalWindow::WindowProperties::windowRect()
+{
+    return safeGetValue(m_values, 1).value<QRect>();
+}
+
+QRect QOhNormalWindow::WindowProperties::drawableRect()
+{
+    return safeGetValue(m_values, 2).value<QRect>();
+}
+
+bool QOhNormalWindow::WindowProperties::isFullScreen()
+{
+    return safeGetValue(m_values, 3).toBool();
+}
+
+bool QOhNormalWindow::WindowProperties::focusable()
+{
+    return safeGetValue(m_values, 4).toBool();
+}
+/**
+ * @brief class QOhNormalWindow::WindowProperties::WindowProperties End
+ */
diff --git a/src/plugins/platforms/openharmony/qohnormalwindow.h b/src/plugins/platforms/openharmony/qohnormalwindow.h
new file mode 100644
index 00000000000..6f73a141d6a
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohnormalwindow.h
@@ -0,0 +1,81 @@
+#ifndef QOHNORMALWINDOW_H
+#define QOHNORMALWINDOW_H
+
+#include "qohnativewindow.h"
+
+class QOhNormalWindow : public QOhNativeWindow
+{
+public:
+    class WindowProperties
+    {        
+    public:
+        WindowProperties();
+        void update(const QVariantList &);
+        int32_t id();
+        uint32_t displayId();
+        QRect windowRect();
+        QRect drawableRect();
+        bool isFullScreen();
+        bool focusable();
+
+    private:
+        QVariantList m_values;
+    };
+    explicit QOhNormalWindow(QOhNativeWindow *parent = nullptr);
+    ~QOhNormalWindow();
+
+    static WindowProperties getWindowProperties(const Napi::Object &window);
+
+    WindowType nativeWindowType() const override;
+
+    void attachAbility(QJsAbility *ability) override;
+
+    int32_t id() const override;
+
+    void setWindowLimits(WindowLimits &, bool force = true) override;
+
+    WindowLimits getWindowLimits() override;
+
+    bool isFocused() override;
+
+    bool setGeometry(const QRect &rectIn) override;
+
+    QRect geometry() const override;
+
+    virtual QRect normalGeometry() const override;
+
+    QMargins frameMargins() const override;
+
+    void requestFocus() override;
+
+    QtOh::WindowStatusType windowStatus() const override;
+    QtOh::WindowStatusType windowStatusFromSystem() const;
+
+    void stopListener() override;
+    void startListener() override;
+    bool canShowWindow() const override;
+    QRect titleButtonRect() const override;
+    HitTest hitTest(const QPoint &point, qreal scale) const override;
+    void reportWindowGeometry(const QRect &rectIn = QRect()) override;
+    virtual bool loadContent(const QString &name) override;
+    WindowProperties properties() const;
+private:
+    int titleHeight() const;
+    bool isWindowRectAutoSave() const;
+    bool handleFirstSetGeometry();
+    void handleGeometryChanged(const QRect &rectIn = QRect(), const QMargins &margins = QMargins());
+#if OHOS_SDK_VERSION >= 15
+    void registerMouseAndTouchEventFilter();
+    static bool windowMouseEventFilter(Input_MouseEvent *mouseEvent);
+    static bool windowTouchEventFilter(Input_TouchEvent *touchEvent);
+#endif
+    QRect m_lastReportedGeometry;
+    QRect m_titleButtonRect;
+    QRect m_normalGeometry;
+    mutable int32_t m_windowId = -1;
+    mutable bool m_firstShowWindow = true;
+    bool m_firstSetGeometry = true;
+    bool m_handleGeometryChangedPending = false;
+};
+
+#endif // QOHNORMALWINDOW_H
diff --git a/src/plugins/platforms/openharmony/qohobjectholder.h b/src/plugins/platforms/openharmony/qohobjectholder.h
new file mode 100644
index 00000000000..dc348487114
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohobjectholder.h
@@ -0,0 +1,57 @@
+#ifndef QOHOBJECTHOLDER_H
+#define QOHOBJECTHOLDER_H
+
+#include <QtCore/qglobal.h>
+#include <functional>
+#include <utility>
+QT_BEGIN_NAMESPACE
+
+template<typename Type>
+class QOhObjectHolder
+{
+    using Deleter = std::function<void(Type**)>;
+public:
+    template<typename RetType, typename Creator, typename... Args,
+             typename = std::enable_if_t<!std::is_same_v<std::decay_t<Creator>, Type*>>>
+    QOhObjectHolder(Creator &&creator, RetType(*deleter)(Type*), Args&&... args)
+        : m_object(creator(std::forward<Args>(args)...))
+        , m_deleter(deleter ? [deleter](Type** obj) { deleter(*obj); *obj = nullptr; } : Deleter{})
+    {}
+
+    template<typename RetType, typename Creator, typename... Args,
+            typename = std::enable_if_t<!std::is_same_v<std::decay_t<Creator>, Type*>>>
+    QOhObjectHolder(Creator &&creator, RetType(*deleter)(Type**), Args&&... args)
+        : m_object(creator(std::forward<Args>(args)...))
+        , m_deleter(deleter ? std::function<void(Type**)>(deleter) : Deleter{})
+    {}
+
+    template<typename RetType = void>
+    QOhObjectHolder(Type *type, RetType(*deleter)(Type*) = nullptr)
+        : m_object(type)
+        , m_deleter(deleter ? [deleter](Type** obj) { deleter(*obj); *obj = nullptr; } : Deleter{})
+    {}
+
+    template<typename RetType = void,
+             typename = std::enable_if_t<!std::is_same_v<RetType(*)(Type**), nullptr_t>>>
+    QOhObjectHolder(Type *type, RetType(*deleter)(Type**))
+        : m_object(type)
+        , m_deleter(std::function<void(Type**)>(deleter))
+    {}
+
+    ~QOhObjectHolder() {
+        if (m_object && m_deleter) {
+            m_deleter(&m_object);
+        }
+    }
+
+    Type* object() const { return m_object; }
+    Type *take() { Type *ret = m_object; m_object = nullptr; return ret; }
+
+private:
+    Type* m_object = nullptr;
+    Deleter m_deleter;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHOBJECTHOLDER_H
diff --git a/src/plugins/platforms/openharmony/qohplatformabilityctrl.cpp b/src/plugins/platforms/openharmony/qohplatformabilityctrl.cpp
new file mode 100644
index 00000000000..64be3c6abfa
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformabilityctrl.cpp
@@ -0,0 +1,155 @@
+#include "qohplatformabilityctrl.h"
+#include "qohnativewindowmanager.h"
+#include "qjsuiabilitycontext.h"
+#include <qopenharmonydefines.h>
+#include "qohauxiliary.h"
+#include <multimedia/image_framework/image/pixelmap_native.h>
+
+Q_GLOBAL_STATIC(QOhPlatformAbilityCtrl, ctrl)
+
+QT_BEGIN_NAMESPACE
+
+static Napi::Value createWant(const QVariantMap &want)
+{
+    return QNapi::create(want);
+}
+
+static Napi::Object createAbilityResult(const QVariantMap &abilityResult)
+{
+    Napi::Object jsAbilityResult = Napi::Object::New(QtOh::uiEnv());
+    if (abilityResult.contains("resultCode"))
+        jsAbilityResult.Set("resultCode", abilityResult["resultCode"].toInt());
+
+    Napi::Object jswant = QNapi::create(abilityResult).ToObject();
+    if (jswant.Has("resultCode"))
+        jswant.Delete("resultCode");
+    jsAbilityResult.Set("want", jswant);
+    return jsAbilityResult;
+}
+
+static Napi::Value createStartOptions(const QVariantMap &startOptions)
+{
+    Napi::Object jsStartOptions = Napi::Object::New(QtOh::uiEnv());
+    if (startOptions.contains("windowMode"))
+        jsStartOptions.Set("windowMode", startOptions["windowMode"].toInt());
+
+    if (startOptions.contains("displayId"))
+        jsStartOptions.Set("displayId", startOptions["displayId"].toInt());
+
+    if (startOptions.contains("withAnimation"))
+        jsStartOptions.Set("withAnimation", startOptions["withAnimation"].toBool());
+
+    if (startOptions.contains("windowLeft"))
+        jsStartOptions.Set("windowLeft", startOptions["windowLeft"].toInt());
+
+    if (startOptions.contains("windowTop"))
+        jsStartOptions.Set("windowTop", startOptions["windowTop"].toInt());
+
+    if (startOptions.contains("windowWidth"))
+        jsStartOptions.Set("windowWidth", startOptions["windowWidth"].toInt());
+
+    if (startOptions.contains("windowHeight"))
+        jsStartOptions.Set("windowHeight", startOptions["windowHeight"].toInt());
+
+    if (startOptions.contains("processMode"))
+        jsStartOptions.Set("processMode", startOptions["processMode"].toInt());
+
+    if (startOptions.contains("startupVisibility"))
+        jsStartOptions.Set("startupVisibility", startOptions["startupVisibility"].toInt());
+
+    if (QtOh::apiVersion() >= 14) {
+        if (startOptions.contains("startWindowIcon")){
+            std::unique_ptr<OH_PixelmapNative, decltype(&::OH_PixelmapNative_Release)> nativePixel(QtOh::UdmfHelper::createNativePixelMapFromQImage(startOptions["startWindowIcon"].value<QPixmap>().toImage()),
+                                                                                                   ::OH_PixelmapNative_Release);
+            napi_value pixelMap { nullptr };
+            int result = ::OH_PixelmapNative_ConvertPixelmapNativeToNapi(QtOh::uiEnv(), nativePixel.get(), &pixelMap);
+            if (Image_ErrorCode::IMAGE_SUCCESS != result) {
+                qWarning("%s convert cursor pixmap failed. code: %d", Q_FUNC_INFO, result);
+            }else{
+                jsStartOptions.Set("startWindowIcon", Napi::Value::From(QtOh::uiEnv(), pixelMap));
+            }
+        }
+
+        if (startOptions.contains("startWindowBackgroundColor"))
+            jsStartOptions.Set("startWindowBackgroundColor", startOptions["startWindowBackgroundColor"].toString().toStdString());
+
+        if (startOptions.contains("supportWindowModes")){
+            QVariant storedList = startOptions["supportWindowModes"];
+            if (storedList.canConvert<QVariantList>()) {
+                QVariantList retrievedList = storedList.toList();
+                if(!retrievedList.isEmpty()){
+                    Napi::Array ps = Napi::Array::New(QtOh::uiEnv(), retrievedList.size());
+                    uint32_t index = 0;
+                    for (auto &v : retrievedList) {
+                        ps[index++] = v.toInt();
+                    }
+                    jsStartOptions.Set("supportWindowModes", ps);
+                }
+            }
+        }
+    }
+    return jsStartOptions;
+}
+
+void QOhPlatformAbilityCtrl::startAbility(const QVariantMap &want, const QVariantMap &startOptions,
+                                                   const std::function<void (Napi::Value)> &resultHandler)
+{
+    QJsContext *context = qNativeWindowManager->context();
+    if (context == nullptr)
+        return;
+    QtOh::runOnJsUIThreadNoWait([=]{
+        Napi::Function callback = Napi::Function::New(QtOh::uiEnv(), [=](const Napi::CallbackInfo& info) {
+            if (info.Length() < 1) {
+                LOGW("startAbility failed, error unkonwn");
+                return;
+            }
+            Napi::Object error = info[0].As<Napi::Object>();
+            int code = (int)error.Get("code").ToNumber();
+            if (code != 0)
+                LOGW("startAbility failed, code is %{public}d, message is %{public}s", code, error.Get("message").ToString().Utf8Value().c_str());
+            resultHandler(info[0]);
+        });
+        context->startAbility(createWant(want), createStartOptions(startOptions), callback);
+    });
+
+}
+
+void QOhPlatformAbilityCtrl::startAbilityForResult(const QVariantMap &want, const QVariantMap &startOptions,
+                                                            const std::function<void (Napi::Value, Napi::Value)> &resultHandler)
+{
+    QJsContext *context = qNativeWindowManager->context();
+    if (context == nullptr)
+        return;
+    QtOh::runOnJsUIThreadNoWait([=]{
+        Napi::Function callback = Napi::Function::New(QtOh::uiEnv(), [=](const Napi::CallbackInfo& info) {
+            if (info.Length() < 2) {
+                LOGW("startAbility failed, error unkonwn");
+                return;
+            }
+            Napi::Object error = info[0].As<Napi::Object>();
+            int code = (int)error.Get("code").ToNumber();
+            if (code != 0)
+                LOGW("startAbility failed, code is %{public}d, message is %{public}s", code, error.Get("message").ToString().Utf8Value().c_str());
+            
+            resultHandler(info[0], info[1]);
+        });
+        context->startAbilityForResult(createWant(want), createStartOptions(startOptions), callback);
+    });
+}
+
+void QOhPlatformAbilityCtrl::terminateSelfWithResult(const QVariantMap &abilityResult)
+{
+    QJsContext *context = qNativeWindowManager->context();
+    if (context == nullptr)
+        return;
+    QtOh::runOnJsUIThreadNoWait([=]{
+        context->terminateSelfWithResult(createAbilityResult(abilityResult));
+    });
+}
+
+QOhPlatformAbilityCtrl *QOhPlatformAbilityCtrl::instance()
+{
+    return ctrl();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohplatformabilityctrl.h b/src/plugins/platforms/openharmony/qohplatformabilityctrl.h
new file mode 100644
index 00000000000..12ce11242a7
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformabilityctrl.h
@@ -0,0 +1,22 @@
+#ifndef QOHPLATFORMABILITYCTRL_H
+#define QOHPLATFORMABILITYCTRL_H
+
+#include <qpa/qplatformabilityctrl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOhPlatformAbilityCtrl : public QPlatformAbilityCtrl
+{
+public:
+    static QOhPlatformAbilityCtrl *instance();
+
+    virtual void startAbility(const QVariantMap &want, const QVariantMap &startOptions,
+                              const std::function<void (Napi::Value)> &resultHandler);
+    virtual void startAbilityForResult(const QVariantMap &want, const QVariantMap &startOptions,
+                                       const std::function<void(Napi::Value,Napi::Value)> &resultHandler);
+    virtual void terminateSelfWithResult(const QVariantMap &abilityResult);
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHPLATFORMABILITYCTRL_H
diff --git a/src/plugins/platforms/openharmony/qohplatformbackingstore.cpp b/src/plugins/platforms/openharmony/qohplatformbackingstore.cpp
new file mode 100644
index 00000000000..d61b5eea1f9
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformbackingstore.cpp
@@ -0,0 +1,438 @@
+#include <QPainter>
+#include <qpa/qplatformscreen.h>
+#include <qopenharmonydefines.h>
+#include <poll.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <native_window/external_window.h>
+#include <private/qimage_p.h>
+#include <private/qwindow_p.h>
+
+#include "qohmain.h"
+#include "qohplatformbackingstore.h"
+
+#include <cstring>
+#include <native_buffer/native_buffer.h>
+#include <native_window/buffer_handle.h>
+#include <QScopeGuard>
+#include <QtGui/private/qhighdpiscaling_p.h>
+#include "qohplatformwindow.h"
+
+QT_BEGIN_NAMESPACE
+
+std::uint64_t getNativeWindowBufferQueueSize(::OHNativeWindow *nativeWindow)
+{
+    std::int32_t bufferQueueSize = 5;
+    auto getBufferQueueSizeResult = ::OH_NativeWindow_NativeWindowHandleOpt(
+            nativeWindow, ::NativeWindowOperation::GET_BUFFERQUEUE_SIZE, &bufferQueueSize);
+    if (Q_UNLIKELY(getBufferQueueSizeResult != 0)) {
+        qCWarning(lcQpaBackingStore) << "call OH_NativeWindow_NativeWindowHandleOpt failed." << getBufferQueueSizeResult;
+    }
+    return bufferQueueSize;
+}
+
+class BufferRegionHandler
+{
+public:
+    BufferRegionHandler(::OHNativeWindow *nativeWindow)
+        : m_bufferQueueSize(getNativeWindowBufferQueueSize(nativeWindow))
+    {
+    }
+
+    QRegion mergeRegionForBufferHandle(::BufferHandle *bufferHandle, QRegion region) const
+    {
+        const auto it = m_buffersToFlushSequenceIds.find(bufferHandle);
+        if (it == m_buffersToFlushSequenceIds.end()) {
+            return {};
+        }
+
+        std::uint64_t numberOfRegions = m_flushSequenceId - it->second;
+        if (numberOfRegions > m_bufferQueueSize) {
+            return {};
+        }
+
+        for (auto it = m_lastFlushedRegions.cend() - numberOfRegions;
+             it != m_lastFlushedRegions.cend(); ++it) {
+            region = region.united(*it);
+        }
+
+        return region;
+    }
+    void storeRegionForBufferHandle(::BufferHandle *bufferHandle, const QRegion &region)
+    {
+        m_buffersToFlushSequenceIds[bufferHandle] = m_flushSequenceId;
+
+        if (m_buffersToFlushSequenceIds.size() > m_bufferQueueSize) {
+            m_buffersToFlushSequenceIds.clear();
+            m_lastFlushedRegions.clear();
+            m_flushSequenceId = 0;
+            return;
+        }
+
+        m_lastFlushedRegions.push_back(region);
+        if (m_lastFlushedRegions.size() > m_bufferQueueSize) {
+            m_lastFlushedRegions.pop_front();
+        }
+
+        ++m_flushSequenceId;
+    }
+
+private:
+    const std::uint64_t m_bufferQueueSize;
+    std::uint64_t m_flushSequenceId { 0 };
+    std::unordered_map<::BufferHandle *, std::uint64_t> m_buffersToFlushSequenceIds;
+    std::deque<QRegion> m_lastFlushedRegions;
+};
+
+constexpr std::int32_t ohNativeWindowErrorCodeSuccess = 0;
+QOhPlatformBackingStore::QOhPlatformBackingStore(QWindow *window)
+    : QPlatformBackingStore(window)
+    , m_alphaNeedsFill(false)
+    , m_regionHandler(nullptr)
+{
+}
+
+QOhPlatformBackingStore::~QOhPlatformBackingStore()
+{
+
+}
+
+QPaintDevice *QOhPlatformBackingStore::paintDevice()
+{
+    return &m_image;
+}
+
+void QOhPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents)
+{
+    QSize actualSize = size;
+    if (window()->handle()) {
+        QSize windowSize = window()->handle()->geometry().size();
+        actualSize = QSize(qMax(size.width(), windowSize.width()), qMax(size.height(), windowSize.height()));
+    }
+
+    if (m_image.isNull() || m_image.size() != actualSize) {
+        QImage::Format format = window()->screen()->handle()->format();
+
+        QImage oldImage  = m_image;
+        if (QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha)
+            m_alphaNeedsFill = true;
+        else
+            format = qt_maybeAlphaVersionWithSameDepth(format);
+
+        QImage newImage(actualSize.width(), actualSize.height(), format);
+
+        if (!oldImage.isNull() && !staticContents.isEmpty()) {
+            QRegion staticRegion(staticContents);
+            staticRegion &= QRect(0, 0, oldImage.width(), oldImage.height());
+            staticRegion &= QRect(0, 0, newImage.width(), newImage.height());
+            QPainter painter(&newImage);
+            painter.setCompositionMode(QPainter::CompositionMode_Source);
+            for (const QRect &rect : staticRegion)
+                painter.drawImage(rect, oldImage, rect);
+        }
+
+        m_image = newImage;
+    }
+}
+
+Q_GUI_EXPORT void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
+
+bool QOhPlatformBackingStore::scroll(const QRegion &area, int dx, int dy)
+{
+    if (m_image.isNull())
+        return false;
+
+    const QPoint offset(dx, dy);
+    for (const QRect &rect : area)
+        qt_scrollRectInImage(m_image, rect, offset);
+
+    return true;
+}
+
+void QOhPlatformBackingStore::beginPaint(const QRegion &region)
+{
+    if (m_alphaNeedsFill) {
+        QPainter p(&m_image);
+        p.setCompositionMode(QPainter::CompositionMode_Source);
+        const QColor blank = Qt::transparent;
+        for (const QRect &r : region)
+            p.fillRect(r, blank);
+    }
+}
+
+QImage QOhPlatformBackingStore::toImage() const
+{
+    return m_image;
+}
+
+void QOhPlatformBackingStore::releaseVsync(QWindow *w)
+{
+#if OHOS_SDK_VERSION > 14
+    auto internalRelease = [](QWindow *w) {
+        if (m_vsyncs.contains(w)) {
+            auto vsync = m_vsyncs.take(w);
+            if (vsync) {
+                // 只做标记,在最后的callback中去做删除
+                vsync->setDeleted(true);
+            }
+        }
+    };
+    internalRelease(w);
+    auto children = w->findChildren<QWindow *>();
+    for (auto child : children) {
+        internalRelease(child);
+    }
+#endif
+}
+
+QImage::Format mapNativeBufferFormatToQImageFormatOrFail(std::int32_t format)
+{
+    QImage::Format result;
+
+    switch (format) {
+    case ::NATIVEBUFFER_PIXEL_FMT_RGB_888:
+        result = QImage::Format_RGB888;
+        break;
+    case ::NATIVEBUFFER_PIXEL_FMT_RGBA_8888:
+        result = QImage::Format_RGBA8888;
+        break;
+    default:
+        qFatal("%s: unsupported format %d", Q_FUNC_INFO, format);
+    }
+    return result;
+}
+bool tryMapBufferHandleMemory(::BufferHandle *bufferHandle, void *&outMemory)
+{
+    void *bufferMemory = ::mmap(
+            bufferHandle->virAddr, bufferHandle->size, PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0);
+
+    if (bufferMemory == MAP_FAILED) {
+        int mmapErrno = errno;
+        return false;
+    }
+
+    outMemory = bufferMemory;
+    return true;
+}
+
+void copyImage(const QImage &srcImage, QImage &dstImage)
+{
+    const int copyHeight = qMin(srcImage.height(), dstImage.height());
+
+    // 逐行拷贝重叠区域
+    for(int y = 0; y < copyHeight; ++y) {
+        const uchar* srcLine = srcImage.constScanLine(y);
+        uchar* dstLine = dstImage.scanLine(y);
+        std::memcpy(dstLine, srcLine, qMin(srcImage.bytesPerLine(), dstImage.bytesPerLine()));
+    }
+}
+
+void copyImage(const QImage &srcImage, QImage &dstImage, const QRegion &region)
+{
+    // 获取源图像和目标图像的有效区域
+    const QRect srcRect = QRect(0, 0, srcImage.width(), srcImage.height());
+    const QRect dstRect = QRect(0, 0, dstImage.width(), dstImage.height());
+
+    // 计算实际可拷贝的区域(考虑两个图像边界和指定区域)
+    QRegion validRegion = region;
+    validRegion &= srcRect;  // 限制在源图像范围内
+    validRegion &= dstRect;  // 限制在目标图像范围内
+
+    // 确保图像格式一致(至少深度/像素大小一致)
+    if(srcImage.depth() != dstImage.depth()) {
+        qCWarning(lcQpaBackingStore) << "Image depths differ, colors may be incorrect";
+        return;
+    }
+
+    const int bytesPerPixel = srcImage.depth() / 8;
+
+    // 遍历每个矩形区域
+    for(const QRect &rect : validRegion) {
+        // 计算每行的起始位置和拷贝字节数
+        const int xSrc = rect.x() * bytesPerPixel;
+        const int xDst = rect.x() * bytesPerPixel;
+        const int copyBytes = rect.width() * bytesPerPixel;
+
+        // 确保不会越界(二次检查)
+        const int srcMaxOffset = srcImage.bytesPerLine() - xSrc;
+        const int dstMaxOffset = dstImage.bytesPerLine() - xDst;
+        const int actualCopyBytes = qMin(copyBytes, qMin(srcMaxOffset, dstMaxOffset));
+
+        if(actualCopyBytes <= 0) continue;
+
+        // 逐行拷贝
+        for(int row = 0; row < rect.height(); ++row) {
+            const int y = rect.y() + row;
+
+            // 再次检查行范围
+            if(y >= srcImage.height() || y >= dstImage.height()) break;
+
+            const uchar* srcRow = srcImage.constScanLine(y) + xSrc;
+            uchar* dstRow = dstImage.scanLine(y) + xDst;
+
+            std::memcpy(dstRow, srcRow, actualCopyBytes);
+        }
+    }
+}
+
+std::vector<::Region::Rect> makeOhosRegionRectsForFlush(
+        const QRegion &region, const QPoint &rootwindowOffset, const QSize &dstImageSize)
+{
+    std::vector<::Region::Rect> rects;
+    if (!region.isEmpty()){
+        std::transform(
+                    region.begin(), region.end(), std::back_inserter(rects),
+                    [&](const auto &qrect){
+                        return ::Region::Rect{
+                        .x = qrect.x() + rootwindowOffset.x(),
+                        .y = (dstImageSize.height() - qrect.y()) + rootwindowOffset.y() - qrect.height(),
+                        .w = static_cast<std::uint32_t>(qrect.width()),
+                        .h = static_cast<std::uint32_t>(qrect.height()),
+            };
+        });
+    }
+    return rects;
+}
+
+
+void QOhPlatformBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+{
+    auto platformWindow = window->handle();
+    if (platformWindow == nullptr) {
+        qCWarning(lcQpaBackingStore) << window << "native window has destroyed";
+        return;
+    }
+    if (!platformWindow->isExposed()) {
+        qCWarning(lcQpaBackingStore) << window << "window not exposed";
+        return;
+    }
+    WId id = window->winId();
+    WindowNode *node = reinterpret_cast<WindowNode *>(id);
+
+    if (node == nullptr) {
+        qCWarning(lcQpaBackingStore) << "get window node failed.";
+        return;
+    }
+
+    OHNativeWindow *nativeWindow = reinterpret_cast<OHNativeWindow *>(node->window);
+    if (nativeWindow == nullptr) {
+        qCWarning(lcQpaBackingStore) << Q_FUNC_INFO << "get xcomponent node window failed, window" << window;
+        return;
+    }
+
+    if (m_regionHandler == nullptr) {
+        m_regionHandler = std::make_unique<BufferRegionHandler>(nativeWindow);
+    }
+
+#if OHOS_SDK_VERSION > 14
+    if (!m_vsyncs.contains(window)) {
+        m_vsyncs.insert(window, new QOhNativeVSync(window, this));
+    }
+
+    auto vsync = m_vsyncs.value(window);
+    if (vsync) {
+        if (!vsync->isReady()) {
+            // qCWarning(lcQpaBackingStore) << "OHOS buffer not ready, wait for its ready.";
+            vsync->saveFrame(window, region, offset);
+            return;
+        } else if (vsync->isPendingFlush()) {
+            vsync->flush();
+            vsync->saveFrame(window, region, offset);
+            return;
+        } else {
+            vsync->clearFlag();
+        }
+    }
+#endif
+    int fenceFd = -1;
+    OHNativeWindowBuffer *buffer = nullptr;
+    int ret = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &buffer, &fenceFd);
+    if (ret != 0 || nullptr == buffer) {
+        qCWarning(lcQpaBackingStore) << "call OH_NativeWindow_NativeWindowRequestBuffer failed.";
+        return;
+    }
+    bool isRootWindow = window == this->window();
+    const QRect windowRect = platformWindow->geometry();
+    QPoint copyPoint(qMax(0, offset.x()), qMax(0, offset.y()));
+    QRect copyRect = QRect(copyPoint, windowRect.size());
+    QImage srcImage = isRootWindow
+            ? m_image
+            : m_image.copy(copyRect.intersected(m_image.rect()));
+
+    auto nativeWindowAbortBufferGuard = qScopeGuard([nativeWindow, buffer](){
+        auto abortBufferEc = ::OH_NativeWindow_NativeWindowAbortBuffer(nativeWindow, buffer);
+        if (abortBufferEc != ohNativeWindowErrorCodeSuccess) {
+            return;
+        }
+    });
+
+    BufferHandle *bufferHandle = OH_NativeWindow_GetBufferHandleFromNative(buffer);
+    if (bufferHandle == nullptr) {
+        qCWarning(lcQpaBackingStore) << "call OH_NativeWindow_GetBufferHandleFromNative failed.";
+        return;
+    }
+
+#if OHOS_SDK_VERSION > 14
+    // 如果QWidget主动设置大小之后绘制时,
+    // 由于异步设置系统窗口大小还未正确改变成设置的大小,导致绘制不完整。保存重新绘制
+    auto geometry = platformWindow->geometry();
+    if (bufferHandle->width != geometry.width() || bufferHandle->height != geometry.height())
+        vsync->saveFrame(window, region, offset);
+#endif
+    int width = qMin(bufferHandle->width, m_image.width());
+    int height = qMin(bufferHandle->height, m_image.height());
+
+    int retCode = -1;
+    uint32_t timeout = 3000;
+    if (fenceFd != -1) {
+        struct pollfd pollfds = {fenceFd, POLLIN, 0};
+        do {
+            retCode = poll(&pollfds, 1, timeout);
+        } while (retCode == -1 && (errno == EINTR || errno == EAGAIN));
+        close(fenceFd); /* 防止fd泄漏 */
+    }
+
+    QImage::Format dstImageFormat = mapNativeBufferFormatToQImageFormatOrFail(bufferHandle->format);
+    QSize dstImageSize{width, height};
+    uchar *mappedAddress =
+            static_cast<uchar*>(mmap(bufferHandle->virAddr, bufferHandle->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0));
+
+    if (mappedAddress == MAP_FAILED) {
+        qCWarning(lcQpaBackingStore) << "mmap failed";
+        return;
+    }
+
+    if (offset.y() < 0) {
+        int offsetY = abs(offset.y());
+        if (offsetY + dstImageSize.height() > windowRect.height())
+            offsetY = windowRect.height() - dstImageSize.height();
+        mappedAddress += bufferHandle->stride * offsetY;
+    }
+    QImage dstImage(
+                mappedAddress,
+                dstImageSize.width(), dstImageSize.height(),
+                bufferHandle->stride,
+                dstImageFormat);
+
+    const auto& mergedRegionOpt = m_regionHandler->mergeRegionForBufferHandle(bufferHandle, region);
+
+    std::vector<::Region::Rect> rects;
+    if (mergedRegionOpt.isEmpty() || mergedRegionOpt.isNull()) {
+        copyImage(srcImage, dstImage);
+        rects = makeOhosRegionRectsForFlush(QRegion(), isRootWindow ? QPoint{} : offset, dstImage.size());
+    } else {
+        copyImage(srcImage, dstImage, mergedRegionOpt);
+        rects = makeOhosRegionRectsForFlush(mergedRegionOpt, isRootWindow ? QPoint{} : offset, dstImage.size());
+    }
+
+    OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, -1,
+                                            ::Region{
+                                                .rects = rects.empty() ? nullptr : rects.data(),
+                                                .rectNumber = static_cast<std::int32_t>(rects.size()),
+                                            });
+    nativeWindowAbortBufferGuard.dismiss();
+    munmap(mappedAddress, bufferHandle->size);
+    m_regionHandler->storeRegionForBufferHandle(bufferHandle, region);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohplatformbackingstore.h b/src/plugins/platforms/openharmony/qohplatformbackingstore.h
new file mode 100644
index 00000000000..37a0392941d
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformbackingstore.h
@@ -0,0 +1,42 @@
+#ifndef QOHPLATFORMBACKINGSTORE_H
+#define QOHPLATFORMBACKINGSTORE_H
+
+#include <qpa/qplatformbackingstore.h>
+#include "qohnativevsync.h"
+
+#include <deque>
+#include <native_window/buffer_handle.h>
+#include <native_window/external_window.h>
+#include <unordered_map>
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+class BufferRegionHandler;
+class QOhPlatformBackingStore : public QPlatformBackingStore
+{
+public:
+    explicit QOhPlatformBackingStore(QWindow *window);
+    ~QOhPlatformBackingStore();
+    QPaintDevice *paintDevice() override;
+
+    void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
+    void resize(const QSize &size, const QRegion &staticContents) override;
+    bool scroll(const QRegion &area, int dx, int dy) override;
+    void beginPaint(const QRegion &) override;
+    QImage toImage() const override;
+
+    static void releaseVsync(QWindow *w);
+
+private:
+    QImage m_image;
+    bool m_alphaNeedsFill;
+#if OHOS_SDK_VERSION > 14
+    static inline QHash<QWindow *, QOhNativeVSync *> m_vsyncs = {};
+#endif
+
+    std::unique_ptr<BufferRegionHandler> m_regionHandler;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHPLATFORMBACKINGSTORE_H
diff --git a/src/plugins/platforms/openharmony/qohplatformclipboard.cpp b/src/plugins/platforms/openharmony/qohplatformclipboard.cpp
new file mode 100644
index 00000000000..937f08d8740
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformclipboard.cpp
@@ -0,0 +1,257 @@
+#include <QSet>
+#include <QUrl>
+#include <QImage>
+#include <QBuffer>
+#include <QTextDocument>
+#include <QLoggingCategory>
+#include <QtCore/qopenharmonydefines.h>
+
+#include <typeinfo>
+#include <database/udmf/udmf_meta.h>
+#include <database/udmf/udmf_err_code.h>
+#include <database/pasteboard/oh_pasteboard.h>
+#include <database/pasteboard/oh_pasteboard_err_code.h>
+
+#include "qohauxiliary.h"
+#include "qohplatformclipboard.h"
+#include "qpa/qplatformaccessctrl.h"
+#include "qpa/qplatformintegration.h"
+#include "private/qguiapplication_p.h"
+
+#ifndef QT_NO_CLIPBOARD
+
+#define qClipBoard QOhPlatformClipboard::instance()
+
+Q_LOGGING_CATEGORY(clipboard, "qt.ohos.clipboard")
+
+/* TODO 系统提供的剪切板相关处理不完善
+ * 无法进行延迟数据读取等操作
+ */
+class QOhPasteDataObject
+{
+public:
+    explicit QOhPasteDataObject(QMimeData *data) : m_data(data){}
+    ~QOhPasteDataObject() = default;
+
+    void releaseQt() { m_data = nullptr; }
+    QMimeData *mimeData() { return m_data.data(); }
+
+private:
+    QPointer<QMimeData> m_data;
+};
+
+/*!
+ * \brief 剪贴板数据变更观察者对象销毁时的通知回调函数
+ */
+void QOhPlatformClipboard::pasteboardFinalizeImpl(void *context)
+{
+    Q_UNUSED(context);
+    LOGW("pasteboard finalize impl");
+}
+
+/*!
+ * \brief 贴板数据内容变更时的通知回调函数
+ */
+void QOhPlatformClipboard::pasteboardNofityImpl(void *context, ::Pasteboard_NotifyType type)
+{
+    Q_UNUSED(type);
+    Q_UNUSED(context);
+
+    QtOh::runOnQtMainThread([]{
+        if (qClipBoard) {
+            qClipBoard->emitChanged(QClipboard::Clipboard);
+        }
+    });
+    LOGW("pasteboard notify impl");
+}
+
+#if OHOS_SDK_VERSION >= 15
+void QOhPlatformClipboard::reportProgress()
+{
+    int status = ::PASTEBOARD_ErrCode::ERR_OK;
+    ::OH_UdmfData *data = ::OH_Pasteboard_GetDataWithProgress(m_pasteboard.get(), m_params.get(), &status);
+    if (::PASTEBOARD_ErrCode::ERR_OK != status) {
+        qCWarning(clipboard, "%s get data with progress failed: %d", Q_FUNC_INFO, status);
+    }
+    ::OH_UdmfData_Destroy(data);
+}
+
+QClipboard::ProgressMode QOhPlatformClipboard::progressMode() const
+{
+    return m_progressMode;
+}
+
+void QOhPlatformClipboard::setProgressMode(QClipboard::ProgressMode mode)
+{
+    /* 进度回调---用于非默认进度显示 表示进度数据变化的订阅函数
+     * 当选择不使用系统默认进度显示时,可设置该项获取粘贴过程的进度
+     */
+    if (QClipboard::ProgressMode::Default == mode) {
+        ::OH_Pasteboard_GetDataParams_SetProgressIndicator(m_params.get(), ::Pasteboard_ProgressIndicator::PASTEBOARD_DEFAULT);
+        ::OH_Pasteboard_GetDataParams_SetProgressListener(m_params.get(), nullptr);
+    } else if (QClipboard::ProgressMode::None == mode) {
+        ::OH_Pasteboard_GetDataParams_SetProgressIndicator(m_params.get(), ::Pasteboard_ProgressIndicator::PASTEBOARD_NONE);
+        ::OH_Pasteboard_GetDataParams_SetProgressListener(m_params.get(), &QOhPlatformClipboard::pasteboardProgressListener);
+    }
+    m_progressMode = mode;
+}
+
+/*!
+ * \brief 非默认进度条显示-回调函数
+ * \param progressInfo 定义进度上报的数据结构
+ * 且仅当进度指示选项Pasteboard_ProgressIndicator设置为NONE时才会上报此信息
+ */
+void QOhPlatformClipboard::pasteboardProgressListener(::Pasteboard_ProgressInfo *progressInfo)
+{
+    /* 通过Pasteboard_ProgressInfo获取粘贴进度
+     * 且仅当进度指示选项Pasteboard_ProgressIndicator设置
+     * 为PASTEBOARD_NONE时,才可以获取到此信息
+     */
+    int percentage = ::OH_Pasteboard_ProgressInfo_GetProgress(progressInfo);
+    if (qClipBoard) {
+        QMetaObject::invokeMethod(QGuiApplication::clipboard(), "progressValueChanged", Q_ARG(int, percentage));
+    }
+    LOGI("%{public}s, percentage: %{public}d", Q_FUNC_INFO, percentage);
+}
+#endif
+
+template<typename T, typename Deleter>
+QSharedPointer<T> newSharedOrFail(T *ptr, Deleter &&deleter)
+{
+    if (ptr == nullptr) {
+        qFatal("%s: got null pointer with deleter of type '%s'",
+               Q_FUNC_INFO, typeid(deleter).name());
+    }
+
+    return QSharedPointer<T>(ptr, deleter);
+}
+
+QOhPlatformClipboard::QOhPlatformClipboard()
+    : m_mimeData(new QMimeData())
+    , m_pasteboard(nullptr)
+    , m_observer(nullptr)
+#if OHOS_SDK_VERSION >= 15
+    , m_progressMode(QClipboard::ProgressMode::None)
+    , m_params(nullptr)
+#endif
+{
+    m_pasteboard = newSharedOrFail(::OH_Pasteboard_Create(), ::OH_Pasteboard_Destroy);  /* 创建剪贴板实例 */
+    m_observer = newSharedOrFail(::OH_PasteboardObserver_Create(), ::OH_PasteboardObserver_Destroy); /* 创建剪贴板数据变更观察者实例 */
+#if OHOS_SDK_VERSION >= 15
+    m_params = newSharedOrFail(::OH_Pasteboard_GetDataParams_Create(), ::OH_Pasteboard_GetDataParams_Destroy);
+    /* 向剪贴板设置进度条指示选项,采用系统默认进度显示
+     * PASTEBOARD_NONE 不采用系统默认进度显示
+     * PASTEBOARD_DEFAULT 采用系统默认进度显示。
+     */
+    ::OH_Pasteboard_GetDataParams_SetProgressIndicator(m_params.get(), ::Pasteboard_ProgressIndicator::PASTEBOARD_NONE);
+
+    /* 进度回调---用于非默认进度显示 表示进度数据变化的订阅函数
+     * 当选择不使用系统默认进度显示时,可设置该项获取粘贴过程的进度
+    */
+    ::OH_Pasteboard_GetDataParams_SetProgressListener(m_params.get(), &QOhPlatformClipboard::pasteboardProgressListener);
+#endif
+    /* 将两个回调函数设置到观察者实例 */
+    ::OH_PasteboardObserver_SetData(m_observer.get(), reinterpret_cast<void*>(this),
+                                    &QOhPlatformClipboard::pasteboardNofityImpl,
+                                    &QOhPlatformClipboard::pasteboardFinalizeImpl);
+
+    /* 设置对剪贴板本地设备数据变化的订阅 */
+    ::OH_Pasteboard_Subscribe(m_pasteboard.get(), NOTIFY_LOCAL_DATA_CHANGE, m_observer.get());
+    m_self = this;
+}
+
+QOhPlatformClipboard::~QOhPlatformClipboard()
+{
+#if OHOS_SDK_VERSION >= 15
+    ::OH_Pasteboard_ProgressCancel(m_params.get());
+#endif
+    OH_Pasteboard_Unsubscribe(m_pasteboard.get(), NOTIFY_LOCAL_DATA_CHANGE, m_observer.get());
+    /* TODO 应用在harmony平台对剪贴板是否存在所有权?,需要责清理系统剪贴板数据吗? */
+    //OH_Pasteboard_ClearData(m_pasteboard.get());
+
+    if (m_mimeData) {
+        m_mimeData->deleteLater();
+        m_mimeData = nullptr;
+    }
+
+    m_self = nullptr;    
+}
+
+QOhPlatformClipboard *QOhPlatformClipboard::instance()
+{
+    return m_self;
+}
+
+QMimeData *QOhPlatformClipboard::mimeData(QClipboard::Mode mode)
+{
+    Q_UNUSED(mode);
+    if (!supportsMode(mode))
+        return nullptr;
+
+    /* 检查剪贴板中是否有数据 */
+    if (!OH_Pasteboard_HasData(m_pasteboard.get())) {
+        qCWarning(clipboard) << Q_FUNC_INFO << "the clipboard has no data.";
+        return m_mimeData.data();
+    }
+    int status = ::PASTEBOARD_ErrCode::ERR_OK;
+    ::OH_UdmfData *data = ::OH_Pasteboard_GetData(m_pasteboard.get(), &status);
+    if (::PASTEBOARD_ErrCode::ERR_OK != status) {
+        ::OH_UdmfData_Destroy(data);
+        qCWarning(clipboard, "%s get clipboard data failed: %d", Q_FUNC_INFO, status);
+        return m_mimeData.data();
+    }
+
+    QtOh::UdmfHelper::acquireDatasFromUdmfToMime(data, m_mimeData);
+    return m_mimeData.data();
+}
+
+void QOhPlatformClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
+{
+    if (!supportsMode(mode)) {
+        qCDebug(clipboard) << "the platform does not support clipboard mode:" << mode;
+        return;
+    }
+
+    const bool newData = !m_mimeData || m_mimeData != data;
+    if (newData) {
+        if (data) {
+            m_mimeData ? [this](){ delete m_mimeData; m_mimeData = nullptr; }() : void();
+#if OHOS_SDK_VERSION >= 15
+            ::OH_Pasteboard_ProgressCancel(m_params.get());
+#endif
+            m_mimeData = data;
+        } else {
+            m_mimeData = new QMimeData();
+        }
+    }
+
+    OH_UdmfData *t = QtOh::UdmfHelper::makeUdmfDataFromMime(m_mimeData);
+    int code = ::OH_Pasteboard_SetData(m_pasteboard.get(), t);
+    if (PASTEBOARD_ErrCode::ERR_OK != code) {
+        OH_UdmfData_Destroy(t);
+        qCWarning(clipboard, "%s set pasteboard data failed, code: %d", Q_FUNC_INFO, code);
+    }
+}
+
+bool QOhPlatformClipboard::supportsMode(QClipboard::Mode mode) const
+{
+    return QClipboard::Clipboard == mode;
+}
+
+void QOhPlatformClipboard::releaseData()
+{
+    if (m_data) {
+        delete m_data->mimeData();
+        m_data->releaseQt();
+
+        delete m_data;
+        m_data = nullptr;
+    }
+}
+
+bool QOhPlatformClipboard::ownsClipboard() const
+{
+    return m_data;
+}
+
+#endif // QT_NO_CLIPBOARD
diff --git a/src/plugins/platforms/openharmony/qohplatformclipboard.h b/src/plugins/platforms/openharmony/qohplatformclipboard.h
new file mode 100644
index 00000000000..d727db285be
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformclipboard.h
@@ -0,0 +1,54 @@
+#ifndef QOHPLATFORMCLIPBOARD_H
+#define QOHPLATFORMCLIPBOARD_H
+
+#include <QPointer>
+#include <QMimeData>
+#include <qpa/qplatformclipboard.h>
+
+#include <database/pasteboard/oh_pasteboard.h>
+
+#ifndef QT_NO_CLIPBOARD
+
+#if OHOS_SDK_VERSION >= 15
+struct Pasteboard_GetDataParams;
+#endif
+
+class QOhPasteDataObject;
+
+class QOhPlatformClipboard: public QPlatformClipboard
+{
+public:
+    QOhPlatformClipboard();
+    ~QOhPlatformClipboard();
+    static QOhPlatformClipboard *instance();
+
+    QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;
+    void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) override;
+    bool supportsMode(QClipboard::Mode mode) const override;
+
+private:
+    void releaseData();
+    bool ownsClipboard() const;
+    static void pasteboardFinalizeImpl(void *context);
+    static void pasteboardNofityImpl(void *context, ::Pasteboard_NotifyType type);
+#if OHOS_SDK_VERSION >= 15
+    void reportProgress() override;
+    QClipboard::ProgressMode progressMode() const override;
+    void setProgressMode(QClipboard::ProgressMode mode) override;
+    static void pasteboardProgressListener(::Pasteboard_ProgressInfo* progressInfo);
+#endif
+private:
+    QPointer<QMimeData> m_mimeData;
+    static inline QOhPlatformClipboard *m_self = nullptr;
+    QOhPasteDataObject *m_data = nullptr;
+    QSharedPointer<OH_Pasteboard> m_pasteboard;
+    QSharedPointer<OH_PasteboardObserver> m_observer;
+#if OHOS_SDK_VERSION >= 15
+    QClipboard::ProgressMode m_progressMode;
+    QSharedPointer<Pasteboard_GetDataParams> m_params;
+#endif
+};
+
+#endif // QT_NO_CLIPBOARD
+
+#endif // QOHPLATFORMCLIPBOARD_H
diff --git a/src/plugins/platforms/openharmony/qohplatformcursor.cpp b/src/plugins/platforms/openharmony/qohplatformcursor.cpp
new file mode 100644
index 00000000000..914a2471f6e
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformcursor.cpp
@@ -0,0 +1,241 @@
+#include "qohplatformcursor.h"
+#include "jsclass/qjscursor.h"
+#include "qohplatformwindow.h"
+#include "qohwindowcontext.h"
+#include <QtCore/qopenharmonydefines.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
+#include <QCursor>
+#include <QPixmap>
+#include <QImage>
+#include <QByteArray>
+#include <QBuffer>
+#include <QIODevice>
+#include <QBitmap>
+
+QT_BEGIN_NAMESPACE
+
+PixmapCursorCacheKey::PixmapCursorCacheKey(const QCursor &c)
+    : bitmapCacheKey(c.pixmap().cacheKey()), maskCacheKey(0)
+{
+    if (!bitmapCacheKey) {
+        Q_ASSERT(!c.bitmap(Qt::ReturnByValue).isNull());
+        Q_ASSERT(!c.mask(Qt::ReturnByValue).isNull());
+        bitmapCacheKey = c.bitmap(Qt::ReturnByValue).cacheKey();
+        maskCacheKey = c.mask(Qt::ReturnByValue).cacheKey();
+    }
+}
+
+QOhPlatformCursor::QOhPlatformCursor(const QPlatformScreen *screen)
+    : m_screen(screen)
+{
+    if (!m_jsCursor)
+        m_jsCursor.reset(new QJsCursor);
+    if (!m_defaultCursor)
+        m_defaultCursor.reset(new QCursorInfo{QJsCursor::DEFAULT});
+}
+
+void QOhPlatformCursor::changeCursor(QCursor *windowCursor, QWindow *window)
+{
+    QOhPlatformWindow *platformWindow = QOhWindowContext::get(window);
+    if (!platformWindow) // Desktop/Foreign window.
+        return;
+
+    if (!windowCursor) {
+        platformWindow->setCursor(nullptr);
+        return;
+    };
+
+    QCursorInfo *wcursor = cursorInfo(*windowCursor);
+    if (wcursor != nullptr) {
+        platformWindow->setCursor(wcursor);
+    }
+}
+
+void QOhPlatformCursor::setOverrideCursor(const QCursor &cursor)
+{
+    m_overrideCursor = cursorInfo(cursor);
+    if (m_overrideCursor != nullptr && m_windowId != -1) {
+        m_jsCursor->setCursor(m_windowId, m_overrideCursor);
+    }
+}
+
+void QOhPlatformCursor::clearOverrideCursor()
+{
+    if (m_overrideCursor != nullptr) {
+        m_overrideCursor = nullptr;
+        if (m_currentCursor != nullptr && m_windowId != -1) {
+            m_jsCursor->setCursor(m_windowId, m_currentCursor);
+        }
+    }
+}
+
+QPoint QOhPlatformCursor::pos() const
+{
+    return m_pos;
+}
+
+void QOhPlatformCursor::setPos(const QPoint &pos)
+{
+    m_pos = pos;
+}
+
+QSize QOhPlatformCursor::size() const
+{
+    return QPlatformCursor::size();
+}
+
+void QOhPlatformCursor::setWindowOverrideCursor(int windowId, QCursorInfo *info)
+{
+    if (info != nullptr)
+        m_jsCursor->setCursor(windowId, info);
+}
+
+void QOhPlatformCursor::setCursor(int windowId, QCursorInfo *info)
+{
+    m_windowId = windowId;
+    m_currentCursor = info;
+    m_jsCursor->setCursor(windowId, info);
+}
+
+void QOhPlatformCursor::setDefaultCursor(int windowId)
+{
+    m_jsCursor->setCursor(windowId, m_defaultCursor.get());
+}
+
+void QOhPlatformCursor::enforceOverrideCursor(int windowId)
+{
+    if (hasOverrideCursor()) {
+        m_windowId = windowId;
+        m_jsCursor->setCursor(windowId, m_overrideCursor);
+    }
+}
+
+QCursorInfo *QOhPlatformCursor::cursorInfo(const QCursor &cursor)
+{
+    return (cursor.shape() == Qt::BitmapCursor || cursor.shape() == Qt::CustomCursor)
+            ? pixmapWindowCursor(cursor)
+            : standardWindowCursor(cursor.shape());
+}
+
+QCursorInfo *QOhPlatformCursor::pixmapWindowCursor(const QCursor &c)
+{
+    const PixmapCursorCacheKey cacheKey(c);
+    PixmapCursorCache::iterator it = m_pixmapCursorCache.find(cacheKey);
+    if (it == m_pixmapCursorCache.end()) {
+        if (m_pixmapCursorCache.size() > 50) {
+            for (it = m_pixmapCursorCache.begin(); it != m_pixmapCursorCache.end() ; ) {
+                if (it.value() != m_currentCursor) {
+                    delete it.value();
+                    it = m_pixmapCursorCache.erase(it);
+                }
+                else
+                    ++it;
+            }
+        }
+        const qreal scaleFactor = QHighDpiScaling::factor(m_screen);
+        const QPixmap pixmap = c.pixmap();
+        QCursorInfo *info = createPixmapCursor(pixmap, c.hotSpot(), scaleFactor);
+        it = m_pixmapCursorCache.insert(cacheKey, info);
+    }
+    return it.value();
+}
+
+QCursorInfo *QOhPlatformCursor::createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor)
+{
+    const qreal pixmapScaleFactor = scaleFactor / pixmap.devicePixelRatioF();
+    if (!qFuzzyCompare(pixmapScaleFactor, 1)) {
+        pixmap = pixmap.scaled((pixmapScaleFactor * QSizeF(pixmap.size())).toSize(),
+                               Qt::KeepAspectRatio, Qt::SmoothTransformation);
+    }
+    QCursorInfo *cur = new QCursorInfo{ QJsCursor::CUSTOM, int(hotSpot.x() * scaleFactor),
+                                        int(hotSpot.y() * scaleFactor), pixmap };
+    return cur;
+}
+
+QCursorInfo *QOhPlatformCursor::standardWindowCursor(Qt::CursorShape s)
+{
+    StandardCursorCache::Iterator it = m_standardCursorCache.find(s);
+    if (it == m_standardCursorCache.end()) {
+        QJsCursor::PointerStyle pointerStyle = QJsCursor::DEFAULT;
+        switch (s) {
+        case Qt::ArrowCursor:
+            pointerStyle = QJsCursor::DEFAULT;
+            break;
+        case Qt::UpArrowCursor:
+            pointerStyle = QJsCursor::NORTH;
+            break;
+        case Qt::CrossCursor:
+            pointerStyle = QJsCursor::CROSS;
+            break;
+        case Qt::WaitCursor:
+            pointerStyle = QJsCursor::LOADING;
+            break;
+        case Qt::IBeamCursor:
+            pointerStyle = QJsCursor::TEXT_CURSOR;
+            break;
+        case Qt::SizeVerCursor:
+            pointerStyle = QJsCursor::NORTH_SOUTH;
+            break;
+        case Qt::SizeHorCursor:
+            pointerStyle = QJsCursor::WEST_EAST;
+            break;
+        case Qt::SizeBDiagCursor:
+            pointerStyle = QJsCursor::NORTH_EAST_SOUTH_WEST;
+            break;
+        case Qt::SizeFDiagCursor:
+            pointerStyle = QJsCursor::NORTH_WEST_SOUTH_EAST;
+            break;
+        case Qt::SizeAllCursor:
+            pointerStyle = QJsCursor::MOVE;
+            break;
+        case Qt::SplitVCursor:
+            pointerStyle = QJsCursor::RESIZE_UP_DOWN;
+            break;
+        case Qt::SplitHCursor:
+            pointerStyle = QJsCursor::RESIZE_LEFT_RIGHT;
+            break;
+        case Qt::PointingHandCursor:
+            pointerStyle = QJsCursor::HAND_POINTING;
+            break;
+        case Qt::ForbiddenCursor:
+            pointerStyle = QJsCursor::CURSOR_FORBID;
+            break;
+        case Qt::WhatsThisCursor:
+            pointerStyle = QJsCursor::HELP;
+            break;
+            //todo:鸿蒙没有对应的样式,暂时用"加载中"样式
+        case Qt::BusyCursor:
+            pointerStyle = QJsCursor::LOADING;
+            break;
+        case Qt::OpenHandCursor:
+            pointerStyle = QJsCursor::HAND_OPEN;
+            break;
+        case Qt::ClosedHandCursor:
+            pointerStyle = QJsCursor::HAND_GRABBING;
+            break;
+            //todo:鸿蒙没有对应的样式,暂时用"默认"样式
+        case Qt::DragCopyCursor:
+            pointerStyle = QJsCursor::DEFAULT;
+            break;
+            //todo:鸿蒙没有对应样式,暂时用"默认"样式
+        case Qt::DragMoveCursor:
+            pointerStyle = QJsCursor::DEFAULT;
+            break;
+            //todo:鸿蒙没有对应样式,暂时用"默认"样式
+        case Qt::DragLinkCursor:
+            pointerStyle = QJsCursor::DEFAULT;
+            break;
+        case Qt::BlankCursor:
+            pointerStyle = QJsCursor::HIDE;
+            break;
+        default:
+            pointerStyle = QJsCursor::DEFAULT;
+            break;
+        }
+        it = m_standardCursorCache.insert(s, new QCursorInfo{pointerStyle});
+    }
+    return it != m_standardCursorCache.end() ? it.value() : m_defaultCursor.get();
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohplatformcursor.h b/src/plugins/platforms/openharmony/qohplatformcursor.h
new file mode 100644
index 00000000000..d05ebd0257a
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformcursor.h
@@ -0,0 +1,76 @@
+
+#ifndef QOHPLATFORMCURSOR_H
+#define QOHPLATFORMCURSOR_H
+
+#include <qpa/qplatformcursor.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qhash.h>
+#include <QSize>
+#include <QPoint>
+#include "qjscursor.h"
+
+QT_BEGIN_NAMESPACE
+struct QCursorInfo;
+
+struct PixmapCursorCacheKey
+{
+    explicit PixmapCursorCacheKey(const QCursor &c);
+
+    qint64 bitmapCacheKey;
+    qint64 maskCacheKey;
+};
+
+inline bool operator==(const PixmapCursorCacheKey &k1, const PixmapCursorCacheKey &k2)
+{
+    return k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey;
+}
+
+inline uint qHash(const PixmapCursorCacheKey &k, uint seed) noexcept
+{
+    return (uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed;
+}
+
+class QOhPlatformCursor : public QPlatformCursor
+{
+public:
+    explicit QOhPlatformCursor(const QPlatformScreen *screen);
+
+    void changeCursor(QCursor * widgetCursor, QWindow * widget) override;
+    void setOverrideCursor(const QCursor &cursor) override;
+    void clearOverrideCursor() override;
+
+    QPoint pos() const override;
+    void setPos(const QPoint &pos) override;
+    QSize size() const override;
+
+    static void setWindowOverrideCursor(int windowId, QCursorInfo *info);
+    static void setCursor(int windowId, QCursorInfo *info);
+    static void setDefaultCursor(int windowId);
+    static void enforceOverrideCursor(int windowId);
+    static bool hasOverrideCursor() { return m_overrideCursor != nullptr;   }
+private:
+    inline QCursorInfo *cursorInfo(const QCursor &cursor);
+    QCursorInfo *standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor);
+    QCursorInfo *pixmapWindowCursor(const QCursor &c);
+    QCursorInfo *createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor);
+
+
+    typedef QHash<PixmapCursorCacheKey, QCursorInfo*> PixmapCursorCache;
+    typedef QHash<Qt::CursorShape, QCursorInfo*> StandardCursorCache;
+
+    const QPlatformScreen *const m_screen;
+    QPoint m_pos;
+    PixmapCursorCache m_pixmapCursorCache;
+    StandardCursorCache m_standardCursorCache;
+
+    static inline std::unique_ptr<QJsCursor> m_jsCursor = nullptr;
+    static inline QCursorInfo *m_overriddenCursor = nullptr;
+    static inline QCursorInfo *m_overrideCursor = nullptr;
+    static inline QCursorInfo *m_currentCursor = nullptr;
+    static inline std::unique_ptr<QCursorInfo> m_defaultCursor = nullptr;
+    static inline int m_windowId = -1;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHPLATFORMCURSOR_H
diff --git a/src/plugins/platforms/openharmony/qohplatformdialoghelpers.cpp b/src/plugins/platforms/openharmony/qohplatformdialoghelpers.cpp
new file mode 100644
index 00000000000..620f8df01d2
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformdialoghelpers.cpp
@@ -0,0 +1,738 @@
+#include <QDebug>
+#include <QTimer>
+#include <QWindow>
+#include <QFileInfo>
+#include <QJsModule>
+#include <QScopeGuard>
+#include <QStringList>
+#include <QTextDocument>
+#include <QGuiApplication>
+#include <QEventLoopLocker>
+#include <qpa/qplatformtheme.h>
+#include <private/qguiapplication_p.h>
+#include <QtCore/qopenharmonydefines.h>
+#include <qpa/qplatformnativeinterface.h>
+
+#include <private/qopenharmony_p.h>
+#include <private/qjspromise_p.h>
+#include "qjscontext.h"
+#include "qohnativewindowmanager.h"
+#include "qohplatformdialoghelpers.h"
+
+QT_BEGIN_NAMESPACE
+
+class QOhNativeDialogBase : public QObject
+{
+    Q_OBJECT
+public:
+    QOhNativeDialogBase() {}
+    virtual ~QOhNativeDialogBase() {}
+    void exec(QWindow *parent) { doExec(parent); m_executed = true; }
+    bool executed() const { return m_executed; }
+signals:
+    void accepted();
+    void rejected();
+protected:
+    virtual void doExec(QWindow *parent) = 0;
+private:
+    bool m_executed = false;
+};
+
+class QOhPlatformMessageDialogHelper: public QPlatformMessageDialogHelper
+{
+    Q_OBJECT
+public:
+    QOhPlatformMessageDialogHelper();
+    ~QOhPlatformMessageDialogHelper();
+    void exec() override;
+    bool show(Qt::WindowFlags windowFlags,
+              Qt::WindowModality windowModality,
+              QWindow *parent) override;
+    void hide() override;
+
+public slots:
+    void setDialogResult(int buttonID);
+
+private:
+    void addButtons(QSharedPointer<QMessageDialogOptions> opt, ButtonRole role);
+
+private:
+    int m_buttonId;
+    bool m_shown;
+    QStringList m_buttons;
+    QList<int> m_buttonIds;
+};
+
+QOhPlatformMessageDialogHelper::QOhPlatformMessageDialogHelper()
+    : m_buttonId(-1)
+    , m_shown(false)
+{
+
+}
+
+QOhPlatformMessageDialogHelper::~QOhPlatformMessageDialogHelper()
+{
+
+}
+
+void QOhPlatformMessageDialogHelper::exec()
+{
+    if (!m_shown)
+        show(Qt::Dialog, Qt::ApplicationModal, 0);
+}
+
+static QString htmlText(QString text)
+{
+    if (Qt::mightBeRichText(text))
+        return text;
+    text.remove(QLatin1Char('\r'));
+    return text.toHtmlEscaped().replace(QLatin1Char('\n'), QLatin1String("<br />"));
+}
+
+bool QOhPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags
+                                         , Qt::WindowModality windowModality
+                                         , QWindow *parent)
+{
+    if (m_shown)
+        return true;
+    Q_UNUSED(windowFlags)
+    Q_UNUSED(windowModality)
+    Q_UNUSED(parent)
+
+    QSharedPointer<QMessageDialogOptions> opt = options();
+    if (!opt.data())
+        return false;
+
+    m_buttons.clear();
+    m_buttonIds.clear();
+    const int * currentLayout = buttonLayout(Qt::Horizontal);
+    while (*currentLayout != QPlatformDialogHelper::EOL) {
+        int role = (*currentLayout & ~QPlatformDialogHelper::Reverse);
+        addButtons(opt, static_cast<ButtonRole>(role));
+        ++currentLayout;
+    }
+
+    QString text = htmlText(opt->text());
+    QString str = htmlText(opt->informativeText());
+    if (!str.isEmpty())
+        text += str;
+    str = htmlText(opt->detailedText());
+    if (!str.isEmpty())
+        text += str;
+
+    m_shown = true;
+    return true;
+}
+
+void QOhPlatformMessageDialogHelper::addButtons(QSharedPointer<QMessageDialogOptions> opt, ButtonRole role)
+{
+    for (const QMessageDialogOptions::CustomButton &b : opt->customButtons()) {
+        if (b.role == role) {
+            QString label = b.label;
+            label.remove(QChar('&'));
+            m_buttons << label;
+            m_buttonIds << b.id;
+        }
+    }
+
+    for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) {
+        StandardButton b = static_cast<StandardButton>(i);
+        if (buttonRole(b) == role && (opt->standardButtons() & i)) {
+            const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(b);
+            m_buttons << text;
+            m_buttonIds << i;
+        }
+    }
+}
+
+void QOhPlatformMessageDialogHelper::hide()
+{
+    m_shown = false;
+}
+
+void QOhPlatformMessageDialogHelper::setDialogResult(int buttonID)
+{
+    m_buttonId = buttonID;
+    if (m_buttonId < 0) {
+        emit reject();
+        return;
+    }
+
+    int realId = m_buttonIds.at(m_buttonId);
+    QPlatformDialogHelper::StandardButton standardButton = static_cast<QPlatformDialogHelper::StandardButton>(realId);
+    QPlatformDialogHelper::ButtonRole role = QPlatformDialogHelper::buttonRole(standardButton);
+    if (buttonID > QPlatformDialogHelper::LastButton) {
+        const QMessageDialogOptions::CustomButton *custom = options()->customButton(buttonID);
+        Q_ASSERT(custom);
+        role = custom->role;
+    }
+    emit clicked(standardButton, role);
+}
+
+class OhFileData
+{
+public:
+    OhFileData() : m_data(new Data) {}
+    void fromOptions(const QSharedPointer<QFileDialogOptions> &o);
+
+    QUrl directory() const;
+    void setDirectory(const QUrl &);
+    QString selectedNameFilter() const;
+    void setSelectedNameFilter(const QString &);
+    QList<QUrl> selectedFiles() const;
+    void setSelectedFiles(const QList<QUrl> &);
+    void setResult(const QStringList &files);
+    QString selectedFile() const;
+private:
+    class Data : public QSharedData {
+    public:
+        QUrl directory;
+        QString selectedNameFilter;
+        QList<QUrl> selectedFiles;
+        QMutex mutex;
+    };
+    QExplicitlySharedDataPointer<Data> m_data;
+};
+
+inline QUrl OhFileData::directory() const
+{
+    m_data->mutex.lock();
+    const QUrl result = m_data->directory;
+    m_data->mutex.unlock();
+    return result;
+}
+
+inline void OhFileData::setDirectory(const QUrl &d)
+{
+    QMutexLocker locker(&m_data->mutex);
+    m_data->directory = d;
+}
+
+inline QString OhFileData::selectedNameFilter() const
+{
+    m_data->mutex.lock();
+    const QString result = m_data->selectedNameFilter;
+    m_data->mutex.unlock();
+    return result;
+}
+
+inline void OhFileData::setSelectedNameFilter(const QString &f)
+{
+    QMutexLocker locker(&m_data->mutex);
+    m_data->selectedNameFilter = f;
+}
+
+inline QList<QUrl> OhFileData::selectedFiles() const
+{
+    m_data->mutex.lock();
+    const auto result = m_data->selectedFiles;
+    m_data->mutex.unlock();
+    return result;
+}
+
+inline QString OhFileData::selectedFile() const
+{
+    const auto files = selectedFiles();
+    return files.isEmpty() ? QString() : files.front().toLocalFile();
+}
+
+inline void OhFileData::setSelectedFiles(const QList<QUrl> &urls)
+{
+    QMutexLocker locker(&m_data->mutex);
+    m_data->selectedFiles = urls;
+}
+
+void OhFileData::setResult(const QStringList &files)
+{
+    QList<QUrl> result;
+    std::transform(files.constBegin(), files.constEnd(), std::back_inserter(result), [](const QString &url){
+        return QUrl(url);
+    });
+    setSelectedFiles(result);
+}
+
+inline void OhFileData::fromOptions(const QSharedPointer<QFileDialogOptions> &o)
+{
+    QMutexLocker locker(&m_data->mutex);
+    m_data->directory = o->initialDirectory();
+    m_data->selectedFiles = o->initiallySelectedFiles();
+    m_data->selectedNameFilter = o->initiallySelectedNameFilter();
+}
+
+class QOhNativeFileDialog : public QOhNativeDialogBase
+{
+    Q_OBJECT
+public:
+    enum class OHSelectMode {
+        FILE,
+        FOLDER,
+        MIXED
+    };
+    explicit QOhNativeFileDialog(const OhFileData &data) : m_open(false), m_maxNumber(1), m_data(data) {}
+    inline void setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::AcceptMode acceptMode, QFileDialogOptions::FileDialogOptions options);
+    inline void setDirectory(const QUrl &directory);
+    inline void updateDirectory() { setDirectory(m_data.directory()); }
+    inline QString directory() const;
+    virtual void setNameFilters(const QStringList &f);
+    void selectNameFilter(const QString &filter);
+    void setUserSelectedNameFilter(int index);
+    inline void updateSelectedNameFilter() { selectNameFilter(m_data.selectedNameFilter()); }
+    inline QString selectedNameFilter() const;
+    void selectFile(const QString &fileName);
+
+protected:
+    void doExec(QWindow *parent);
+    const OhFileData &data() const { return m_data; }
+    OhFileData &data() { return m_data; }
+
+private:
+    std::pair<Napi::Value, Napi::Value> validContextAndWindow(QWindow *window) const;
+    std::shared_ptr<QJsObject> documentPicker(QWindow *parent) const;
+    OHSelectMode qtMode2OhMode(QFileDialogOptions::FileMode mode);
+    int selectMaxSelectNumber(QFileDialogOptions::FileMode mode);
+    Napi::Value documentSelectOptions() const;
+    Napi::Value documentSaveOptions() const;
+    void open(QWindow *parent);
+    void save(QWindow *parent);
+private:
+    bool m_open;
+    OHSelectMode m_mode;
+    int m_maxNumber;
+    QString m_saveFile;
+    QStringList m_nameFilters;
+    OhFileData m_data;
+    QEventLoop m_eventLoop;
+};
+
+static QString qt_make_filter_for_openharmony(const QString &filter)
+{
+    QString _filter = filter;
+    QString description = "|";
+    QStringList parts;
+    if (_filter.contains("(") && _filter.contains(")")) {
+        parts = _filter.split("(");
+        _filter = parts.takeLast();
+        _filter.chop(1);
+        description.prepend(parts.join("(") + "("+ _filter + ")");
+    } else {
+        description.prepend(_filter);
+    }
+    parts = _filter.split(" ");
+    for (QString &part : parts) {
+        if (part.startsWith("*.")) {
+            /*
+             * 移除开头的 '*'
+             * 说明: 鸿蒙系统的文件选择器,只接受 '.png' 这种格式的后缀
+             */
+            part.remove(0, 1);
+        }
+        else if(!part.contains(".") ) {
+            part.prepend(".");
+        }
+    }
+    /*
+     * 连接描述和过滤器部分
+     *
+     * 说明: 鸿蒙系统的文件选择器
+     * 每项过滤后缀可以存在多个后缀名
+     * 则每一个后缀名之间用英文逗号进行分隔
+     */
+    return description + parts.join(",");
+}
+
+static QStringList qt_make_filter_list_for_openharmony(const QStringList &filters)
+{
+    QStringList allExtensions;
+    if (filters.count() == 1 && filters.first() == QFileDialogOptions::defaultNameFilterString()){
+        allExtensions << ".*";
+    } else {
+        for (auto _filter : filters) {
+            allExtensions << qt_make_filter_for_openharmony(_filter);
+        }
+    }
+    return allExtensions;
+}
+
+QOhNativeFileDialog::OHSelectMode QOhNativeFileDialog::qtMode2OhMode(QFileDialogOptions::FileMode mode)
+{
+    switch (mode) {
+    case QFileDialogOptions::AnyFile:
+    case QFileDialogOptions::ExistingFile:
+    case QFileDialogOptions::ExistingFiles:
+        break;
+    case QFileDialogOptions::Directory:
+        return OHSelectMode::FOLDER;
+    case QFileDialogOptions::DirectoryOnly:
+        return OHSelectMode::FOLDER;
+    default:
+        break;
+    }
+    return OHSelectMode::FILE;
+}
+
+int QOhNativeFileDialog::selectMaxSelectNumber(QFileDialogOptions::FileMode mode)
+{
+    switch (mode) {
+    case QFileDialogOptions::ExistingFiles:
+        return 500;
+    case QFileDialogOptions::ExistingFile:
+    default:
+        break;
+    }
+    return 1;
+}
+
+void QOhNativeFileDialog::setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::AcceptMode acceptMode, QFileDialogOptions::FileDialogOptions options)
+{
+    m_open = acceptMode == QFileDialogOptions::AcceptOpen;
+    m_mode = qtMode2OhMode(mode);
+    m_maxNumber = selectMaxSelectNumber(mode);
+}
+
+void QOhNativeFileDialog::setDirectory(const QUrl &directory)
+{
+    Q_UNUSED(directory)
+    Q_UNIMPLEMENTED();
+}
+
+void QOhNativeFileDialog::setNameFilters(const QStringList &f)
+{
+    m_nameFilters = f;
+}
+
+void QOhNativeFileDialog::selectNameFilter(const QString &filter)
+{
+    QString ohFilter = qt_make_filter_for_openharmony(filter);
+    Q_UNUSED(ohFilter)
+    Q_UNIMPLEMENTED();
+}
+
+void QOhNativeFileDialog::selectFile(const QString &fileName)
+{
+    m_saveFile = fileName;
+}
+
+void QOhNativeFileDialog::setUserSelectedNameFilter(int index)
+{
+    if (index >= 0 && index < m_nameFilters.count()) {
+        const QString filter = m_nameFilters.at(index);
+        if (!filter.isEmpty())
+            m_data.setSelectedNameFilter(filter);
+    }
+}
+
+void QOhNativeFileDialog::doExec(QWindow *parent)
+{
+    if (m_open)
+        open(parent);
+    else
+        save(parent);
+    m_eventLoop.exec();
+}
+
+std::pair<Napi::Value, Napi::Value> QOhNativeFileDialog::validContextAndWindow(QWindow *window) const
+{
+    QWindow *_window = window;
+    if (_window == nullptr)
+        _window = QGuiApplication::focusWindow();
+    if (_window == nullptr) {
+        _window = QGuiApplication::topLevelWindows().empty() ? nullptr : QGuiApplication::topLevelWindows().last();
+    }
+    if (_window == nullptr)
+        return {};
+
+    QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface();
+    QJsObject *nativeWindow = static_cast<QJsObject *>(platform->nativeResourceForWindow("nativeWindow", _window));
+    if (nativeWindow == nullptr)
+        return {};
+    QJsContext *context = qNativeWindowManager->context(_window);
+    return {context->object(), nativeWindow->object()};
+}
+
+std::shared_ptr<QJsObject> QOhNativeFileDialog::documentPicker(QWindow *parent) const
+{
+    static QJsModule picker("@ohos.file.picker");
+    Napi::Value documentPickerConstructor = picker.get("DocumentViewPicker");
+    auto args = validContextAndWindow(parent);
+    return std::make_shared<QJsObject>(documentPickerConstructor, std::initializer_list<napi_value>{args.first, args.second});
+}
+
+Napi::Value QOhNativeFileDialog::documentSelectOptions() const
+{
+    static QJsModule picker("@ohos.file.picker");
+    QStringList _filters = qt_make_filter_list_for_openharmony(m_nameFilters);
+    if (_filters.length() >= 100 || _filters.isEmpty()) {
+        _filters = QStringList() << ".*";
+    }
+    Napi::Value documentSelectOptionsConstructor = picker.get("DocumentSelectOptions");
+    QJsObject documentSelectOptions(documentSelectOptionsConstructor);
+    documentSelectOptions.set("fileSuffixFilters", QNapi::create(_filters));
+    documentSelectOptions.set("selectMode", m_mode);
+    documentSelectOptions.set("maxSelectNumber", m_maxNumber);
+    const QString path = m_data.directory().toLocalFile();
+    QString defaultPath = QString("%1/%2").arg(path, m_data.selectedFile());
+    if (!QFile::exists(defaultPath)) {
+        defaultPath = path;
+    }
+
+    defaultPath = QDir::cleanPath(defaultPath);
+    QString data = QtOh::uriFromPath(defaultPath);
+    if (!data.isEmpty()) {
+        documentSelectOptions.set("defaultFilePathUri", data);
+    }
+    return documentSelectOptions.object();
+}
+
+Napi::Value QOhNativeFileDialog::documentSaveOptions() const
+{
+    static QJsModule picker("@ohos.file.picker");
+    Napi::Value documentSaveOptionsConstructor = picker.get("DocumentSaveOptions");
+    QJsObject documentSaveOptions(documentSaveOptionsConstructor);
+    documentSaveOptions.set("newFileNames", QNapi::create(QStringList() << m_saveFile));
+    documentSaveOptions.set("fileSuffixChoices", QNapi::create(qt_make_filter_list_for_openharmony(m_nameFilters)));
+    const QString path = m_data.directory().toLocalFile();
+    QString defaultPath = QString("%1/%2").arg(path, m_saveFile);
+    if (!QFile::exists(defaultPath)) {
+        defaultPath = path;
+    }
+
+    defaultPath = QDir::cleanPath(defaultPath);
+    QString data = QtOh::uriFromPath(defaultPath);
+    if (!data.isEmpty()) {
+        documentSaveOptions.set("defaultFilePathUri", data);
+    }
+    return documentSaveOptions.object();
+}
+
+void QOhNativeFileDialog::open(QWindow *parent)
+{
+    auto callJsFunc = [this, parent]{
+        auto documentPicker = this->documentPicker(parent);
+        Napi::Promise result = documentPicker->call("select", documentSelectOptions()).As<Napi::Promise>();
+        QJsPromise promise(result);
+        promise.onThen([this](const Napi::CallbackInfo& info) {
+                   QEventLoopLocker locker(&m_eventLoop);
+                   if (info.Length() < 1) {
+                       return;
+                   }
+                   QStringList filePaths = QNapi::getFirst<QStringList>(info);
+                   if (!filePaths.isEmpty()) {
+                       m_data.setResult(filePaths);
+                       emit accepted();
+                   } else {
+                       emit rejected();
+                   }
+               }).onCatch([this](const Napi::CallbackInfo& info){
+                    Q_UNUSED(info)
+                    QEventLoopLocker locker(&m_eventLoop);
+                    emit rejected();
+                });
+    };
+
+    QtOh::runOnJsUIThreadNoWait(callJsFunc);
+}
+
+void QOhNativeFileDialog::save(QWindow *parent)
+{
+    auto callJsFunc = [this, parent]{
+        auto documentPicker = this->documentPicker(parent);
+        Napi::Promise result = documentPicker->call("save", documentSaveOptions()).As<Napi::Promise>();
+        QJsPromise promise(result);
+        promise.onThen([this, documentPicker](const Napi::CallbackInfo& info){
+                   QEventLoopLocker locker(&m_eventLoop);
+                   if (info.Length() < 1) {
+                       return;
+                   }
+                   int index = QNapi::get<int>(documentPicker->call("getSelectedIndex"));
+                   setUserSelectedNameFilter(index);
+                   QStringList filePaths = QNapi::getFirst<QStringList>(info);
+                   if (!filePaths.isEmpty()) {
+                       m_data.setResult(filePaths);
+                       emit accepted();
+                   } else {
+                       emit rejected();
+                   }
+               }).onCatch([this](const Napi::CallbackInfo& info){
+                    Q_UNUSED(info)
+                    QEventLoopLocker locker(&m_eventLoop);
+                    emit rejected();
+                });
+    };
+
+    QtOh::runOnJsUIThreadNoWait(callJsFunc);
+}
+
+class QOhPlatformFileDialogHelper: public QOhDialogHelperBase<QPlatformFileDialogHelper>
+{
+    Q_OBJECT
+public:
+    virtual bool defaultNameFilterDisables() const override { return true; }
+    virtual void setDirectory(const QUrl &directory) override;
+    virtual QUrl directory() const override;
+    virtual void selectFile(const QUrl &filename) override;
+    virtual QList<QUrl> selectedFiles() const override;
+    virtual QList<QUrl> selectedUris() const override;
+    virtual void setFilter() override;
+    virtual void selectNameFilter(const QString &filter) override;
+    virtual QString selectedNameFilter() const override;
+    virtual QOhNativeDialogBase *createNativeDialog() override;
+private:
+    inline QOhNativeFileDialog *nativeFileDialog() const
+    { return static_cast<QOhNativeFileDialog *>(nativeDialog()); }
+    OhFileData m_data;
+};
+
+void QOhPlatformFileDialogHelper::setDirectory(const QUrl &directory)
+{
+    m_data.setDirectory(directory);
+    if (hasNativeDialog())
+        nativeFileDialog()->updateDirectory();
+}
+
+QUrl QOhPlatformFileDialogHelper::directory() const
+{
+    return m_data.directory();
+}
+
+void QOhPlatformFileDialogHelper::selectFile(const QUrl &filename)
+{
+    QFileInfo fi(filename.toLocalFile());
+    QString saveFile = fi.fileName();
+    if (saveFile.contains("/")) {
+        int index = saveFile.lastIndexOf("/");
+        saveFile = saveFile.right(saveFile.length() - index - 1);
+    }
+
+    if (hasNativeDialog())
+        nativeFileDialog()->selectFile(saveFile);
+}
+
+QList<QUrl> QOhPlatformFileDialogHelper::selectedFiles() const
+{
+    auto files = m_data.selectedFiles();
+    QList<QUrl> result;
+    for (auto file: files) {
+        const QString &path = file.toString();
+        QString data = QtOh::pathFromUri(path);
+        if (!data.isEmpty()) {
+            result << QUrl::fromLocalFile(data);
+        }
+    }
+    return result;
+}
+
+QList<QUrl> QOhPlatformFileDialogHelper::selectedUris() const
+{
+    return m_data.selectedFiles();
+}
+
+void QOhPlatformFileDialogHelper::setFilter()
+{
+
+}
+
+void QOhPlatformFileDialogHelper::selectNameFilter(const QString &filter)
+{
+    m_data.setSelectedNameFilter(filter);
+    if (hasNativeDialog())
+        nativeFileDialog()->updateSelectedNameFilter();
+}
+
+QString QOhPlatformFileDialogHelper::selectedNameFilter() const
+{
+    return m_data.selectedNameFilter();
+}
+
+QOhNativeDialogBase *QOhPlatformFileDialogHelper::createNativeDialog()
+{
+    const QSharedPointer<QFileDialogOptions> &opts = options();
+    m_data.fromOptions(opts);
+    auto result = new QOhNativeFileDialog(m_data);
+    QObject::connect(result, &QOhNativeDialogBase::accepted, this, &QPlatformDialogHelper::accept);
+    QObject::connect(result, &QOhNativeDialogBase::rejected, this, &QPlatformDialogHelper::reject);
+    const QFileDialogOptions::FileMode mode = opts->fileMode();
+    result->setMode(mode, opts->acceptMode(), opts->options());
+    const QStringList nameFilters = opts->nameFilters();
+    if (!nameFilters.isEmpty())
+        result->setNameFilters(nameFilters);
+    result->updateDirectory();
+    result->updateSelectedNameFilter();
+    const QList<QUrl> initialSelection = opts->initiallySelectedFiles();
+    if (!initialSelection.empty()) {
+        const QUrl &url = initialSelection.constFirst();
+        if (url.isLocalFile()) {
+            QFileInfo info(url.toLocalFile());
+            if (!info.isDir())
+                result->selectFile(info.fileName());
+        } else {
+            result->selectFile(url.path());
+        }
+    }
+    if (mode != QFileDialogOptions::Directory && mode != QFileDialogOptions::DirectoryOnly) {
+        const QString initialNameFilter = opts->initiallySelectedNameFilter();
+        if (!initialNameFilter.isEmpty())
+            result->selectNameFilter(initialNameFilter);
+    }
+    return result;
+}
+
+template<class BaseClass>
+void QOhDialogHelperBase<BaseClass>::exec()
+{
+    if (QOhNativeDialogBase *nd = nativeDialog()) {
+        nd->exec(m_parent);
+        m_nativeDialog.clear();
+    }
+}
+
+template<class BaseClass>
+bool QOhDialogHelperBase<BaseClass>::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
+{
+    Q_UNUSED(windowFlags)
+    const bool modal = (windowModality != Qt::NonModal);
+    Q_UNUSED(modal);
+    m_parent = parent;
+    if (!ensureNativeDialog())
+        return false;
+    return true;
+}
+
+template<class BaseClass>
+void QOhDialogHelperBase<BaseClass>::hide()
+{
+//    if (m_nativeDialog)
+//        m_nativeDialog->hide();
+    m_parent = nullptr;
+}
+
+template <class BaseClass>
+QOhNativeDialogBase *QOhDialogHelperBase<BaseClass>::nativeDialog() const
+{
+    if (m_nativeDialog.isNull()) {
+        return nullptr;
+    }
+    return m_nativeDialog.data();
+}
+
+template <class BaseClass>
+QOhNativeDialogBase *QOhDialogHelperBase<BaseClass>::ensureNativeDialog()
+{
+    if (m_nativeDialog.isNull() || m_nativeDialog->executed())
+        m_nativeDialog = QOhNativeDialogBasePtr(createNativeDialog());
+    return m_nativeDialog.data();
+}
+
+QPlatformDialogHelper *QOhPlatformDialogHelpers::createHelper(QPlatformTheme::DialogType type)
+{
+    switch (type) {
+        //    case QPlatformTheme::MessageDialog:
+        //        return new QOhPlatformMessageDialogHelper;
+    case QPlatformTheme::FileDialog:
+        return new QOhPlatformFileDialogHelper();
+    default:
+        return nullptr;
+    }
+}
+
+QT_END_NAMESPACE
+#include "qohplatformdialoghelpers.moc"
diff --git a/src/plugins/platforms/openharmony/qohplatformdialoghelpers.h b/src/plugins/platforms/openharmony/qohplatformdialoghelpers.h
new file mode 100644
index 00000000000..f25641d12cf
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformdialoghelpers.h
@@ -0,0 +1,40 @@
+#ifndef QOHPLATFORMDIALOGHELPERS_H
+#define QOHPLATFORMDIALOGHELPERS_H
+
+#include <qpa/qplatformdialoghelper.h>
+#include <qpa/qplatformtheme.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOhNativeDialogBase;
+template <class BaseClass>
+class QOhDialogHelperBase : public BaseClass
+{
+    Q_DISABLE_COPY_MOVE(QOhDialogHelperBase)
+public:
+    using QOhNativeDialogBasePtr = QSharedPointer<QOhNativeDialogBase>;
+
+    void exec() override;
+    bool show(Qt::WindowFlags windowFlags,
+              Qt::WindowModality windowModality,
+              QWindow *parent) override;
+    void hide() override;
+
+protected:
+    QOhDialogHelperBase() = default;
+    QOhNativeDialogBase *nativeDialog() const;
+    inline bool hasNativeDialog() const { return static_cast<bool>(m_nativeDialog); } /* Qt6 only modify */
+
+private:
+    virtual QOhNativeDialogBase *createNativeDialog() = 0;
+    inline QOhNativeDialogBase *ensureNativeDialog();
+    QOhNativeDialogBasePtr m_nativeDialog;
+    QPointer<QWindow> m_parent;
+};
+
+namespace QOhPlatformDialogHelpers {
+    QPlatformDialogHelper *createHelper(QPlatformTheme::DialogType type);
+}
+
+QT_END_NAMESPACE
+#endif // QOHPLATFORMDIALOGHELPERS_H
diff --git a/src/plugins/platforms/openharmony/qohplatformforeignwindow.cpp b/src/plugins/platforms/openharmony/qohplatformforeignwindow.cpp
new file mode 100644
index 00000000000..27c6ba9d3ac
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformforeignwindow.cpp
@@ -0,0 +1,32 @@
+#include <QtCore/qvariant.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <qopenharmonydefines.h>
+#include "qohplatformforeignwindow.h"
+#include <qpa/qplatformscreen.h>
+#include "qohauxiliary.h"
+#include "qohwindownode.h"
+
+QT_BEGIN_NAMESPACE
+
+QOhPlatformForeignWindow::QOhPlatformForeignWindow(QWindow *window, WId nativeHandle)
+    : QOhPlatformWindow(window)
+    , m_nativeHandle(nativeHandle)
+{
+    auto r = QtOh::densityPixels(window->screen()->handle());
+    QRect rect = window->geometry();
+    QPlatformWindow::setGeometry(QRect(rect.x() * r, rect.y() * r, rect.width() * r, rect.height() * r));
+}
+
+void QOhPlatformForeignWindow::applicationStateChanged(Qt::ApplicationState state)
+{
+    QOhPlatformWindow::applicationStateChanged(state);
+}
+
+void QOhPlatformForeignWindow::initialize()
+{
+    QOhPlatformWindow::initialize();
+    createNativeWindowNode(m_nativeHandle);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohplatformforeignwindow.h b/src/plugins/platforms/openharmony/qohplatformforeignwindow.h
new file mode 100644
index 00000000000..c14f493b5d0
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformforeignwindow.h
@@ -0,0 +1,22 @@
+#ifndef QOHPLATFORMFOREIGNWINDOW_H
+#define QOHPLATFORMFOREIGNWINDOW_H
+
+#include "qohplatformwindow.h"
+#include "qohmain.h"
+
+QT_BEGIN_NAMESPACE
+
+class QOhPlatformForeignWindow : public QOhPlatformWindow
+{
+public:
+    explicit QOhPlatformForeignWindow(QWindow *window, WId nativeHandle);
+    void applicationStateChanged(Qt::ApplicationState state) override;
+    bool isForeignWindow() const override { return true; }
+    void initialize() override;
+private:
+    WId m_nativeHandle;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHPLATFORMFOREIGNWINDOW_H
diff --git a/src/plugins/platforms/openharmony/qohplatforminputcontext.cpp b/src/plugins/platforms/openharmony/qohplatforminputcontext.cpp
new file mode 100644
index 00000000000..e8300191793
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatforminputcontext.cpp
@@ -0,0 +1,578 @@
+#include "qohmain.h"
+#include "qohevent.h"
+#include "qohplatformscreen.h"
+#include "qohplatformwindow.h"
+#include "qohplatformintegration.h"
+#include "qohplatforminputcontext.h"
+#include "qohinputmethodproxy.h"
+#include "qohcontroller.h"
+#include "qohcursorinfo.h"
+#include "qohattachoptions.h"
+#include "qohtexteditorproxy.h"
+#include "qohinputmethod.h"
+#include "qohwindowcontext.h"
+#include "qohkeys.h"
+
+#include <QtCore/qopenharmonydefines.h>
+
+#include <QJsModule>
+#include <QPointer>
+#include <QTimer>
+#include <qevent.h>
+#include <qthread.h>
+#include <qwindow.h>
+#include <qmetaobject.h>
+#include <qinputmethod.h>
+#include <qsharedpointer.h>
+#include <qguiapplication.h>
+#include <private/qhighdpiscaling_p.h>
+
+#include <QTextCharFormat>
+#include <QTextBoundaryFinder>
+#include <qpa/qplatformcursor.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qwindowsysteminterface.h>
+
+QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(ohim, "qt.ohos.inputcontext")
+
+static QOhPlatformInputContext *m_openHarmonyInputContext = 0;
+
+// cursor position getter that also works with editors that have not been updated to the new API
+static inline int getAbsoluteCursorPosition(const QSharedPointer<QInputMethodQueryEvent> &query)
+{
+    QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
+    return absolutePos.isValid() ? absolutePos.toInt() : query->value(Qt::ImCursorPosition).toInt();
+}
+
+// position of the start of the current block
+static inline int getBlockPosition(const QSharedPointer<QInputMethodQueryEvent> &query)
+{
+    QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
+    return  absolutePos.isValid() ? absolutePos.toInt() - query->value(Qt::ImCursorPosition).toInt() : 0;
+}
+
+void QOhPlatformInputContext::cursorRectangleChanged()
+{
+    if (!m_controller->isAttached()) {
+        //qCWarning(ohim) << "Attempting to update cursor position when detached from controller.";
+        return;
+    }
+
+    auto focusedWindow = QGuiApplication::focusWindow();
+    if (focusedWindow == nullptr) {
+        qCDebug(ohim) << "Could not retrieve focused window. Updating cursor position isn't possible";
+        return;
+    }
+
+    while (focusedWindow->parent()) {
+        focusedWindow = focusedWindow->parent();
+    }
+
+    if (!focusedWindow) {
+        qCDebug(ohim) << "Could not retrieve focused window. Updating cursor position isn't possible";
+        return;
+    }
+
+    auto position = focusedWindow->position();
+    auto platformScreen = focusedWindow->screen()->handle();
+    position -= platformScreen->geometry().topLeft();
+    auto focusedWindowPosition = QHighDpi::toNativeLocalPosition(position, focusedWindow);
+    QRect cursorRectangle = QHighDpi::toNativeLocalPosition(QGuiApplication::inputMethod()->cursorRectangle().toRect(), focusedWindow);
+    if (cursorRectangle == m_lastCursorRectangle &&
+        m_lastFocusedWindowPosition == focusedWindowPosition) {
+        return;
+    }
+
+    m_lastCursorRectangle = cursorRectangle;
+    m_lastFocusedWindowPosition = focusedWindowPosition;
+    auto screenSpaceInputItemRectangle = QHighDpi::toNativeLocalPosition(QGuiApplication::inputMethod()->inputItemClipRectangle(), focusedWindow)
+                                                 .translated(m_lastFocusedWindowPosition).toRect();
+
+    auto screenSpaceCursorRectangle = m_lastCursorRectangle.translated(m_lastFocusedWindowPosition);
+
+    auto clampToRect = [](const QPoint &p, const QRect &rect)->QPoint {
+        int x = qBound(rect.left(), p.x(), rect.right());
+        int y = qBound(rect.top(), p.y(), rect.bottom());
+        return QPoint(x, y);
+    };
+
+    auto inputItemClampedCursorPos = clampToRect( {screenSpaceCursorRectangle.x(),
+                                                   screenSpaceCursorRectangle.y() },
+                                                 screenSpaceInputItemRectangle.isValid()
+                                                         ? screenSpaceInputItemRectangle
+                                                         : focusedWindow->geometry());
+
+    InputMethod::QOhCursorInfo cursorInfo = InputMethod::QOhCursorInfo(inputItemClampedCursorPos.x(),
+                                             inputItemClampedCursorPos.y(),
+                                             screenSpaceCursorRectangle.width(),
+                                             screenSpaceCursorRectangle.height());
+    if (m_controller->inputMethodProxy())
+        m_controller->inputMethodProxy()->notifyCursorUpdate(cursorInfo);
+}
+
+void QOhPlatformInputContext::updateCursor()
+{
+    QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+    if (query.isNull())
+        return;
+
+    bool imEnable = query->queries().testFlag(Qt::ImEnabled);
+    if (!imEnable)
+        return;
+
+/* FIXME 暂时注释这里和QInputMethod::cursorRectangleChanged响应的输入位置更新
+ * 因为会导致点击应用内界面,输入法位置乱跳
+ */
+#if 0
+    if (m_controller->isAttached()) {
+        cursorRectangleChanged();
+    }
+#endif
+}
+
+QOhPlatformInputContext::QOhPlatformInputContext()
+    : QPlatformInputContext()
+      , m_state(0)
+{
+    m_controller.reset(new InputMethod::QOhController());
+    auto *textEditorProxy = m_controller->textEditorProxy();
+    connect(textEditorProxy, &InputMethod::QOhTextEditorProxy::keyboardVisibleChanged, this, &QOhPlatformInputContext::emitInputPanelVisibleChanged);
+    connect(textEditorProxy, &InputMethod::QOhTextEditorProxy::updateCursor, this, &QOhPlatformInputContext::updateCursor);
+    connect(textEditorProxy, &InputMethod::QOhTextEditorProxy::commitText, this, &QOhPlatformInputContext::commitText);
+    connect(textEditorProxy, &InputMethod::QOhTextEditorProxy::preeditText, this, &QOhPlatformInputContext::preeditText);
+    connect(textEditorProxy, &InputMethod::QOhTextEditorProxy::enterKeyDown, this, &QOhPlatformInputContext::enterKeyDown);
+    connect(textEditorProxy, &InputMethod::QOhTextEditorProxy::deleteBackward, this, &QOhPlatformInputContext::deleteBackward);
+    connect(textEditorProxy, &InputMethod::QOhTextEditorProxy::deleteForward, this, &QOhPlatformInputContext::deleteForward);
+    connect(textEditorProxy, &InputMethod::QOhTextEditorProxy::moveCursor, this, &QOhPlatformInputContext::commitMoveCursor);
+    connect(textEditorProxy, &InputMethod::QOhTextEditorProxy::finishTextPreview, this, &QOhPlatformInputContext::finishTextPreview);
+
+    m_openHarmonyInputContext = this;
+
+    connect(qApp, &QGuiApplication::focusWindowChanged,
+            this, &QOhPlatformInputContext::focusWindowChanged);
+    qRegisterMetaType<QtOh::KeyEvent>("QtOh::KeyEvent");
+}
+
+QOhPlatformInputContext::~QOhPlatformInputContext()
+{
+    m_openHarmonyInputContext = Q_NULLPTR;
+}
+/*!
+ * \brief 检查输入上下文是否具有指定的功能
+ * \param capability 枚举值,用于指定功能类型
+ * \return 返回布尔值,如果具有指定功能,则返回 true,否则返回 false
+ */
+bool QOhPlatformInputContext::hasCapability(Capability capability) const
+{
+    switch (capability) {
+    /* Note 鸿蒙支持隐藏文本(密码)输入 */
+    case HiddenTextCapability:
+        return true;
+    default:break;
+    }
+    return true;
+}
+/*!
+ * \brief 重置输入法状态,将输入法状态恢复到默认状态
+ */
+void QOhPlatformInputContext::reset()
+{
+    finishTextPreview();
+    m_lastCursorRectangle = QRect();
+    m_lastFocusedWindowPosition = QPoint();
+}
+/*!
+ * \brief 提交当前输入法状态,将当前输入法状态应用到文本编辑器中
+ */
+void QOhPlatformInputContext::commit()
+{
+
+}
+/*!
+ * \brief 编辑器更新通知。由QInputMethod::update()调用
+ * 函数的作用是更新输入上下文的状态,以便与应用程序的输入方法通信
+ * 并响应输入法相关的查询,一般流程如下:
+ * 1.当输入法状态发生变化,或者焦点对象发生变化时
+ * QGuiApplication 会调用当前活动的 QPlatformInputContext 对象的 update 函数
+ *
+ * 2.在 update 函数内部,QPlatformInputContext 可以查询焦点对象的相关信息,
+ * 例如文本内容、光标位置等,然后将这些信息传递给输入法对象
+ *
+ * 3.输入法对象根据接收到的信息更新其状态,并相应地调整显示内容或行为
+ * 4.用户与输入法进行交互,输入文本或者调整输入法的设置
+ * 5.当用户输入完成或者输入法状态发生变化时,输入法对象可能会触发输入法事件,
+ * 通知 QPlatformInputContext 对象更新状态
+ */
+void QOhPlatformInputContext::update(Qt::InputMethodQueries queries)
+{
+    if (Qt::ImEnabled & queries)
+        updateInputEnabled();
+
+    if (Qt::ImCursorRectangle & queries)
+        cursorRectangleChanged();
+}
+
+/*!
+ * \brief 调用输入法的动作,以执行指定的操作,如向前移动光标、向后删除等
+ * \param act 动作类型
+ * \param cursorPosition 光标位置
+ */
+void QOhPlatformInputContext::invokeAction(QInputMethod::Action act, int cursorPosition)
+{
+#warning TODO Handle
+    Q_UNUSED(act);
+    Q_UNUSED(cursorPosition);
+}
+/*!
+ * \brief 过滤输入事件,以便输入上下文可以处理输入事件并相应地调整输入法状态
+ * \param event 输入事件
+ * \return 返回布尔值
+ */
+bool QOhPlatformInputContext::filterEvent(const QEvent *event)
+{
+    if ((event->type() == QEvent::KeyRelease) && m_controller->isAttached()) {
+        QKeyEvent *keyEvent = dynamic_cast<QKeyEvent *>(const_cast<QEvent *>(event));
+        auto key = keyEvent->key();
+        if ((key == Qt::Key_Up || key == Qt::Key_Down || key == Qt::Key_Left || key == Qt::Key_Right)) {
+            cursorRectangleChanged();
+        }
+    }
+    return QPlatformInputContext::filterEvent(event);
+}
+
+void QOhPlatformInputContext::setKeyboardRect(const QRect &rect)
+{
+    bool changed = m_keyboardRect != rect;
+    if (!changed)
+        return;
+    m_keyboardRect = rect;
+    emitKeyboardRectChanged();
+}
+/*!
+ * \brief 获取键盘区域的矩形范围,以便应用程序可以根据键盘的显示状态调整布局
+ * \return 返回键盘区域矩形大小
+ */
+QRectF QOhPlatformInputContext::keyboardRect() const
+{
+    return m_keyboardRect;
+}
+
+/*!
+ * \brief 返回布尔值,指示输入面板是否处于动画状态
+ * \return 返回布尔值
+ */
+bool QOhPlatformInputContext::isAnimating() const
+{
+    return false;
+}
+/*!
+ * \brief 显示输入面板(软键盘)
+ */
+void QOhPlatformInputContext::showInputPanel()
+{
+     if (!inputMethodAccepted())
+         return;
+
+    QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+    if (query.isNull())
+        return;
+
+    bool imEnable = query->queries().testFlag(Qt::ImEnabled);
+    if (!imEnable)
+        return;
+    if (!m_controller->isAttached()) {
+        m_controller->attach(InputMethod::QOhAttachOptions(true
+                                                   #if OHOS_SDK_VERSION > 14
+                                                           , m_requestKeyboardReason
+                                                   #endif
+                                                           ));
+
+    }
+    /*attach可能失败,失败时inputMethodProxy为nullptr*/
+    if (m_controller->isAttached()) {
+        m_controller->inputMethodProxy()->notifyConfigurationChanged(Qt::EnterKeyType(query->value(Qt::ImEnterKeyType).toInt()),
+                                                                     Qt::InputMethodHints(query->value(Qt::ImHints).toInt()));
+        if (!isInputPanelVisible()) {
+#if OHOS_SDK_VERSION > 14
+            m_controller->inputMethodProxy()->showTextInput(InputMethod::QOhAttachOptions(true, m_requestKeyboardReason));
+#endif
+            m_controller->inputMethodProxy()->showKeyboard();
+            cursorRectangleChanged();
+        }
+    }
+}
+/*!
+ * \brief 隐藏输入面板
+ */
+void QOhPlatformInputContext::hideInputPanel()
+{
+    if (m_controller->isAttached()) {
+        reset();
+        /* NOTE: 清空焦点对象,确保下次显示时能正确重新触发输入法 */
+        m_focusObject.clear();
+        if (m_controller->textEditorProxy()->isKeyboardVisible() && m_controller->inputMethodProxy())
+            m_controller->inputMethodProxy()->hideKeyboard();
+        m_controller->detach();
+        setRequestKeyboardReason(InputMethod::RequestKeyboardReason::NONE);
+    }    
+}
+/*!
+ * \brief 返回布尔值,指示输入面板的可见性状态
+ * \return 返回布尔值
+ */
+bool QOhPlatformInputContext::isInputPanelVisible() const
+{
+    bool visible = m_controller->textEditorProxy()->isKeyboardVisible();
+    return visible;
+}
+
+/*!
+ * \brief 设置获得焦点的对象
+ * \param object 对象指针
+ */
+void QOhPlatformInputContext::setFocusObject(QObject *object)
+{
+    Q_UNUSED(object)
+    if (m_isInPreviewText)
+        reset();
+    /* NOTE: 清空之前的焦点对象,确保每次焦点变化都能正确触发输入法 */
+    m_focusObject.clear();
+    QTimer::singleShot(0, this, [this]{ updateInputEnabled(); });
+}
+
+QOhPlatformInputContext *QOhPlatformInputContext::ohInputContext()
+{
+    return m_openHarmonyInputContext;
+}
+
+void QOhPlatformInputContext::clear()
+{
+    m_ignoreMouseEvents = false;
+}
+
+bool QOhPlatformInputContext::ignoreMouse() const
+{
+    return m_ignoreMouseEvents;
+}
+
+/*!
+ * \brief FIXME 临时方法发送EnterKey按键事件
+ */
+void QOhPlatformInputContext::enterKeyDown()
+{
+    LOGW("<--------------------- enterKeyDown ----------------->");
+    QObject *input = qGuiApp->focusObject();
+    if(!input)
+        return;
+    QKeyEvent *k1 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier, KEY_ENTER, KEY_ENTER, KEY_ENTER);
+    QGuiApplication::postEvent(input, k1);
+
+    QKeyEvent *k2 = new QKeyEvent(QEvent::KeyRelease, Qt::Key_Enter, Qt::NoModifier, KEY_ENTER, KEY_ENTER, KEY_ENTER);
+    QGuiApplication::postEvent(input, k2);
+}
+
+void QOhPlatformInputContext::deleteBackward()
+{
+    Qt::KeyboardModifiers mods = QOhKeys::keyboardModifiers();
+    QWindowSystemInterface::handleExtendedKeyEvent(QOhWindowContext::mouseGrabberWindow(),
+                                                   QEvent::KeyPress, Qt::Key_Backspace,
+                                                   mods, KEY_DEL, KEY_DEL, int(mods));
+
+    QWindowSystemInterface::handleExtendedKeyEvent(QOhWindowContext::mouseGrabberWindow(),
+                                                   QEvent::KeyRelease, Qt::Key_Backspace,
+                                                   mods, KEY_DEL, KEY_DEL, int(mods));
+    cursorRectangleChanged();
+
+}
+
+void QOhPlatformInputContext::deleteForward()
+{
+    Qt::KeyboardModifiers mods = QOhKeys::keyboardModifiers();
+    QWindowSystemInterface::handleExtendedKeyEvent(QOhWindowContext::mouseGrabberWindow(),
+                                                   QEvent::KeyPress, Qt::Key_Delete,
+                                                   mods, KEY_FORWARD_DEL, KEY_FORWARD_DEL, int(mods));
+
+    QWindowSystemInterface::handleExtendedKeyEvent(QOhWindowContext::mouseGrabberWindow(),
+                                                   QEvent::KeyRelease, Qt::Key_Delete,
+                                                   mods, KEY_FORWARD_DEL, KEY_FORWARD_DEL, int(mods));
+    cursorRectangleChanged();
+
+}
+
+void QOhPlatformInputContext::commitText(const QString &text)
+{
+    if (!m_controller->isAttached())
+        return;
+    QObject *input = checkFocusObject();
+
+    if (input && !text.isEmpty()) {
+
+        QInputMethodQueryEvent query(Qt::ImCursorPosition);
+        QCoreApplication::sendEvent(input, &query);
+        QVariant posValue = query.value(Qt::ImCursorPosition);
+        int cursorPosition = 0;
+        if (!posValue.isNull()) {
+            cursorPosition = posValue.toInt();
+        }
+
+        QInputMethodEvent event;
+        event.setCommitString(text);
+        QCoreApplication::sendEvent(input, &event);
+        cursorRectangleChanged();
+        if (m_controller->inputMethodProxy())
+            m_controller->inputMethodProxy()->notifySelectionChanged(text, cursorPosition, cursorPosition + text.length());
+        m_isInPreviewText = false;
+        m_previewText = QString();
+    }
+}
+
+void QOhPlatformInputContext::preeditText(const QString &text)
+{
+    QObject *input = checkFocusObject();
+    if (!input)
+        return;
+
+    m_isInPreviewText = true;
+    m_previewText = text;
+    QInputMethodQueryEvent query(Qt::ImAbsolutePosition);
+    QCoreApplication::sendEvent(input, &query);
+    int cursorPos = query.value(Qt::ImAbsolutePosition).toInt();
+    QTextCharFormat format;
+    format.setFontUnderline(true);
+    format.setUnderlineColor(Qt::gray);
+    QList<QInputMethodEvent::Attribute> attributes;
+    attributes.append(QInputMethodEvent::Attribute(
+                          QInputMethodEvent::TextFormat,
+                          0,
+                          text.length(),
+                          format
+                          ));
+    attributes.append(QInputMethodEvent::Attribute(
+                          QInputMethodEvent::Cursor,
+                          text.length(),
+                          1,
+                          QVariant()
+                          ));
+    QInputMethodEvent event(text, attributes);
+
+    QCoreApplication::sendEvent(input, &event);
+}
+
+void QOhPlatformInputContext::commitMoveCursor(int direction)
+{
+    QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+    if (query.isNull())
+        return;
+	/* Qt 6 only modify */
+    QScopedPointer<QInputMethodEvent> event;
+    const int absolutecursorPos = getAbsoluteCursorPosition(query);
+    /* 1-up 2-down
+     * 3-left 4-right
+     */
+    switch(direction)
+    {
+    case 1:
+        break;
+    case 2:
+        break;
+    case 3:
+        event.reset(new QInputMethodEvent({}, { { QInputMethodEvent::Selection, qMax(absolutecursorPos - 1, 0), 0 } }));
+        break;
+    case 4:
+        event.reset(new QInputMethodEvent ({}, { { QInputMethodEvent::Selection, absolutecursorPos + 1, 0 } }));
+        break;
+    default:break;
+    }
+
+    auto input = checkFocusObject();
+    if (input)
+        QGuiApplication::sendEvent(input, event.data());
+}
+
+void QOhPlatformInputContext::finishTextPreview()
+{
+    if (m_isInPreviewText) {
+        if (!m_focusObject.isNull() && !m_previewText.isEmpty()) {
+            QInputMethodEvent event;
+            event.setCommitString(m_previewText);
+            QCoreApplication::sendEvent(m_focusObject.data(), &event);
+            m_previewText = QString();
+        }
+        m_isInPreviewText = false;
+    }
+}
+
+void QOhPlatformInputContext::showInputPanelLater(Qt::ApplicationState state)
+{
+    if (state != Qt::ApplicationActive)
+        return;
+    disconnect(qGuiApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(showInputPanelLater(Qt::ApplicationState)));
+    showInputPanel();
+}
+
+void QOhPlatformInputContext::focusWindowChanged(QWindow *focusWindow)
+{
+    if (focusWindow == nullptr) {
+        if (m_controller->isAttached()) {
+            if (m_controller->textEditorProxy()->isKeyboardVisible() && m_controller->inputMethodProxy())
+                m_controller->inputMethodProxy()->hideKeyboard();
+            m_controller->detach();
+        }
+    }
+}
+
+QObject *QOhPlatformInputContext::checkFocusObject()
+{
+    QObject *input = qGuiApp->focusObject();
+    if (!input)
+        return nullptr;
+    if (m_focusObject.isNull() || m_focusObject.data() != input)
+        m_focusObject = input;
+    return input;
+}
+
+void QOhPlatformInputContext::sendInputMethodEvent(QInputMethodEvent *event)
+{
+    if (!qGuiApp)
+        return;
+
+    QObject *focusObject = qGuiApp->focusObject();
+    if (!focusObject)
+        return;
+
+    QCoreApplication::sendEvent(focusObject, event);
+}
+
+void QOhPlatformInputContext::setRequestKeyboardReason(InputMethod::RequestKeyboardReason reason)
+{
+    m_requestKeyboardReason = reason;
+}
+
+void QOhPlatformInputContext::updateInputEnabled()
+{
+    if (!QGuiApplication::focusObject())
+        return;
+
+    if (inputMethodAccepted() && !isInputPanelVisible()) {
+        showInputPanel();
+    }
+}
+
+QSharedPointer<QInputMethodQueryEvent> QOhPlatformInputContext::focusObjectInputMethodQuery(Qt::InputMethodQueries queries)
+{
+    if (!qGuiApp)
+        return {};
+
+    QObject *focusObject = qGuiApp->focusObject();
+    if (!focusObject)
+        return {};
+
+    QInputMethodQueryEvent *ret = new QInputMethodQueryEvent(queries);
+    QCoreApplication::sendEvent(focusObject, ret);
+    return QSharedPointer<QInputMethodQueryEvent>(ret);
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/plugins/platforms/openharmony/qohplatforminputcontext.h b/src/plugins/platforms/openharmony/qohplatforminputcontext.h
new file mode 100644
index 00000000000..38e39e757f7
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatforminputcontext.h
@@ -0,0 +1,96 @@
+#ifndef QOHPLATFORMINPUTCONTEXT_H
+#define QOHPLATFORMINPUTCONTEXT_H
+
+#include <QPointer>
+#include <cstdint>
+#include <napi/native_api.h>
+#include <qpa/qplatforminputcontext.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <multimodalinput/oh_input_manager.h>
+#include <ace/xcomponent/native_xcomponent_key_event.h>
+#include <ace/xcomponent/native_interface_xcomponent.h>
+#include "qohinputmethod.h"
+
+QT_BEGIN_NAMESPACE
+class QWindow;
+namespace InputMethod
+{
+class QOhController;
+};
+
+namespace QtOh {
+class KeyEvent;
+}
+
+class QOhPlatformInputContext: public QPlatformInputContext
+{
+    Q_OBJECT
+
+public:
+    QOhPlatformInputContext();
+    ~QOhPlatformInputContext() override;
+
+    /* 判断输入上下文是否有效 */
+    bool isValid() const override { return true; }
+    bool hasCapability(Capability capability) const override;
+
+    void reset() override;
+    void commit() override;
+    void update(Qt::InputMethodQueries queries) override;
+    void invokeAction(QInputMethod::Action act, int cursorPosition) override;
+
+    bool filterEvent(const QEvent *event) override;
+
+    void setKeyboardRect(const QRect &rect);
+    QRectF keyboardRect() const override;
+
+    bool isAnimating() const override;
+
+    void showInputPanel() override;
+    void hideInputPanel() override;
+    bool isInputPanelVisible() const override;
+
+    void setFocusObject(QObject *object) override;
+
+    void clear();
+    bool ignoreMouse() const;
+    static QOhPlatformInputContext *ohInputContext();
+
+    void setRequestKeyboardReason(InputMethod::RequestKeyboardReason reason = InputMethod::RequestKeyboardReason::NONE);
+
+    void updateInputEnabled();
+
+private Q_SLOTS:
+    void cursorRectangleChanged();
+    void updateCursor();
+    void enterKeyDown();
+    void deleteBackward();
+    void deleteForward();
+    void commitText(const QString &text);
+    void preeditText(const QString &text);
+    void commitMoveCursor(int direction);    
+    void finishTextPreview();
+    void showInputPanelLater(Qt::ApplicationState state);
+    void focusWindowChanged(QWindow *focusWindow);
+    QObject *checkFocusObject();
+private:    
+    void sendInputMethodEvent(QInputMethodEvent *event);    
+    QSharedPointer<QInputMethodQueryEvent> focusObjectInputMethodQuery(Qt::InputMethodQueries queries = Qt::ImQueryAll);
+
+private:    
+    int m_state; /* 辅助键状态 */
+    QPointer<QObject> m_focusObject;
+    bool m_ignoreMouseEvents = false;        
+    QScopedPointer<InputMethod::QOhController> m_controller;
+    bool m_isInPreviewText = false;
+    QString m_previewText;
+    /* 记录输入跟随位置 */
+    QRect m_lastCursorRectangle;
+    QPoint m_lastFocusedWindowPosition;
+    QRect m_keyboardRect;
+    InputMethod::RequestKeyboardReason m_requestKeyboardReason = InputMethod::RequestKeyboardReason::NONE;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHPLATFORMINPUTCONTEXT_H
diff --git a/src/plugins/platforms/openharmony/qohplatformintegration.cpp b/src/plugins/platforms/openharmony/qohplatformintegration.cpp
new file mode 100644
index 00000000000..88f5791adf9
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformintegration.cpp
@@ -0,0 +1,308 @@
+#include <QThread>
+#include <QMetaObject>
+#include <QOpenGLContext>
+#include <QGuiApplication>
+#include <QOffscreenSurface>
+#include <qohutility.h>
+#include <QtGui/private/qguiapplication_p.h>
+
+#include "qohdrag.h"
+#include "qoheventdispatcher.h"
+#include "qohplatformtheme.h"
+#include "qohdesktopwindow.h"
+#include "qabstracteventdispatcher.h"
+#include "qohplatformscreen.h"
+#include "qohplatformservices.h"
+#include "qohfileenginehandler.h"
+#include "qohplatformopenglcontext.h"
+#include "qohplatformclipboard.h"
+#include "qohplatformintegration.h"
+#include "qohplatforminputcontext.h"
+#include "qohplatformbackingstore.h"
+#include "qohplatformopenglwindow.h"
+#include <private/qohfontdatabase_p.h>
+#include "qohplatformforeignwindow.h"
+#include "qohplatformoffscreensurface.h"
+#include "qohplatformnativeinterface.h"
+#include "qohplatformabilityctrl.h"
+#ifndef QT_NO_ACCESSIBILITY
+#if defined(OHOS_SDK_VERSION) && (OHOS_SDK_VERSION > 13)
+#include "qohplatformaccessibility.h"
+#endif
+#endif
+
+#include <qpa/qplatformwindow.h>
+#include <QtGui/qpa/qplatformcursor.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qplatformoffscreensurface.h>
+#include <private/qeglpbuffer_p.h>
+#include <QtGui/qpa/qplatforminputcontextfactory_p.h>
+#include "qjsscreen.h"
+#include "qjsdisplay.h"
+#include "qohkeys.h"
+
+#if QT_CONFIG(vulkan)
+#include "qohplatformvulkaninstance.h"
+#endif
+
+#include "qohmain.h"
+#if OHOS_SDK_VERSION > 13
+#include "qohdisplaymanager.h"
+#endif
+
+#include "qjsaccessmanager.h"
+#include "qohnativewindowmanager.h"
+#include "qopenharmonydefines.h"
+
+QT_BEGIN_NAMESPACE
+
+QOhPlatformIntegration::QOhPlatformIntegration(const QStringList &paramList)
+    : m_harmonyFontDatabase(nullptr)    
+{
+    Q_UNUSED(paramList);
+
+    m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    if (m_eglDisplay == EGL_NO_DISPLAY) {
+        LOGE("Could not open egl display, error code: %{public}d", eglGetError());
+        return;
+    }
+
+    EGLint major, minor;
+    if (!eglInitialize(m_eglDisplay, &major, &minor)) {
+        m_eglDisplay = EGL_NO_DISPLAY;
+        LOGE("Could not initialize egl display, error code: %{public}d", eglGetError());
+    }
+
+    if (!eglBindAPI(EGL_OPENGL_ES_API)) {
+        LOGE("Could not bind GL_ES API, error code: %{public}d", eglGetError());
+        return;
+    }
+
+    m_harmonyFontDatabase.reset(new QOhFontDatabase);
+
+#if OHOS_SDK_VERSION > 13
+    auto displayMan = new QOhDisplayManager();
+    displayMan->init();
+    m_displayManager.reset(displayMan);
+    //m_displayManager->init();
+#else
+    m_display = new QJsDisplay();
+    m_display->initialize();
+    QJsScreen *s = m_display->defaultScreen();
+    m_primaryScreen.reset(new QOhPlatformScreen(s));
+    QWindowSystemInterface::handleScreenAdded(m_primaryScreen.data());
+#endif
+    QPlatformCursor::setCapability(QPlatformCursor::OverrideCursor);
+
+    m_mainThread = QThread::currentThread();
+
+#ifndef QT_NO_CLIPBOARD
+    m_platformClipboard.reset(new QOhPlatformClipboard);
+#endif
+#ifndef QT_NO_DRAGANDDROP
+    m_drag.reset(new QOhDrag);
+#endif
+    m_platformNativeInterface.reset(new QOhPlatformNativeInterface());
+    m_platformServices.reset(new QOhPlatformServices());
+    m_openHarmonyFileEngineHandler.reset(new QOhFileEngineHandler);
+#ifndef QT_NO_ACCESSIBILITY
+#if defined(OHOS_SDK_VERSION) && (OHOS_SDK_VERSION > 13)
+    m_accessibility.reset(new QOhPlatformAccessibility);
+#endif
+#endif
+}
+
+
+bool QOhPlatformIntegration::hasCapability(Capability cap) const
+{
+    switch (cap) {
+    // 目前没有接收系统的程序状态变化,applicationContext.on('applicationStateChange')不会触发
+    // Qt内部处理
+    case ApplicationState:
+    case SwitchableWidgetComposition:
+        return false;
+    default:
+        return true;
+    }
+}
+
+QPlatformBackingStore *QOhPlatformIntegration::createPlatformBackingStore(QWindow *window) const
+{
+    return new QOhPlatformBackingStore(window);
+}
+
+#ifndef QT_NO_OPENGL
+QPlatformOpenGLContext *QOhPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
+{
+    QSurfaceFormat format(context->format());
+    // EGLConfig *config = const_cast<EGLConfig *>(&m_eglConfig);
+    auto ctx = new QOhPlatformOpenGLContext(format, context->shareHandle(), m_eglDisplay, nullptr);
+    return ctx;
+}
+/* Qt6 only modify */
+# if QT_CONFIG(egl)
+QOpenGLContext *QOhPlatformIntegration::createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const
+{
+    return QEGLPlatformContext::createFrom<QOhPlatformOpenGLContext>(context, display, m_eglDisplay, shareContext);
+}
+#endif
+#endif
+
+QPlatformOffscreenSurface *QOhPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
+{    
+    QSurfaceFormat format(surface->requestedFormat());
+
+    return new QEGLPbuffer(m_eglDisplay, format, surface);
+}
+
+QPlatformAccessCtrl *QOhPlatformIntegration::accessCtrl() const
+{
+    return QJsAccessManager::instance();
+}
+
+QPlatformAbilityCtrl *QOhPlatformIntegration::abilityCtrl() const
+{
+    return QOhPlatformAbilityCtrl::instance();
+}
+
+QPlatformWindow *QOhPlatformIntegration::createPlatformWindow(QWindow *window) const
+{
+    if (window->type() == Qt::Desktop) {
+        return new QOhDesktopWindow(window);
+    }
+    return new QOhPlatformOpenGLWindow(window);
+}
+
+QPlatformWindow *QOhPlatformIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
+{
+    return new QOhPlatformForeignWindow(window, nativeHandle);
+}
+
+QAbstractEventDispatcher *QOhPlatformIntegration::createEventDispatcher() const
+{
+    return new QOhEventDispatcher(const_cast<QOhPlatformIntegration*>(this));
+}
+
+QOhPlatformIntegration::~QOhPlatformIntegration()
+{
+    if (m_eglDisplay != EGL_NO_DISPLAY)
+        eglTerminate(m_eglDisplay);
+    QOhPlatformInputContext *context = qobject_cast<QOhPlatformInputContext *>(m_platformInputContext.data());
+    if (context != nullptr)
+        context->clear();
+#if OHOS_SDK_VERSION > 13
+#else
+    delete m_display;
+#endif
+}
+
+void QOhPlatformIntegration::initialize()
+{
+    const QString icStr = QPlatformInputContextFactory::requested();
+    if (icStr.isNull()) {
+        QOhPlatformInputContext *context = new QOhPlatformInputContext;
+        m_platformInputContext.reset(context);
+    }
+    else
+        m_platformInputContext.reset(QPlatformInputContextFactory::create(icStr));
+}
+
+Qt::KeyboardModifiers QOhPlatformIntegration::queryKeyboardModifiers() const
+{
+    return QOhKeys::keyboardModifiers();
+}
+
+QPlatformInputContext *QOhPlatformIntegration::inputContext() const
+{
+    return m_platformInputContext.data();
+}
+
+QPlatformNativeInterface *QOhPlatformIntegration::nativeInterface() const
+{
+    return m_platformNativeInterface.data();
+}
+
+QPlatformServices *QOhPlatformIntegration::services() const
+{
+    return m_platformServices.data();
+}
+
+#ifndef QT_NO_ACCESSIBILITY
+#if defined(OHOS_SDK_VERSION) && (OHOS_SDK_VERSION > 13)
+QPlatformAccessibility *QOhPlatformIntegration::accessibility() const
+{
+    return m_accessibility.data();
+}
+#endif
+#endif
+
+QVariant QOhPlatformIntegration::styleHint(StyleHint hint) const
+{
+    switch (hint) {
+    case PasswordMaskDelay:
+        return m_showPasswordEnabled ? 1500 : 0;
+    case ShowIsMaximized:
+        return false;
+    default:
+        return QPlatformIntegration::styleHint(hint);
+    }
+}
+
+Qt::WindowState QOhPlatformIntegration::defaultWindowState(Qt::WindowFlags flags) const
+{
+    // Don't maximize dialogs on OpenHarmony
+    if (flags & Qt::Dialog & ~Qt::Window) {
+        return Qt::WindowNoState;
+    }
+    if (flags & Qt::Dialog & ~Qt::Window) {
+        return Qt::WindowNoState;
+    }
+    if ((flags & Qt::WindowType_Mask) == Qt::Window) {
+        if ((QtOh::Utility::type() != QtOh::Utility::PC) && !QtOh::isFreeWindowEnable())
+            return Qt::WindowFullScreen;
+    }
+    return QPlatformIntegration::defaultWindowState(flags);
+}
+/* NOTE 改主题名称和加载的样式插件相关联 */
+static const QLatin1String openharmonyThemeName("openharmony");
+QStringList QOhPlatformIntegration::themeNames() const
+{
+    return QStringList{ "harmonyos", QString(openharmonyThemeName) };
+}
+
+QPlatformTheme *QOhPlatformIntegration::createPlatformTheme(const QString &name) const
+{
+    Q_UNUSED(name);
+    return new QOhPlatformTheme;
+}
+
+QPlatformFontDatabase *QOhPlatformIntegration::fontDatabase() const
+{
+    return m_harmonyFontDatabase.data();
+}
+
+#ifndef QT_NO_CLIPBOARD
+QPlatformClipboard *QOhPlatformIntegration::clipboard() const
+{
+    return m_platformClipboard.data();
+}
+#endif
+
+#ifndef QT_NO_DRAGANDDROP
+QPlatformDrag *QOhPlatformIntegration::drag() const
+{
+    return m_drag.data();
+}
+#endif
+
+#if QT_CONFIG(vulkan)
+
+QPlatformVulkanInstance *QOhPlatformIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
+{
+    return new QOhPlatformVulkanInstance(instance);
+}
+
+#endif // QT_CONFIG(vulkan)
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/openharmony/qohplatformintegration.h b/src/plugins/platforms/openharmony/qohplatformintegration.h
new file mode 100644
index 00000000000..c7f25667ca8
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformintegration.h
@@ -0,0 +1,127 @@
+#ifndef QOHPLATFORMINTERATION_H
+#define QOHPLATFORMINTERATION_H
+
+#include <EGL/egl.h>
+#include <qpointingdevice.h> /* Qt 6 only modify */
+#include <qscopedpointer.h>
+#include <QtGui/qtguiglobal.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformmenu.h>
+#include <qpa/qplatformservices.h>
+#include <qpa/qplatformopenglcontext.h> /* Qt 6 only modify */
+
+
+QT_BEGIN_NAMESPACE
+
+class QOhDrag;
+class QJsDisplay;
+class QDesktopWidget;
+class QPlatformAccessCtrl;
+class QPlatformColorModeCtrl;
+class QPlatformAccessibility;
+class QOhPlatformScreen;
+class QOhFileEngineHandler;
+class QOhFontDatabase;
+class QOhPlatformInputContext;
+#ifndef QT_NO_ACCESSIBILITY
+#if defined(OHOS_SDK_VERSION) && (OHOS_SDK_VERSION > 13)
+class QOhPlatformAccessibility;
+class QOhDisplayManager;
+#endif
+#endif
+
+class QOhPlatformIntegration : public QPlatformIntegration
+/* Qt 6 only modify */
+# if QT_CONFIG(egl)
+    , public QNativeInterface::Private::QEGLIntegration
+# endif
+{
+    friend class QOhPlatformScreen;
+
+public:
+    QOhPlatformIntegration(const QStringList &paramList);
+    ~QOhPlatformIntegration() override;
+
+    void initialize() override;
+    Qt::KeyboardModifiers queryKeyboardModifiers() const override;
+    bool hasCapability(QPlatformIntegration::Capability cap) const override;
+    QPlatformWindow *createPlatformWindow(QWindow *window) const override;
+    QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override;
+    QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
+#ifndef QT_NO_OPENGL
+    QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
+	/* Qt 6 only modify */
+# if QT_CONFIG(egl)
+    QOpenGLContext *createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const override;
+#endif
+#endif
+    QAbstractEventDispatcher *createEventDispatcher() const override;
+    QOhPlatformScreen *screen() { return m_primaryScreen.data(); }
+    QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override;
+
+    bool isVirtualDesktop() { return true; }
+    QPlatformAccessCtrl *accessCtrl() const override;
+    QPlatformAbilityCtrl *abilityCtrl() const override;    
+    QPlatformFontDatabase *fontDatabase() const override;
+
+#ifndef QT_NO_CLIPBOARD
+    QPlatformClipboard *clipboard() const override;
+#endif
+
+#ifndef QT_NO_DRAGANDDROP
+    virtual QPlatformDrag *drag() const override;
+#endif
+    QPlatformInputContext *inputContext() const override;
+    QPlatformNativeInterface *nativeInterface() const override;
+    QPlatformServices *services() const override;
+
+#ifndef QT_NO_ACCESSIBILITY
+#if defined(OHOS_SDK_VERSION) && (OHOS_SDK_VERSION > 13)
+    virtual QPlatformAccessibility *accessibility() const override;
+#endif
+#endif
+
+    QVariant styleHint(StyleHint hint) const override;
+    Qt::WindowState defaultWindowState(Qt::WindowFlags flags) const override;
+
+    QStringList themeNames() const override;
+    QPlatformTheme *createPlatformTheme(const QString &name) const override;
+
+#if QT_CONFIG(vulkan)
+    QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override;
+#endif // QT_CONFIG(vulkan)
+private:
+    EGLDisplay m_eglDisplay;
+    EGLConfig m_eglConfig;
+    QScopedPointer<QOhPlatformScreen> m_primaryScreen;
+
+    QThread *m_mainThread;
+
+    static inline bool m_showPasswordEnabled = false;
+    QScopedPointer<QOhFontDatabase> m_harmonyFontDatabase;
+    QScopedPointer<QPlatformInputContext> m_platformInputContext;
+
+#ifndef QT_NO_CLIPBOARD
+    QScopedPointer<QPlatformClipboard> m_platformClipboard;
+#endif
+#ifndef QT_NO_DRAGANDDROP
+    QScopedPointer<QOhDrag> m_drag;
+#endif    
+    QScopedPointer<QPlatformNativeInterface> m_platformNativeInterface;
+    QScopedPointer<QPlatformServices> m_platformServices;
+    QScopedPointer<QOhFileEngineHandler> m_openHarmonyFileEngineHandler;
+#ifndef QT_NO_ACCESSIBILITY
+#if defined(OHOS_SDK_VERSION) && (OHOS_SDK_VERSION > 13)
+    QScopedPointer<QOhPlatformAccessibility> m_accessibility;
+#endif
+#endif
+#if OHOS_SDK_VERSION > 13
+    QScopedPointer<QOhDisplayManager> m_displayManager;
+#else
+    QJsDisplay *m_display;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif //QOHPLATFORMINTERATION_H
diff --git a/src/plugins/platforms/openharmony/qohplatformmenu.cpp b/src/plugins/platforms/openharmony/qohplatformmenu.cpp
new file mode 100644
index 00000000000..ef882db09a0
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformmenu.cpp
@@ -0,0 +1,100 @@
+#include "qohplatformmenu.h"
+#include <QDebug>
+
+QOhPlatformMenuItem::QOhPlatformMenuItem()
+    :QPlatformMenuItem(),
+      m_menu(nullptr),
+      m_isVisible(true)
+{
+
+}
+
+QOhPlatformMenu::QOhPlatformMenu()
+    :QPlatformMenu(),
+      m_isVisible(true)
+{
+
+}
+
+void QOhPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
+{
+    QOhPlatformMenuItem *ohMenuItem = qobject_cast<QOhPlatformMenuItem *>(menuItem);
+    if(!ohMenuItem){
+        return;
+    }
+
+    if(m_childs.isEmpty()){
+        m_childs.append(ohMenuItem);
+        return;
+    }
+
+    for(int i = 0; i < m_childs.size(); ++i){
+        if(m_childs[i] == before){
+            m_childs.insert(i, ohMenuItem);
+            return;
+        }
+    }
+
+    m_childs.insert(m_childs.size(), ohMenuItem);
+    Q_EMIT menuUpdated();
+}
+
+void QOhPlatformMenu::removeMenuItem(QPlatformMenuItem *menuItem)
+{
+    QOhPlatformMenuItem *item = qobject_cast<QOhPlatformMenuItem *>(menuItem);
+    if(item)
+        m_childs.removeAll(item);
+    Q_EMIT menuUpdated();
+}
+
+void QOhPlatformMenu::syncMenuItem(QPlatformMenuItem *menuItem)
+{
+    Q_UNUSED(menuItem)
+    Q_EMIT menuUpdated();
+}
+
+QPlatformMenuItem *QOhPlatformMenu::menuItemAt(int position) const
+{
+    if (position >= 0 && m_childs.size() > position) {
+        return m_childs[position];
+    }
+
+    return nullptr;
+}
+
+QPlatformMenuItem *QOhPlatformMenu::menuItemForTag(quintptr tag) const
+{
+    if(m_childs.isEmpty()){
+        return nullptr;
+    }
+
+    for(int i = 0; i < m_childs.size(); ++i){
+        if(m_childs[i]->tag() == tag){
+            return m_childs[i];
+        }
+
+        if(m_childs[i]->menu()){
+            if(QPlatformMenuItem *ret = m_childs[i]->menu()->menuItemForTag(tag)){
+                return ret;
+            }
+        }
+    }
+
+    return nullptr;
+}
+
+QPlatformMenuItem *QOhPlatformMenu::createMenuItem() const
+{
+    return new QOhPlatformMenuItem();
+}
+
+QPlatformMenu *QOhPlatformMenu::createSubMenu() const
+{
+    return new QOhPlatformMenu();
+}
+
+QList<QOhPlatformMenuItem *> QOhPlatformMenu::childItems()
+{
+    return m_childs;
+}
+
diff --git a/src/plugins/platforms/openharmony/qohplatformmenu.h b/src/plugins/platforms/openharmony/qohplatformmenu.h
new file mode 100644
index 00000000000..56ccb8234f5
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformmenu.h
@@ -0,0 +1,74 @@
+#ifndef QOHPLATFORMMENU_H
+#define QOHPLATFORMMENU_H
+
+#include <qpa/qplatformmenu.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOhPlatformMenuItem: public QPlatformMenuItem{
+    Q_OBJECT
+public:
+    QOhPlatformMenuItem();
+
+    void setText(const QString &text) override { m_text = text; }
+    void setIcon(const QIcon &icon) override { Q_UNUSED(icon)}
+    void setMenu(QPlatformMenu *menu) override { m_menu = menu; }
+    void setVisible(bool isVisible) override { m_isVisible = isVisible; }
+    void setIsSeparator(bool isSeparator) override { m_isSeparator = isSeparator; }
+    void setFont(const QFont &font) override { Q_UNUSED(font)}
+    void setRole(MenuRole role) override { Q_UNUSED(role)}
+    void setCheckable(bool checkable) override { Q_UNUSED(checkable)}
+    void setChecked(bool isChecked) override { Q_UNUSED(isChecked)}
+#ifndef QT_NO_SHORTCUT
+    void setShortcut(const QKeySequence& shortcut) override { Q_UNUSED(shortcut)}
+#endif
+    void setEnabled(bool enabled) override { Q_UNUSED(enabled)}
+    void setIconSize(int size) override { Q_UNUSED(size)}
+
+    QPlatformMenu *menu() { return m_menu; }
+    QString text() { return m_text; }
+    bool isVisible() { return m_isVisible; }
+    bool isSeparator() { return m_isSeparator; }
+
+private:
+    QString m_text;
+    QPlatformMenu *m_menu;
+    bool m_isSeparator;
+    bool m_isVisible;
+};
+
+class QOhPlatformMenu: public QPlatformMenu{
+    Q_OBJECT
+
+public:
+    QOhPlatformMenu();
+
+    void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) override;
+    void removeMenuItem(QPlatformMenuItem *menuItem) override;
+    void syncMenuItem(QPlatformMenuItem *menuItem) override;
+    void syncSeparatorsCollapsible(bool enable) override { Q_UNUSED(enable) };
+
+    void setText(const QString &text) override { m_text = text; }
+    void setIcon(const QIcon &icon) override { Q_UNUSED(icon); }
+    void setEnabled(bool enabled) override { Q_UNUSED(enabled); }
+    void setVisible(bool visible) override { m_isVisible = visible; };
+
+    QPlatformMenuItem *menuItemAt(int position) const override;
+    QPlatformMenuItem *menuItemForTag(quintptr tag) const override;
+    QPlatformMenuItem *createMenuItem() const override;
+    QPlatformMenu *createSubMenu() const override;
+
+    QList<QOhPlatformMenuItem *> childItems();
+
+Q_SIGNALS:
+    void menuUpdated();
+
+private:
+    QList<QOhPlatformMenuItem *> m_childs;
+    QString m_text;
+    bool m_isVisible;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHPLATFORMMENU_H
diff --git a/src/plugins/platforms/openharmony/qohplatformnativeinterface.cpp b/src/plugins/platforms/openharmony/qohplatformnativeinterface.cpp
new file mode 100644
index 00000000000..13a1603e517
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformnativeinterface.cpp
@@ -0,0 +1,144 @@
+#include <QtCore/qhash.h>
+
+#include "qohmain.h"
+#include "qjsability.h"
+#include "qjscontext.h"
+#include "qohwindownode.h"
+#include "qjswindowstage.h"
+#include "qohnativewindow.h"
+#include "qohplatformwindow.h"
+#include "qohnativewindowmanager.h"
+#include "qohplatformnativeinterface.h"
+
+QT_BEGIN_NAMESPACE
+
+enum ResourceType {
+    InvalidType,
+    UIAbility,
+    NativeNode,
+    UIAbilityContext,
+    NativeXComponentType,
+    NativeJsWindowType,
+    NativeWindowStageType,
+    NativeSettings
+#if QT_CONFIG(vulkan)
+    , NativeVkSurface
+#endif
+};
+
+static ResourceType resourceType(const QByteArray &key)
+{
+    static QHash<QByteArray, ResourceType> resources = {
+        {"nativeXComponent", NativeXComponentType},
+        {"nativeWindow", NativeJsWindowType},
+        {"UIAbility", UIAbility},
+        {"NativeNode", NativeNode},
+        {"UIAbilityContext", UIAbilityContext},
+        {"nativeWindowStage", NativeWindowStageType},
+        {"nativeSettings", NativeSettings},
+#if QT_CONFIG(vulkan)
+        {"vkSurface", NativeVkSurface},
+#endif
+    };
+    if (resources.contains(key))
+        return resources.value(key);
+    return InvalidType;
+}
+
+void *QOhPlatformNativeInterface::nativeResourceForIntegration(const QByteArray &resource)
+{
+    ResourceType type = resourceType(resource);
+    switch (type) {
+    case UIAbility:
+    {
+        auto ability = QOhNativeWindowManager::instance()->defaultAbility();
+        return ability ? std::bit_cast<void*>(ability) : nullptr;
+    }
+    case UIAbilityContext:
+    {
+        auto ability = QOhNativeWindowManager::instance()->defaultAbility();
+        return ability ? std::bit_cast<void*>(ability->context()) : nullptr;
+    }
+    case NativeSettings:
+    {
+        return std::bit_cast<void*>(QJsSettings::instance());
+    }
+    default:
+        break;
+    }
+    return nullptr;
+}
+
+void *QOhPlatformNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
+{
+    ResourceType type = resourceType(resource);
+    void *result = nullptr;
+    QOhWindowNode *node = QOhWindowNode::fromId(window->winId());
+    switch (type) {
+    case NativeXComponentType:
+    {
+        if (node != nullptr)
+            result = node->component();
+    }
+    break;
+    case NativeNode:
+    {
+        if (nullptr != node)
+            result = node;
+    }
+    break;
+    case NativeJsWindowType:
+    {
+        if (node != nullptr) {
+            QJsObject *obj = node->ownerWindow();
+            result = obj;
+        }
+    }
+    break;
+    case NativeWindowStageType:
+    {
+        if (node != nullptr) {
+            QOhNativeWindow *window = node->ownerWindow();
+            if (window != nullptr) {
+                QJsAbility *ability = window->ability();
+                if (ability != nullptr) {
+                    QJsContext *context = ability->context();
+                    if (context != nullptr) {
+                        QJsObject *obj = context->windowStage();
+                        result = obj;
+                    }
+                }
+            }
+        }
+        break;
+    }
+#if QT_CONFIG(vulkan)
+    case NativeVkSurface:
+    {
+        if (node != nullptr) {
+            result = static_cast<void*>(node->vkSurface());
+        }
+    }
+#endif
+    break;
+    default:
+        break;
+    }
+    return result;
+}
+
+QPlatformNativeInterface::NativeResourceForIntegrationFunction QOhPlatformNativeInterface::nativeResourceFunctionForIntegration(const QByteArray &resource)
+{
+    if (!resource.compare("isFreeWindowEnable")) {
+        return []{
+            static bool ret = false;
+            ret = QtOh::isFreeWindowEnable();
+            return std::bit_cast<void*>(&ret);
+        };
+    }
+
+    return nullptr;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/openharmony/qohplatformnativeinterface.h b/src/plugins/platforms/openharmony/qohplatformnativeinterface.h
new file mode 100644
index 00000000000..f7e9cb8c2b9
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformnativeinterface.h
@@ -0,0 +1,19 @@
+#ifndef QOHPLATFORMNATIVEINTERFACE_H
+#define QOHPLATFORMNATIVEINTERFACE_H
+
+#include <qpa/qplatformnativeinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOhPlatformNativeInterface: public QPlatformNativeInterface
+{
+    Q_OBJECT
+public:
+    void *nativeResourceForIntegration(const QByteArray &resource) override;
+    void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) override;
+    NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHPLATFORMNATIVEINTERFACE_H
diff --git a/src/plugins/platforms/openharmony/qohplatformoffscreensurface.cpp b/src/plugins/platforms/openharmony/qohplatformoffscreensurface.cpp
new file mode 100644
index 00000000000..df328c56926
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformoffscreensurface.cpp
@@ -0,0 +1,30 @@
+#include "qohplatformoffscreensurface.h"
+
+#include <QtGui/QOffscreenSurface>
+#include <private/qeglconvenience_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QOhPlatformOffscreenSurface::QOhPlatformOffscreenSurface(EGLNativeWindowType surfaceTexture, EGLDisplay display,
+                                                         const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface)
+    : QPlatformOffscreenSurface(offscreenSurface)
+    , m_format(format)
+    , m_display(display)
+    , m_surface(EGL_NO_SURFACE)
+{
+    EGLConfig config = q_configFromGLFormat(m_display, m_format, false);
+    if (config) {
+        const EGLint attributes[] = {
+            EGL_NONE
+        };
+        m_surface = eglCreateWindowSurface(m_display, config, surfaceTexture, attributes);
+    }
+}
+
+QOhPlatformOffscreenSurface::~QOhPlatformOffscreenSurface()
+{
+    eglDestroySurface(m_display, m_surface);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/openharmony/qohplatformoffscreensurface.h b/src/plugins/platforms/openharmony/qohplatformoffscreensurface.h
new file mode 100644
index 00000000000..749c1ec14e4
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformoffscreensurface.h
@@ -0,0 +1,28 @@
+#ifndef QOPENHARMONYPLATFORMOFFSCREENSURFACETEXTURE_H
+#define QOPENHARMONYPLATFORMOFFSCREENSURFACETEXTURE_H
+
+#include <qpa/qplatformoffscreensurface.h>
+#include <private/qeglplatformcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+class QOffscreenSurface;
+class QOhPlatformOffscreenSurface : public QPlatformOffscreenSurface
+{
+public:
+    QOhPlatformOffscreenSurface(EGLNativeWindowType surfaceTexture, EGLDisplay display, const QSurfaceFormat &format,
+                                            QOffscreenSurface *offscreenSurface);
+    ~QOhPlatformOffscreenSurface();
+
+    QSurfaceFormat format() const override { return m_format; }
+    bool isValid() const override { return m_surface != EGL_NO_SURFACE; }
+
+    EGLSurface surface() const { return m_surface; }
+private:
+    QSurfaceFormat m_format;
+    EGLDisplay m_display;
+    EGLSurface m_surface;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOPENHARMONYPLATFORMOFFSCREENSURFACETEXTURE_H
diff --git a/src/plugins/platforms/openharmony/qohplatformopenglcontext.cpp b/src/plugins/platforms/openharmony/qohplatformopenglcontext.cpp
new file mode 100644
index 00000000000..a749f2ac61d
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformopenglcontext.cpp
@@ -0,0 +1,32 @@
+#include "qohplatformopenglcontext.h"
+#include "qohplatformopenglwindow.h"
+#include <QDebug>
+#include <QSurface>
+#include <QtGui/QOffscreenSurface>
+#include <QtGui/private/qopenglcontext_p.h>
+#include <private/qeglpbuffer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QOhPlatformOpenGLContext::QOhPlatformOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLConfig *config)
+    :QEGLPlatformContext(format, share, display, config, Flags())
+{
+}
+
+EGLSurface QOhPlatformOpenGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
+{
+    if (surface->surface()->surfaceClass() == QSurface::Window) {
+        if (auto *w = dynamic_cast<QOhPlatformOpenGLWindow *>(surface)) {
+            EGLSurface surface = w->eglSurface(eglDisplay(), eglConfig());
+            return surface;
+        }
+        return nullptr;
+    } else {
+        if (auto *platformOffscreenSurface = dynamic_cast<QPlatformOffscreenSurface *>(surface))
+            return platformOffscreenSurface->surface();
+        else
+            return static_cast<QEGLPbuffer *>(surface)->pbuffer();
+    }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohplatformopenglcontext.h b/src/plugins/platforms/openharmony/qohplatformopenglcontext.h
new file mode 100644
index 00000000000..f551aef2914
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformopenglcontext.h
@@ -0,0 +1,20 @@
+#ifndef QOPENHARMONYPLATFORMOPENGLCONTEXT_H
+#define QOPENHARMONYPLATFORMOPENGLCONTEXT_H
+
+#include <private/qeglplatformcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOhPlatformOpenGLContext : public QEGLPlatformContext
+{
+public:
+    using QEGLPlatformContext::QEGLPlatformContext; /* Qt 6 only modify */
+    QOhPlatformOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLConfig *config);
+private:
+    EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override;
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QOPENHARMONYPLATFORMOPENGLCONTEXT_H
diff --git a/src/plugins/platforms/openharmony/qohplatformopenglwindow.cpp b/src/plugins/platforms/openharmony/qohplatformopenglwindow.cpp
new file mode 100644
index 00000000000..cc4926d549e
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformopenglwindow.cpp
@@ -0,0 +1,920 @@
+#include "qohplatformopenglwindow.h"
+#include "qohxcomponent.h"
+#include "qohnativewindow.h"
+#include "qohplatformscreen.h"
+#include "qohnativewindowmanager.h"
+#include "qohplatformbackingstore.h"
+
+#include "qohmain.h"
+#include "qohutility.h"
+#include "qjsability.h"
+#include "qjscontext.h"
+#include "qohwindowcontext.h"
+#include "qohwindownode.h"
+#include "qohplatformcursor.h"
+#include "qohsystemtrayicon.h"
+#include "qohdisplaymanager.h"
+#include "qohplatforminputcontext.h"
+
+#include <QDebug>
+#include <QTimer>
+#include <QColor>
+#include <QPalette>
+#include <QPainter>
+#include <QStaticText>
+#include <QSurfaceFormat>
+#include <QGuiApplication>
+#include <qpa/qplatformtheme.h>
+#include <qpa/qplatformscreen.h>
+#include <qpa/qplatformwindow_p.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/private/qwindow_p.h>
+#include <QtGui/private/qpainter_p.h>
+#include <private/qguiapplication_p.h>
+#include <private/qeglconvenience_p.h> /* Qt6 only modify */
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qwindowsysteminterface_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
+#if OHOS_SDK_VERSION > 13
+#include "qohaccessibilityprovider.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+enum {
+    defaultWindowWidth = 800,
+    defaultWindowHeight = 600
+};
+
+QOhNativeWindow *QOhPlatformOpenGLWindow::m_mouseGrab = nullptr;
+
+QOhPlatformOpenGLWindow::QOhPlatformOpenGLWindow(QWindow *window)
+    :QOhPlatformWindow(window)
+    , m_nativeWindow(nullptr)
+{
+    QRect rect = window->geometry();
+    m_rect = QHighDpi::toNativeLocalPosition(rect, window);
+    const auto *wp = qt_window_private(const_cast<QWindow*>(window));
+    auto *platformScreen = QOhDisplayManager::startScreen();
+    auto nativeTopLeft = platformScreen->geometry().topLeft();
+    if (window->isTopLevel() && wp->positionAutomatic && window->type() != Qt::Popup) {
+        m_rect = m_rect.translated(nativeTopLeft);
+    }
+    // 根据坐标查找屏幕,如果没有查到,使用startScreen。解决只有一个屏幕,主屏左上角坐标不为(0,0)的情况
+    if (window->isTopLevel()) {
+        auto targetPlatformScreen = QOhDisplayManager::instance()->screenAt(m_rect.center());
+        if (targetPlatformScreen == nullptr) {
+            m_rect = m_rect.translated(nativeTopLeft);
+        }
+    }
+    static bool firstMainWindow = true;
+    if (firstMainWindow) {
+        firstMainWindow = false;
+        /* FIXME wanghao 全局光标参与启动计算,临时设置一个启动时全局光标 */
+        QCursor::setPos(platformScreen->geometry().center());
+    }
+    if (window->type() != Qt::Desktop) {
+        QOhPlatformScreen *screen = this->platformScreen();
+        auto targetPlatformScreen = QOhDisplayManager::instance()->screenAt(m_rect.center());
+        if (targetPlatformScreen && screen != targetPlatformScreen) {
+            QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(window, targetPlatformScreen->screen());
+        }
+    }
+}
+
+QOhPlatformOpenGLWindow::~QOhPlatformOpenGLWindow()
+{
+    if (!m_nativeWindow.isNull()) {
+        if (m_mouseGrab == m_nativeWindow.data())
+            m_mouseGrab = nullptr;
+        qNativeWindowManager->destroyWindow(m_nativeWindow.take());
+    }
+}
+
+// 当设置了type flags时需要调整window
+static inline void fixTopLevelWindowFlags(QWindow *w)
+{
+    if (!w->isTopLevel())
+        return;
+    Qt::WindowFlags flags = w->flags();
+    flags &= ~Qt::WindowFullscreenButtonHint;
+
+    /* 添加悬浮窗自带的属性 */
+    if (flags.testFlag(Qt::Floating))
+        flags |= Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint;
+
+    switch (flags) {
+    case Qt::Window:
+        flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint
+              |Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint;
+        break;
+    case Qt::Dialog:
+    case Qt::Tool:
+        flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
+        break;
+    default:
+        break;
+    }
+    if ((flags & Qt::WindowType_Mask) == Qt::SplashScreen)
+        flags |= Qt::FramelessWindowHint;
+
+    w->setFlags(flags);
+}
+
+void QOhPlatformOpenGLWindow::initialize()
+{
+    QOhPlatformWindow::initialize();
+    QPlatformScreen *qScreen = screen();
+    QWindow *qWindow = window();
+    fixTopLevelWindowFlags(qWindow);
+    QRect rect;
+    if (isGeometryControlledBySystem()) {
+        rect = screen()->availableGeometry();
+    } else {
+        QRect windowGeometry = m_rect;
+        QScreen *resultScreen = nullptr;
+        rect = initialGeometry(qWindow, windowGeometry, defaultWindowWidth, defaultWindowHeight,
+                               (const QScreen **)&resultScreen);
+
+        if (qWindow->type() != Qt::Desktop) {
+            if (resultScreen && qScreen != resultScreen->handle()) {
+                // Trigger geometry change (unless it has a special state in which case setWindowState()
+                // will send the message) and screen change signals of QWindow.
+                QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(qWindow, resultScreen);
+            }
+        }
+
+        // 设置到屏幕中间, initialGeometry中,当窗口的大小大于屏幕大小的8/9时就不会移到中间
+        const auto *wp = qt_window_private(const_cast<QWindow*>(qWindow));
+        const bool position = wp->positionAutomatic && (qWindow->type() != Qt::Popup) && qWindow->isTopLevel();
+        if (resultScreen !=nullptr && position) {
+            const QRect availableGeometry = resultScreen->handle()->availableGeometry();
+            const QWindow *tp = qWindow->transientParent();
+            if (rect.width() <= availableGeometry.width()
+                && rect.height() <= availableGeometry.height()) {
+                if (tp) {
+                    // A transient window should be centered w.r.t. its transient parent.
+                    rect.moveCenter(tp->handle()->geometry().center());
+                } else {
+                    rect.moveCenter(availableGeometry.center());
+                }
+            }
+        }
+    }
+    QRect oldRect = m_rect;
+    m_rect = rect;
+    createNativeWindowNode();
+    m_normalRect = rect;
+    const Qt::WindowState state = qWindow->windowState();
+    if (qWindow->type() != Qt::Desktop && state != Qt::WindowMaximized && state != Qt::WindowFullScreen && oldRect != m_rect)
+        QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(qWindow, m_rect);
+
+#if OHOS_SDK_VERSION > 13
+    bool enable = QtOh::isEnvironmentVariableIsTrue("QT_ENABLE_ACCESSIBILITY", false);
+    if (enable)
+        QOhAccessibilityProvider::registerForWindow(window());
+#endif
+    updateNodeRenderFit();
+}
+
+QOhPlatformOpenGLWindow::Kind QOhPlatformOpenGLWindow::windowKind() const
+{
+    auto qWindow = window();
+    auto parent = qWindow->parent();
+    auto transientParent = qWindow->transientParent();
+    auto windowType = qWindow->type();
+    if (windowType == Qt::SplashScreen)
+        return Kind::SplashWindow;
+
+    static QSet<Qt::WindowType> subWindowTypes = {
+        Qt::ToolTip,
+        Qt::Popup,
+        Qt::Floating
+    };
+    bool autoSubWindow = subWindowTypes.contains(windowType);
+
+    Kind initialWindowKind;
+    if (parent != nullptr) {
+        initialWindowKind = Kind::NativeNode;
+    } else if (transientParent != nullptr) {
+        initialWindowKind = Kind::SubWindow;
+    } else if (autoSubWindow || (isModal() && QtOh::apiVersion() < 14) ) {
+        if (m_volatileWindowKind != Kind::InValid)
+            return m_volatileWindowKind;
+
+        auto focusWindow = qGuiApp->focusWindow();
+        // QWidget::show没有激活窗口, 需要调用QWidget::activateWindow、找到focusWindow才是最新显示的窗口
+        QWindow *topWindow = nullptr;
+        QWindowList list = qApp->topLevelWindows();
+        for(int i = list.size() - 1; i >= 0; i--){
+            if (qWindow != list[i] && list[i]->isVisible()){
+                topWindow = list[i];
+            }
+        }
+
+        auto p = (focusWindow && focusWindow != qWindow) ? focusWindow : topWindow;
+        /* FIXME tooltip创建为鸿蒙主窗口
+         * p != qWindow造成焦点在其他非Qt窗口时,
+         * Qt窗口的tooltip创建为主窗口
+         */
+        if (p != nullptr/* && p != qWindow*/) {
+            /* 鸿蒙系统下,如果父窗口隐藏掉, 子窗口无法显示 */
+            // !p->isTopLevel() ||
+            while (p && !p->isVisible() && (p->type() == Qt::Popup || p->type() == Qt::ToolTip)) {
+                p = p->parent(QWindow::ExcludeTransients);
+            }
+            /* 如果没有显示的窗口,只能创建主窗口 */
+            if (p == nullptr) {
+                initialWindowKind = Kind::MainWindow;
+            } else {
+                qWindow->setTransientParent(p);
+                initialWindowKind = Kind::SubWindow;
+            }
+        } else {
+            initialWindowKind = Kind::MainWindow;
+        }
+        m_volatileWindowKind = initialWindowKind;
+    } else {
+        initialWindowKind = Kind::MainWindow;
+    }
+    return initialWindowKind;
+}
+
+void QOhPlatformOpenGLWindow::setMask(const QRegion &region)
+{
+    if (m_nativeWindow.isNull()) {
+        m_initMask = region;
+        return;
+    }
+
+    QRect rect = m_nativeWindow->geometry();
+    m_nativeWindow->setMask(region, rect.isEmpty() ? m_normalRect : rect);
+}
+
+void QOhPlatformOpenGLWindow::setGeometry(const QRect &rect)
+{
+    m_rect = rect;
+    QOhPlatformWindow::setGeometry(rect);
+    if (isGeometryControlledBySystem()) {
+        return;
+    }
+
+    if (m_nativeWindow.isNull()) {
+        m_normalRect = m_rect;
+        return;
+    }
+
+    auto kind = windowKind();
+    // 设置nativewindow的尺寸
+    if (kind != QOhPlatformOpenGLWindow::Kind::SplashWindow) {
+        m_nativeWindow->setGeometry(rect);
+    }
+}
+
+QRect QOhPlatformOpenGLWindow::geometry() const
+{
+    return m_rect;
+}
+
+EGLSurface QOhPlatformOpenGLWindow::eglSurface(EGLDisplay display, EGLConfig config)
+{
+    if (m_eglSurface == EGL_NO_SURFACE) {
+        checkNativeSurface(display, config);
+    }
+    return m_eglSurface;
+}
+
+bool QOhPlatformOpenGLWindow::checkNativeSurface(EGLDisplay display, EGLConfig config)
+{
+    if (nullptr == m_node || !window())
+        return false;
+    m_eglSurface = m_node->eglSurface(display, config);
+    m_format = q_glFormatFromConfig(display, config, window()->requestedFormat());
+    return true;
+}
+
+void QOhPlatformOpenGLWindow::applicationStateChanged(Qt::ApplicationState state)
+{
+    QOhPlatformWindow::applicationStateChanged(state);
+    if (state <=  Qt::ApplicationHidden) {
+    }
+}
+
+void QOhPlatformOpenGLWindow::propagateSizeHints()
+{
+    if (m_nativeWindow.isNull())
+        return;
+    QOhNativeWindow::WindowLimits limits(windowMinimumSize(), windowMaximumSize());
+    m_nativeWindow->setWindowLimits(limits, QtOh::Utility::type() == QtOh::Utility::PC);
+}
+
+QSurfaceFormat QOhPlatformOpenGLWindow::format() const
+{
+    if (m_eglSurface == 0)
+        return window()->requestedFormat();
+    else
+        return m_format;
+}
+
+void QOhPlatformOpenGLWindow::setWindowFlags(Qt::WindowFlags flags)
+{
+    if (m_nativeWindow.isNull())
+        return;
+
+    bool isFrameLess = flags.testFlag(Qt::FramelessWindowHint);
+
+    if (QtOh::isSupportFreeWindow()) {
+        if (m_nativeWindow->isTopWindow()) {
+            m_nativeWindow->setWindowTitleButtonVisible(flags.testFlag(Qt::WindowMaximizeButtonHint),
+                                                    flags.testFlag(Qt::WindowMinimizeButtonHint),
+                                                    flags.testFlag(Qt::WindowCloseButtonHint));
+            m_nativeWindow->setWindowTopmost(flags.testFlag(Qt::WindowStaysOnTopHint));
+        }
+        m_nativeWindow->setWindowTitleMoveEnabled(!isFrameLess);
+    }
+
+    /* 窗口背景透明初始化,仅支持透明背景色及qt默认背景色,其它背景色应使用OhExtras模块接口设置 */
+    QWindow *w = window();
+    bool isTransparent = w->format().hasAlpha() && flags.testFlag(Qt::FramelessWindowHint);
+    if (isTransparent) {
+        m_nativeWindow->setWindowBackgroundColor(Qt::transparent);
+    } else {
+        QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
+        const QPalette *pal = theme->palette();
+        m_nativeWindow->setWindowBackgroundColor(pal->color(QPalette::Window));
+    }
+
+    /* 设置窗口是否鼠标事件(鼠标透传) */
+    bool isTouchable = !flags.testFlag(Qt::WindowTransparentForInput);
+    m_nativeWindow->setWindowTouchable(isTouchable);
+}
+
+void QOhPlatformOpenGLWindow::setParent(const QPlatformWindow *window)
+{
+    if (window && !m_nativeWindow.isNull()) {
+        destroyNativeWindow();
+    }
+
+    QOhPlatformWindow::setParent(window);
+}
+
+void QOhPlatformOpenGLWindow::requestActivateWindow()
+{
+    if (!m_nativeWindow.isNull() && m_nativeWindow->isVisible()) {
+        m_nativeWindow->requestFocus();
+        /*置前*/
+        m_nativeWindow->raise();
+    } else {
+        m_requestActivate = true;
+    }
+    // 如果没有显示,设置不生效,在setVisible中重新设置
+    if (m_node && m_node->isVisible())
+        m_node->setNodeFocus(true);
+    else
+        m_focus = true;
+}
+
+void QOhPlatformOpenGLWindow::setWindowState(Qt::WindowStates state)
+{
+    if (state == m_windowState)
+        return;
+
+    auto newState = state;
+    if ((QtOh::isTabletDevice() || QtOh::isPhoneDevice())  &&
+        !QtOh::isFreeWindowEnable()) {
+        newState = ((window()->flags() & Qt::Window) && (window()->transientParent() || window()->parent())) ? Qt::WindowNoState : state;
+    }
+    setWindowState_sys(newState);
+    m_windowState = newState;
+    QRect rect = m_rect;
+    auto *screen = platformScreen();
+    if (!screen)
+        screen = dynamic_cast<QOhPlatformScreen *>(QGuiApplication::primaryScreen()->handle());
+    if (m_windowState.testFlag(Qt::WindowMaximized)) {
+        m_rect = screen->availableGeometry();
+    }
+    if (m_windowState.testFlag(Qt::WindowFullScreen)) {
+        m_rect = screen->geometry();
+    }
+    if (rect != m_rect) {
+        QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(window(), m_rect);
+    }
+}
+
+void QOhPlatformOpenGLWindow::createNativeWindow()
+{
+    QWindow *window = this->window();
+    QRect initRect = QOhNativeWindow::adjustRect(window, m_normalRect, frameMargins());
+    qCWarning(openharmonyQPA) << "create open harmony window for" << this << "windowFlag:" << window->flags() << initRect;
+    initRect = initRect.translated(-platformScreen()->geometry().topLeft());
+    m_nativeWindow.reset(qNativeWindowManager->createNativeWindow(this, initRect));
+    if (m_nativeWindow.isNull()) {
+        deleteNativeWindowNode();
+        return;
+    }
+    qCWarning(openharmonyQPA)
+            << Q_FUNC_INFO << m_nativeWindow.data()
+            << "m_normalRect:" << initRect
+            << "native window name: " << m_nativeWindow->name();
+    if (m_nativeWindow->nativeWindowType() == QOhNativeWindow::EXTENSION_WINDOW) {
+        m_rect = m_nativeWindow->geometry();
+    }
+
+    bool active = !showWithoutActive();
+    if (active) {
+        m_focus = true;
+    }
+
+    applyCursor();
+
+    m_nativeWindow->setWindowTitleVisible(this->hasFrame());
+    setWindowFlags(window->flags());
+    if (!m_initMask.isEmpty()) {
+        setMask(m_initMask);
+    }
+    propagateSizeHints();
+    m_nativeWindow->setWindowTitle(windowTitle());
+
+    if (isGeometryControlledBySystem()) {
+        // 窗口未显示,无法获取到正确的值,使用屏幕的大小
+//        QRect rect = m_nativeWindow->geometry();
+        QRect rect = screen()->availableGeometry();
+        m_nativeWindow->reportWindowGeometry(rect);
+    } else {
+        QTimer::singleShot(10, window, [this]{
+            if (m_nativeWindow.isNull())
+                return ;
+            m_nativeWindow->reportWindowGeometry();
+        });
+
+        if (m_windowState == Qt::WindowNoState) {
+            m_nativeWindow->setGeometry(m_normalRect);
+        }
+    }
+}
+
+void QOhPlatformOpenGLWindow::setVisible(bool visible)
+{
+    m_isExposed = visible;
+    Kind kind = windowKind();
+    if (kind != Kind::NativeNode && m_nativeWindow.isNull() && visible) {
+        createNativeWindow();
+    }
+
+    if (visible) {
+        showNativeNode();
+        showNativeWindow();
+        fireFullExpose(true);
+    } else {
+        if (m_nativeWindow.isNull()) {
+            hideNativeNode();
+        } else {
+            hideNativeWindow();
+        }
+        if (QOhWindowContext::mouseGrabberWindow() == window())
+            QOhWindowContext::setMouseGrabberWindow(nullptr);
+
+        /* popup窗口不会获取焦点,显示和隐藏不会触发焦点转移,在此处更新输入法状态 */
+        if (window()->type() == Qt::Popup)
+            QOhPlatformInputContext::ohInputContext()->updateInputEnabled();
+        fireExpose(QRegion());
+        QOhPlatformBackingStore::releaseVsync(window());
+    }
+    m_windowIsHidden = !visible;
+}
+
+QOhNativeWindow *QOhPlatformOpenGLWindow::nativeWindow() const
+{
+    return m_nativeWindow.data();
+}
+
+QMargins QOhPlatformOpenGLWindow::frameMargins() const
+{
+    if (m_nativeWindow.isNull()) {
+        QMargins m;
+        if (!hasFrame() || m_windowState.testFlag(Qt::WindowFullScreen))
+            return m;
+        static int titleHeight = 37;
+        m = QMargins(0, titleHeight * QtOh::densityPixels(screen()), 0, 0);
+        return m;
+    }
+
+    return m_nativeWindow->frameMargins();
+}
+
+bool QOhPlatformOpenGLWindow::setWindowState_sys(Qt::WindowStates state)
+{
+    if (m_nativeWindow.isNull())
+        return false;
+
+    Kind kind = windowKind();
+    if (!isGeometryControlledBySystem() && kind == Kind::MainWindow)
+        m_nativeWindow->setWindowModal(isModal());
+
+    //NOTE:isVisible()接口在窗口最小化时返回false
+    const QtOh::WindowStatusType windowStatus = m_nativeWindow->windowStatus();
+    bool visible = m_nativeWindow->isVisible() || windowStatus == QtOh::WindowStatusType::MINIMIZE;
+    auto oldState = m_windowState;
+
+    auto setNativeWindowState = [this](Qt::WindowStates state) {
+        if (state & Qt::WindowFullScreen) {
+            m_nativeWindow->showFullScreen();
+        } else if (state & Qt::WindowMaximized) {
+            m_nativeWindow->showMaximized();
+        } else {
+            m_nativeWindow->showNormal();
+        }
+    };
+
+    const auto stateChange = oldState ^ state;
+    if (stateChange & Qt::WindowFullScreen) {
+        setNativeWindowState(state);
+    } else if ((oldState & Qt::WindowMaximized) != (state & Qt::WindowMaximized)) {
+        if (visible && !(state & Qt::WindowMinimized)) {
+            if (state & Qt::WindowMaximized)
+                m_nativeWindow->showMaximized();
+            else
+                m_nativeWindow->showNormal();
+        } else if (visible && (oldState & state & Qt::WindowMinimized)) {
+
+        }
+    } else if (stateChange == Qt::WindowNoState) {
+        setNativeWindowState(state);
+    }
+    if (stateChange & Qt::WindowMinimized) {
+        if (visible) {
+            if (state & Qt::WindowMinimized) {
+                fireExpose();
+                m_minimized = true;
+                m_nativeWindow->showMinimized();
+            } else {
+                setNativeWindowState(state);
+            }
+        }
+    }
+    return true;
+}
+
+void QOhPlatformOpenGLWindow::raise()
+{
+    QOhPlatformWindow::raise();
+    if (m_nativeWindow.isNull()) {
+        return;
+    }
+    m_nativeWindow->raise();
+}
+
+bool QOhPlatformOpenGLWindow::canApplyNewCursor(const QWindow *w)
+{
+    const QWindow *underMouse = QOhWindowContext::underMouseWindow();
+    if (underMouse == w)
+        return true;
+    for (const QWindow *p = underMouse; p ; p = p->parent()) {
+        if (p == w)
+            return true;
+        const QOhPlatformOpenGLWindow *platformWindow = platformWindowOfWindow(p);
+        if (platformWindow && platformWindow->m_cursor != nullptr)
+            return false;
+    }
+    return false;
+}
+
+void QOhPlatformOpenGLWindow::setCursor(QCursorInfo *cursor)
+{
+#ifndef QT_NO_CURSOR
+    bool changed = (cursor != m_cursor);
+    if (changed) {
+        m_cursor = cursor;
+        QWindow *w = window();
+        const bool apply = canApplyNewCursor(w);
+        //qInfo(openharmonyQPA) << apply  <<(m_cursor ? m_cursor->shape : -1) << w;
+        if (apply)
+            applyCursor();
+    }
+#endif
+}
+
+bool QOhPlatformOpenGLWindow::startSystemMove()
+{
+    if (m_nativeWindow.isNull())
+        return false;
+    return m_nativeWindow->startSystemMove();
+}
+
+void QOhPlatformOpenGLWindow::setWindowTitle(const QString &title)
+{
+    if (m_nativeWindow.isNull())
+        return;
+    return m_nativeWindow->setWindowTitle(title);
+}
+
+bool QOhPlatformOpenGLWindow::isGeometryControlledBySystem() const
+{
+    return (QtOh::Utility::type() != QtOh::Utility::PC) &&
+            ((window()->flags() & Qt::WindowType_Mask) == Qt::Window || Kind::MainWindow == windowKind()) &&
+            !QtOh::isFreeWindowEnable() && !window()->transientParent();
+}
+
+void QOhPlatformOpenGLWindow::setNativeGeometry(const QRect &rect)
+{
+    m_rect = rect;
+}
+
+int32_t QOhPlatformOpenGLWindow::nativeWindowId() const
+{
+    if (!m_nativeWindow.isNull())
+        return m_nativeWindow->id();
+    return 0;
+}
+
+QOhPlatformOpenGLWindow *QOhPlatformOpenGLWindow::platformWindowOfWindow(const QWindow *w)
+{
+    if (!w || !w->handle())
+        return nullptr;
+
+    const Qt::WindowType type = w->type();
+    if (type == Qt::Desktop || w->handle()->isForeignWindow())
+        return nullptr;
+
+    return static_cast<QOhPlatformOpenGLWindow *>(w->handle());
+}
+
+void QOhPlatformOpenGLWindow::applyCursor()
+{
+#ifndef QT_NO_CURSOR
+    const QOhNativeWindow *nativeWindow = this->nativeWindow();
+    QWindow *w = window();
+    while(!nativeWindow && (w = w->parent())) {
+        QOhPlatformOpenGLWindow *pw = static_cast<QOhPlatformOpenGLWindow *>(w->handle());
+        if (!pw)
+            break;
+        nativeWindow = pw->nativeWindow();
+    }
+    if (nativeWindow == nullptr)
+        return;
+    int wid = nativeWindow->id();
+    if (QOhPlatformCursor::hasOverrideCursor()) {
+        if (isTopLevelWindow())
+            QOhPlatformCursor::enforceOverrideCursor(wid);
+        return;
+    }
+
+    if (m_cursor == nullptr) {
+        if (const QWindow *p = window()->parent()) {
+            if (QOhPlatformOpenGLWindow *platformWindow = platformWindowOfWindow(p))
+                platformWindow->applyCursor();
+        } else {
+            QOhPlatformCursor::setDefaultCursor(wid);
+        }
+    } else {
+        QOhPlatformCursor::setCursor(wid, m_cursor);
+    }
+#endif
+}
+
+void QOhPlatformOpenGLWindow::showNativeWindow()
+{
+    if (m_nativeWindow.isNull())
+        return;
+
+    if (showWithoutActive()) {
+        m_nativeWindow->setWindowFocusable(false);
+    }
+
+    Kind kind = windowKind();
+    bool hideEnable = (kind == Kind::MainWindow && QOhSystemTrayIcon::hasTrayIcon() && QtOh::apiVersion() > 13);
+    if (hideEnable) {
+        QJsAbility *ability = m_nativeWindow->ability();
+        if (ability && ability->context()) {
+            m_nativeWindow->setShowSysFlag();
+            ability->context()->showAbility();
+        }
+        bool active = !showWithoutActive();
+        if (active) {
+            m_node->setNodeFocus(true);
+        }
+    }
+
+    setWindowState_sys(m_windowState);
+
+    if (m_requestActivate) {
+        m_nativeWindow->requestFocus();
+        m_requestActivate = std::nullopt;
+    }
+    m_nativeWindow->raiseNativeWindow();
+
+    // 直接执行时,窗口可能还没有执行显示操作,导致显示时会获取焦点
+    if (showWithoutActive() && canSetFocus()) {
+        QTimer::singleShot(50, window(), [this]{
+            if (m_nativeWindow.isNull())
+                return;
+            m_nativeWindow->setWindowFocusable(true);
+        });
+    };
+}
+
+void QOhPlatformOpenGLWindow::hideNativeWindow()
+{
+    if (m_nativeWindow.isNull())
+        return;
+
+    Kind kind = windowKind();
+    bool hideed = false;
+    if (Kind::MainWindow == kind && QtOh::apiVersion() > 13) {
+        QJsAbility *ability = m_nativeWindow->ability();
+        if(ability && ability->context())
+            hideed = ability->context()->hideAbility();
+    }
+
+    if (hideed)
+        return;
+
+    if (kind == Kind::MainWindow || kind == Kind::SplashWindow) {
+        destroyNativeWindow();
+    } else if (kind == Kind::SubWindow) {
+        m_nativeWindow->setVisible(false);
+        if (m_mouseGrab == m_nativeWindow.data()) {
+            m_mouseGrab->setMouseGrabEnabled(false);
+            m_mouseGrab = nullptr;
+        }
+        updateUnderMouseWindow();
+    }
+}
+
+void QOhPlatformOpenGLWindow::destroyNativeWindow()
+{
+    /* 直接销毁,setParent()设置父widget时,原js窗口应销毁 */
+    // 记录隐藏之前的大小,下次显示的时候重新是重新创建js窗口
+    // 在次记录下次显示的设置
+    // 从m_nativeWindow获取可能最新的size还未更新(resize后立即hide)
+    m_normalRect = m_nativeWindow->normalGeometry();
+    m_normalRect = m_normalRect.translated(platformScreen()->geometry().topLeft());
+    if (m_mouseGrab == m_nativeWindow.data()) {
+        m_mouseGrab->setMouseGrabEnabled(false);
+        m_mouseGrab = nullptr;
+    }
+    m_node->detachRootComponent(true);
+    m_node->setOwnerWindow(nullptr);
+    qNativeWindowManager->destroyWindow(m_nativeWindow.take());
+    updateUnderMouseWindow();
+}
+
+void QOhPlatformOpenGLWindow::updateNodeRenderFit()
+{
+    if (m_node && window()) {
+        auto var = window()->property(QOpenHarmonyWindow::NativeNodeFitIdentifier); /* Qt6 only modify */
+        if (!var.isNull())
+            m_node->setRenderFit(ArkUI_RenderFit(var.toInt()));
+    }
+}
+
+void QOhPlatformOpenGLWindow::createNativeWindowNode(WId nativeHandle)
+{
+    QOhPlatformWindow::createNativeWindowNode(nativeHandle);
+    QWindow *qWindow = window();
+    auto node = nativeWindowNode();
+    node->createNode(QRectF(m_rect), !showWithoutActive());
+    updateXComponentBackground();
+    qCInfo(openharmonyQPA) << Q_FUNC_INFO << this
+                           << "rect: " << m_rect
+                           << "parentWindow:" << parent()
+                           << "qWindow transientParent:" << qWindow->transientParent()
+                           << "windowFlags: " << qWindow->flags();
+}
+
+void QOhPlatformOpenGLWindow::updateXComponentBackground()
+{
+    QWindow *qWindow = window();
+    if (!qWindow)
+        return;
+    Qt::WindowFlags flags = qWindow->flags();
+    bool isTransparent = qWindow->format().hasAlpha() && flags.testFlag(Qt::FramelessWindowHint);
+
+    auto *node = nativeWindowNode();
+    /*
+     * NOTE quickwindow窗口不能设置XComponent背景色
+     * 设置后可能导致渲染异常
+     */
+    if (QSurface::OpenGLSurface != qWindow->surfaceType()) {
+        QVariant var = qWindow->property("_q_background");
+        QBrush brush = var.value<QBrush>();
+        QColor bgColor;
+        if (Qt::NoBrush == brush.style()) {
+            bgColor = isTransparent ? Qt::transparent : Qt::white;
+        } else {
+            bgColor = qbrush_color(brush);
+        }
+
+        node->setBackgroundColor(bgColor);
+    } else {
+        node->setBackgroundColor(Qt::transparent);
+    }
+}
+
+void QOhPlatformOpenGLWindow::updateUnderMouseWindow()
+{
+    static int s_updateCount = 0;
+    ++s_updateCount;
+
+    QTimer::singleShot(30, nullptr, [] {
+        if (--s_updateCount != 0)
+            return;
+
+        /* 等待窗口关闭的leave事件触发后,更新当前鼠标下的窗口触发enter事件 */
+        QPoint globalPos, localPos;
+        globalPos = QCursor::pos();
+
+        QWindow *qWindow = nullptr;
+        if (QScreen *windowScreen = QGuiApplication::screenAt(globalPos)) {
+            const QPoint devicePosition = QHighDpi::toNativePixels(globalPos, windowScreen);
+            globalPos = devicePosition;
+            QOhPlatformScreen *ps = dynamic_cast<QOhPlatformScreen *>(windowScreen->handle());
+            qWindow = QOhWindowContext::getWindowByCoordinate(ps, devicePosition);
+        }
+
+        if (!qWindow)
+            return;
+
+        localPos = qWindow->handle()->mapFromGlobal(globalPos);
+        QOhWindowContext::setUnderMouseWindow(qWindow, localPos, globalPos);
+    });
+}
+
+bool QOhPlatformOpenGLWindow::windowEvent(QEvent *event)
+{
+    if (event->type() == QEvent::DynamicPropertyChange) {
+        QDynamicPropertyChangeEvent *propertyEvent = static_cast<QDynamicPropertyChangeEvent*>(event);
+        if (propertyEvent->propertyName() == "_q_background") {
+            updateXComponentBackground();
+        } else if (propertyEvent->propertyName() == QOpenHarmonyWindow::NativeNodeFitIdentifier) { /* Qt6 only modify */
+            updateNodeRenderFit();
+        }
+    }
+    return QOhPlatformWindow::windowEvent(event);
+}
+
+void QOhPlatformOpenGLWindow::showNativeNode()
+{
+    QOhPlatformWindow::showNativeNode();
+    if (m_node != nullptr) {
+        if (m_focus) {
+            m_node->setNodeFocus(m_focus.value());
+            m_focus = std::nullopt;
+        }
+    }
+}
+
+void QOhPlatformOpenGLWindow::handleWindowStateChange(Qt::WindowStates states)
+{
+    /*
+     * 屏蔽主动改变窗口状态的系统回调,比如STATUS_MINIMIZE
+     *下面三种情况都会收到STATUS_MINIMIZE状态回调
+     *1、QWidget::hide接口(底层使用js的minimize()接口),不更新state
+     *2、QWidget::showMinimized由qt上层更新state
+     *3、点击系统的最小化按钮,更新state为Qt::WindowMinimized
+     */
+    // hide接口回调屏蔽
+    if (m_windowIsHidden && states.testFlag(Qt::WindowMinimized))
+        states = states ^ Qt::WindowMinimized;
+
+    Qt::WindowStates newState = Qt::WindowNoState;
+
+    if (!m_nativeWindow.isNull()) {
+        m_minimized = m_nativeWindow->windowStatus() == QtOh::WindowStatusType::MINIMIZE;
+    }
+    if (m_minimized)
+        newState = Qt::WindowMinimized;
+
+    if (states.testFlag(Qt::WindowFullScreen))
+        newState |= Qt::WindowFullScreen;
+    if (states.testFlag(Qt::WindowMaximized))
+        newState |= Qt::WindowMaximized;
+    QOhPlatformWindow::handleWindowStateChange(newState);
+}
+
+void QOhPlatformOpenGLWindow::lower()
+{
+    QOhPlatformWindow::lower();
+    if (m_nativeWindow.isNull()) {
+        return;
+    }
+    m_nativeWindow->lower();
+}
+
+bool QOhPlatformOpenGLWindow::setMouseGrabEnabled(bool grab)
+{
+    if (m_nativeWindow.isNull()) {
+        return false;
+    }
+    if (grab && m_mouseGrab == m_nativeWindow.data())
+        return true;
+    if (grab && m_mouseGrab != nullptr && m_mouseGrab != m_nativeWindow.data())
+        m_mouseGrab->setMouseGrabEnabled(false);
+    bool result = m_nativeWindow->setMouseGrabEnabled(grab);
+    if (result) {
+        m_mouseGrab = grab ? m_nativeWindow.data() : nullptr;
+        QOhPlatformWindow::setMouseGrabEnabled(grab);
+    }
+    return result;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohplatformopenglwindow.h b/src/plugins/platforms/openharmony/qohplatformopenglwindow.h
new file mode 100644
index 00000000000..42b9a9a5f7b
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformopenglwindow.h
@@ -0,0 +1,99 @@
+#ifndef QOHPLATFORMOPENGLWINDOW_H
+#define QOHPLATFORMOPENGLWINDOW_H
+
+#include <QHash>
+#include <EGL/egl.h>
+#include <QPointer>
+#include <QMutex>
+#include <optional>
+#include <QWaitCondition>
+#include "qohplatformwindow.h"
+#include "qohnativewindow.h"
+
+QT_BEGIN_NAMESPACE
+class QOhWindowNode;
+struct OH_NativeXComponent;
+
+class QOhPlatformOpenGLWindow : public QOhPlatformWindow
+{
+public:
+    enum class Kind
+    {
+        MainWindow,
+        SubWindow,
+        NativeNode,// child widget, not a independent window
+        SplashWindow,
+        InValid = 0xFFU
+    };
+    explicit QOhPlatformOpenGLWindow(QWindow *window);
+    ~QOhPlatformOpenGLWindow() override;
+
+    void initialize() override;
+    Kind windowKind() const;
+
+    void setMask(const QRegion &region) override;
+    void setGeometry(const QRect &rect) override;
+    QRect geometry() const override;
+
+    EGLSurface eglSurface(EGLDisplay display, EGLConfig config);
+    QSurfaceFormat format() const override;
+    void setWindowFlags(Qt::WindowFlags flags) override;
+    void setParent(const QPlatformWindow *window) override;
+    void requestActivateWindow() override;
+
+    virtual void setWindowState(Qt::WindowStates state) override;
+    bool checkNativeSurface(EGLDisplay display, EGLConfig config);
+
+    void applicationStateChanged(Qt::ApplicationState) override;
+    void propagateSizeHints() override;
+    bool setMouseGrabEnabled(bool grab) override;
+
+    void setVisible(bool visible) override;
+    QOhNativeWindow *nativeWindow() const;
+    QMargins frameMargins() const override;
+
+    void lower() override;
+    void raise() override;
+
+    int32_t nativeWindowId() const override;
+    virtual void setCursor(QCursorInfo *cursor) override;
+    virtual QCursorInfo *cursor() const override { return m_cursor; }
+    virtual bool startSystemMove() override;
+    void setWindowTitle(const QString &title) override;
+
+    bool isGeometryControlledBySystem() const;
+    void setNativeGeometry(const QRect &rect);
+    void applyCursor();
+    bool windowEvent(QEvent *event) override;
+protected:
+    bool setWindowState_sys(Qt::WindowStates state);
+    void createNativeWindow();
+    void showNativeWindow();
+    void hideNativeWindow();
+    void destroyNativeWindow();
+    void updateNodeRenderFit();
+    void createNativeWindowNode(WId nativeHandle = 0) override;
+    void updateXComponentBackground();
+    void updateUnderMouseWindow();
+    virtual void showNativeNode() override;
+    virtual void handleWindowStateChange(Qt::WindowStates states) override;
+    static bool canApplyNewCursor(const QWindow *w);
+    static QOhPlatformOpenGLWindow *platformWindowOfWindow(const QWindow *w);
+private:
+    EGLSurface m_eglSurface = EGL_NO_SURFACE;
+    QSurfaceFormat m_format;
+    QScopedPointer<QOhNativeWindow> m_nativeWindow;
+    static QOhNativeWindow *m_mouseGrab;
+    QRect m_normalRect;
+    QRect m_rect;
+    QRegion m_initMask;
+    QCursorInfo *m_cursor = nullptr;
+    std::optional<bool> m_focus;
+    std::optional<bool> m_requestActivate;
+    mutable Kind m_volatileWindowKind = Kind::InValid;
+    bool m_windowIsHidden = true;
+    bool m_minimized = false;
+};
+
+QT_END_NAMESPACE
+#endif // QOHPLATFORMOPENGLWINDOW_H
diff --git a/src/plugins/platforms/openharmony/qohplatformplugin.cpp b/src/plugins/platforms/openharmony/qohplatformplugin.cpp
new file mode 100644
index 00000000000..81589a3bb86
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformplugin.cpp
@@ -0,0 +1,25 @@
+#include <qpa/qplatformintegrationplugin.h>
+#include "qohplatformintegration.h"
+
+QT_BEGIN_NAMESPACE
+
+class QOhPlatformIntegrationPlugin: public QPlatformIntegrationPlugin
+{
+    Q_OBJECT
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "openharmony.json")
+public:
+    QPlatformIntegration *create(const QString &key, const QStringList &paramList) override;
+};
+
+
+QPlatformIntegration *QOhPlatformIntegrationPlugin::create(const QString &key, const QStringList &paramList)
+{
+    Q_UNUSED(paramList);
+    if (!key.compare(QLatin1String("openharmony"), Qt::CaseInsensitive))
+        return new QOhPlatformIntegration(paramList);
+    return 0;
+}
+
+QT_END_NAMESPACE
+#include "qohplatformplugin.moc"
+
diff --git a/src/plugins/platforms/openharmony/qohplatformscreen.cpp b/src/plugins/platforms/openharmony/qohplatformscreen.cpp
new file mode 100644
index 00000000000..0383fbf0bce
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformscreen.cpp
@@ -0,0 +1,394 @@
+#include <QTime>
+#include <QStaticText>
+#include <qpa/qwindowsysteminterface.h>
+
+#include "qohplatformscreen.h"
+#include "qohplatformintegration.h"
+#include "qohplatformwindow.h"
+#include "qohplatformopenglwindow.h"
+#include "qohplatformcursor.h"
+#include "qohwindownode.h"
+#include "qohwindowcontext.h"
+#include "qoheventdispatcher.h"
+
+#include <qguiapplication.h>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QWindow>
+#include <private/qguiapplication_p.h>
+#include <private/qhighdpiscaling_p.h>
+#include <private/qjspromise_p.h>
+#include <QtGui/private/qwindow_p.h>
+#include <private/qt_egl_p.h> /* Qt6 only modify */
+#include <QImage>
+#include <QByteArray>
+#include <QtCore/qopenharmonydefines.h>
+#include "qohplatformwindow.h"
+#include "qohwindowcontext.h"
+#include <QTimer>
+#include <sys/mman.h>
+#if OHOS_SDK_VERSION > 13
+#include "qohdisplaymanager.h"
+#include "qohdisplay.h"
+#include <window_manager/oh_display_capture.h>
+#else
+#include "qjsscreen.h"
+#include <multimedia/image_framework/image/pixelmap_native.h>
+#endif
+#include <private/qopenharmony_p.h>
+#include "qohauxiliary.h"
+
+QT_BEGIN_NAMESPACE
+
+QDebug &operator<<(QDebug &outputStream, QOhPlatformScreen *platformScreen)
+{
+    outputStream << "QOhPlatformScreen("
+                 << "id:" << platformScreen->displayId()
+                 << "name:" << platformScreen->name()
+                 << "geo:" << platformScreen->geometry()
+                 << " " << platformScreen->refreshRate() << "hz"
+                 << ")";
+    return outputStream;
+}
+
+#if OHOS_SDK_VERSION > 13
+QOhPlatformScreen::QOhPlatformScreen(QOhDisplay *display)
+    : QPlatformScreen(), m_cursor(new QOhPlatformCursor(this))
+    , m_display(display)
+{
+    m_display->setScreen(this);
+    m_availableGeometry = m_display->availableGeometry();
+    m_format = QImage::Format_RGBX8888;
+    m_depth = 32;
+    m_physicalSize = px2mm(m_display->physicalSize());
+    m_refreshRate = m_display->refreshRate();
+    QObject::connect(m_display, &QOhDisplay::orientationChanged, m_display, [this]{
+        handleScreenOrientationChange();
+    });
+
+    QObject::connect(m_display, &QOhDisplay::geometryChanged, m_display, [this]{
+        auto avaGeo = availableGeometry();
+        if (!avaGeo.isEmpty()) {
+            QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), avaGeo);
+        }
+        handleScreenChanged();
+    });
+    QObject::connect(m_display, &QOhDisplay::availableGeometryChanged, m_display, [this]{
+        setAvailableGeometry(m_display->availableGeometry());
+        /* FIXME 屏幕排列布局改变后,通知Qt改变窗口的geometry数据 */
+        handleScreenChanged();
+    });
+    QObject::connect(m_display, &QOhDisplay::physicalSizeChanged, m_display, [this]{
+        setPhysicalSize(m_display->physicalSize());
+    });
+    QObject::connect(m_display, &QOhDisplay::refreshRateChanged, m_display, [this]{
+        handlerefreshRateChange(m_display->refreshRate());
+    });
+    QObject::connect(m_display, &QOhDisplay::scaledDensityChanged, m_display, [this]{
+        handleScreenLogicalDotsPerInchChange();
+        handleScreenChanged();
+    });
+}
+#else
+QOhPlatformScreen::QOhPlatformScreen(QJsScreen *jsScreen)
+    : QPlatformScreen(), m_cursor(new QOhPlatformCursor(this))
+    , m_jsScreen(jsScreen)
+{
+    m_jsScreen->attach(this);
+    m_availableGeometry = m_jsScreen->availableGeometry();
+
+    m_format = QImage::Format_RGBX8888;
+    m_depth = 32;
+    m_physicalSize = px2mm(m_jsScreen->physicalSize());
+    m_refreshRate = m_jsScreen->refreshRate();
+}
+#endif
+
+QOhPlatformScreen::~QOhPlatformScreen()
+{
+#if OHOS_SDK_VERSION > 13
+    m_display->setScreen(nullptr);
+    delete m_display;
+#else
+    m_jsScreen->attach(nullptr);
+    delete m_jsScreen;
+#endif
+}
+
+#if OHOS_SDK_VERSION > 13
+QOhDisplay *QOhPlatformScreen::display() const
+{
+    return m_display;
+}
+#endif
+
+QString QOhPlatformScreen::name() const
+{
+#if OHOS_SDK_VERSION > 13
+    return m_display->name();
+#else
+    return QPlatformScreen::name();
+#endif
+}
+
+QRect QOhPlatformScreen::geometry() const
+{
+#if OHOS_SDK_VERSION > 13
+    return m_display->geometry();
+#else
+    return QRect(QPoint(), m_jsScreen->size());
+#endif
+}
+
+QRect QOhPlatformScreen::availableGeometry() const
+{
+    return m_availableGeometry;
+}
+
+QWindow *QOhPlatformScreen::topLevelAt(const QPoint &p) const
+{
+    return QOhWindowContext::topLevelAt(const_cast<QOhPlatformScreen *>(this), p);
+}
+
+QPixmap QOhPlatformScreen::grabWindow(WId window, int xIn, int yIn, int width, int height) const
+{
+    QPixmap pixmap;
+    QImage image;
+    int x = xIn;
+    int y = yIn;
+
+    QOhWindowNode *node = QOhWindowNode::fromId(window);
+    if (node) {
+        OH_PixelmapNative *pixelMap = node->grab();
+        if (pixelMap != nullptr) {
+            image = QtOh::UdmfHelper::createQImageFromPixelmapNative(pixelMap);
+            OH_PixelmapNative_Release(pixelMap);
+        }
+    } else {
+#if OHOS_SDK_VERSION > 13
+        /* 截全屏 */
+        uint32_t id = m_display->id();
+        OH_PixelmapNative *pixelMap = nullptr;
+        NativeDisplayManager_ErrorCode code = OH_NativeDisplayManager_CaptureScreenPixelmap(id, &pixelMap);
+        if (code != DISPLAY_MANAGER_OK || pixelMap == nullptr) {
+            QString error;
+            switch (code) {
+            case DISPLAY_MANAGER_ERROR_NO_PERMISSION:
+                error = "no permission.";
+                break;
+            case DISPLAY_MANAGER_ERROR_INVALID_PARAM:
+                error = "parameter error.";
+                break;
+            case DISPLAY_MANAGER_ERROR_DEVICE_NOT_SUPPORTED:
+                error = "device not support.";
+                break;
+            case DISPLAY_MANAGER_ERROR_SYSTEM_ABNORMAL:
+                error = "display manager service works abnormally.";
+                break;
+            default:
+                break;
+            }
+            qWarning() << "capture screen failed:" << error;
+            return QPixmap();
+        }
+        image = QtOh::UdmfHelper::createQImageFromPixelmapNative(pixelMap);
+        OH_PixelmapNative_Release(pixelMap);
+#else
+        //TODO:目前没有直接截全屏的接口(12 release beta1)
+        x = 0;
+        y = 0;
+        QJsModule screenshot("@ohos.screenshot");
+        image = QtOh::runOnJsUIThreadWithPromise<QImage>([&](auto p){
+            Napi::Value result = screenshot.call("pick");
+            if (result.IsPromise()) {
+                QJsPromise promise(result.As<Napi::Promise>());
+                promise.onThen([&, p](const Napi::CallbackInfo &info){
+                    if (info.Length() < 1) {
+                        p->set_value(QImage());
+                        return ;
+                    }
+                    Napi::Object pickInfo = info[0].As<Napi::Object>();
+                    Napi::Value pixelMap = pickInfo.Get("pixelMap");
+                    OH_PixelmapNative *result = nullptr;
+                    OH_PixelmapNative_ConvertPixelmapNativeFromNapi(env(), pixelMap, &result);
+                    image = QtOh::UdmfHelper::createQImageFromPixelmapNative(pixelMap);
+                    p->set_value(image);
+                }.onCatch([p](const Napi::CallbackInfo &info){
+                    Q_UNUSED(info);
+                    p->set_value(QImage());
+                });
+            }
+        });
+#endif
+    }
+    if (image.isNull())
+        return QPixmap();
+    
+    if (x <= 0 && y <= 0 && width <= 0 && height <= 0) {
+        QPixmap pix = QPixmap::fromImage(image);
+        return pix;
+    }
+
+    if (x < 0)
+        x = 0;
+    if (y < 0)
+        y = 0;
+    if (width < 0)
+        width = image.width() - x;
+    if (height < 0)
+        height = image.height() - y;
+
+    QImage croppedImage = image.copy(QRect(x, y, width, height));
+    pixmap = QPixmap::fromImage(croppedImage);
+    return pixmap;
+}
+
+QList<QPlatformScreen *> QOhPlatformScreen::virtualSiblings() const
+{
+    QList<QPlatformScreen *> result;
+#if OHOS_SDK_VERSION > 13
+    auto screens = QOhDisplayManager::instance()->allScreens();
+    for (int i = 0; i < screens.count(); i++) {
+        auto *screen = screens[i];
+        result << screen;
+    }
+#else
+    result << const_cast<QOhPlatformScreen *>(this);
+#endif
+    return result;
+}
+
+uint32_t QOhPlatformScreen::displayId()
+{
+#if OHOS_SDK_VERSION > 13
+    return m_display->id();
+#else
+    return m_jsScreen->id();
+#endif
+}
+
+void QOhPlatformScreen::setPhysicalSize(const QSize &size)
+{
+    m_physicalSize = px2mm(size);
+}
+
+void QOhPlatformScreen::setSize(const QSize &size)
+{
+    Q_UNUSED(size)
+    QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
+}
+
+void QOhPlatformScreen::handleScreenLogicalDotsPerInchChange()
+{
+    QDpi dpi = logicalDpi();
+    QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QPlatformScreen::screen(), dpi.first, dpi.second);
+    QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
+}
+
+void QOhPlatformScreen::handleScreenOrientationChange()
+{
+    QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), orientation());
+    QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
+}
+
+void QOhPlatformScreen::handlerefreshRateChange(int refreshRate)
+{
+    m_refreshRate = refreshRate;
+    QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), refreshRate);
+}
+
+void QOhPlatformScreen::handleScreenChanged()
+{    
+    reportAllWindowGeometry();
+}
+
+void QOhPlatformScreen::reportAllWindowGeometry()
+{
+    auto allWindows = QOhWindowContext::allWindows();
+    for (auto *window : allWindows) {
+        if (QOhPlatformOpenGLWindow *w = dynamic_cast<QOhPlatformOpenGLWindow*>(window);
+            window->isTopLevelWindow() && w && w->nativeWindow()) {
+            /* 修改系统显示大小后最小化的窗口也需要处理geomtry变化,否则显示内容异常 */
+            if (w->screen() != this/* || Qt::WindowMinimized & w->windowStates()*/)
+                continue;
+            w->nativeWindow()->reportWindowGeometry();
+        }
+    }
+}
+
+QSizeF QOhPlatformScreen::px2mm(const QSize &size)
+{
+#if OHOS_SDK_VERSION > 13
+    qreal xdpi = m_display->xDPI();
+    qreal ydpi = m_display->yDPI();
+#else
+    qreal xdpi = m_jsScreen->xDPI();
+    qreal ydpi = m_jsScreen->yDPI();
+#endif
+    return QSizeF(size.width() * 25.4 / xdpi, size.height() * 25.4 / ydpi);
+}
+
+void QOhPlatformScreen::setAvailableGeometry(const QRect &rect)
+{
+    if (m_availableGeometry == rect)
+        return;
+
+    QRect oldGeometry = m_availableGeometry;
+    m_availableGeometry = rect;
+    QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
+    // TODO 确定系统释放自动调整窗口大小
+    /* FIXME wanghao 折叠设备最大化到B、C面后,再次进入折叠态显示异常 */
+    //resizeMaximizedWindows();
+
+    if (oldGeometry.width() == 0 && oldGeometry.height() == 0 && rect.width() > 0 && rect.height() > 0) {
+        const auto allWindows = qGuiApp->allWindows();
+        for (auto *window : allWindows) {
+            if (window->handle()) {
+                QRect geometry = window->handle()->geometry();
+                if (geometry.width() > 0 && geometry.height() > 0)
+                    QWindowSystemInterface::handleExposeEvent(window, QRect(QPoint(0, 0), geometry.size()));
+            }
+        }
+    }
+}
+
+static const int openharmonyLogicalDpi = 96;
+
+QDpi QOhPlatformScreen::logicalDpi() const
+{
+#if OHOS_SDK_VERSION > 13
+    qreal lDpi = m_display->scaledDensity() * openharmonyLogicalDpi;
+#else
+    qreal lDpi = m_jsScreen->scaledDensity() * openharmonyLogicalDpi;
+#endif
+    return QDpi(lDpi, lDpi);
+}
+
+QDpi QOhPlatformScreen::logicalBaseDpi() const
+{
+    return QDpi(openharmonyLogicalDpi, openharmonyLogicalDpi);
+}
+
+qreal QOhPlatformScreen::densityPixels() const
+{
+#if OHOS_SDK_VERSION > 13
+    return m_display->densityPixels();
+#else
+    return m_jsScreen->densityPixels();
+#endif
+}
+
+Qt::ScreenOrientation QOhPlatformScreen::orientation() const
+{
+#if OHOS_SDK_VERSION > 13
+    return m_display->orientation();
+#else
+    return m_jsScreen->orientation();
+#endif
+}
+
+Qt::ScreenOrientation QOhPlatformScreen::nativeOrientation() const
+{
+    return Qt::LandscapeOrientation;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohplatformscreen.h b/src/plugins/platforms/openharmony/qohplatformscreen.h
new file mode 100644
index 00000000000..bca7b89bada
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformscreen.h
@@ -0,0 +1,80 @@
+#ifndef QOHPLATFORMSCREEN_H
+#define QOHPLATFORMSCREEN_H
+
+#include <qpa/qplatformscreen.h>
+#include <native_window/external_window.h>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+
+class QOhPlatformWindow;
+#if OHOS_SDK_VERSION > 13
+class QOhDisplay;
+#else
+class QJsScreen;
+#endif
+
+class QOhPlatformScreen: public QPlatformScreen
+{
+public:
+#if OHOS_SDK_VERSION > 13
+    QOhPlatformScreen(QOhDisplay *display);
+#else
+    QOhPlatformScreen(QJsScreen *jsScreen);
+#endif
+    ~QOhPlatformScreen();
+
+#if OHOS_SDK_VERSION > 13
+    QOhDisplay *display() const;
+#endif
+
+    QString name() const override;
+    QRect geometry() const override;
+    QRect availableGeometry() const override;
+    int depth() const override { return m_depth; }
+    QImage::Format format() const override { return m_format; }
+    QSizeF physicalSize() const override { return m_physicalSize; }
+    qreal refreshRate() const override { return m_refreshRate; }
+    QDpi logicalDpi() const override;
+    QDpi logicalBaseDpi() const override;
+    qreal densityPixels() const;
+    Qt::ScreenOrientation orientation() const override;
+    Qt::ScreenOrientation nativeOrientation() const override;
+
+    QWindow *topLevelAt(const QPoint & p) const override;
+    QPixmap grabWindow(WId window, int xIn, int yIn, int width, int height) const override;
+
+    QList<QPlatformScreen *> virtualSiblings() const override;
+
+    using CursorPtr = QScopedPointer<QPlatformCursor>;
+    QPlatformCursor *cursor() const override { return m_cursor.data(); }
+
+    uint32_t displayId();
+    void setPhysicalSize(const QSize &size);
+    void setAvailableGeometry(const QRect &rect);
+    void setSize(const QSize &size);
+    void handleScreenLogicalDotsPerInchChange();
+    void handleScreenOrientationChange();
+    void handlerefreshRateChange(int refreshRate);
+    void handleScreenChanged();
+    void reportAllWindowGeometry();
+    friend QDebug &operator<<(QDebug &outputStream, QOhPlatformScreen *platformScreen);
+
+private:
+    QSizeF px2mm(const QSize &size);    
+    QRect m_availableGeometry;
+    int m_depth;
+    QImage::Format m_format;
+    QSizeF m_physicalSize;
+    int m_refreshRate;
+
+    const CursorPtr m_cursor;
+#if OHOS_SDK_VERSION > 13
+    QOhDisplay *m_display;
+#else
+    QJsScreen *m_jsScreen;
+#endif
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/plugins/platforms/openharmony/qohplatformservices.cpp b/src/plugins/platforms/openharmony/qohplatformservices.cpp
new file mode 100644
index 00000000000..ef26bead5ba
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformservices.cpp
@@ -0,0 +1,121 @@
+#include "qohplatformservices.h"
+#include "qohnativewindowmanager.h"
+#include "qjscontext.h"
+#include "qopenharmony.h"
+#include <private/qopenharmony_p.h>
+
+#include <QUrl>
+#include <QThread>
+#include <QFileInfo>
+#include <QDebug>
+#include <QtCore/qopenharmonydefines.h>
+
+QT_BEGIN_NAMESPACE
+
+bool QOhPlatformServices::openUrl(const QUrl &url)
+{
+    QString urlOrPath = url.toString(QUrl::FullyEncoded);
+    if (urlOrPath.startsWith("/")) {
+        // 以"/"开头的判断为本地文件
+        return openDocument(QUrl::fromLocalFile(urlOrPath));
+    }
+    QLatin1String scheme("https");
+    QUrl theUrl;
+    if (url.scheme().isEmpty()) {
+        theUrl.setScheme(scheme);
+        theUrl.setHost(urlOrPath);
+    } else {
+        theUrl = url;
+    }
+
+    QJsContext *context = qNativeWindowManager->context();
+    if (context == nullptr)
+        return false;
+    QtOh::runOnJsUIThreadAndWait([=]{
+        Napi::Object jsWant = Napi::Object::New(QtOh::uiEnv());
+
+        jsWant.Set("uri", theUrl.toString(QUrl::FullyEncoded).toStdString());
+        jsWant.Set("action", QString("ohos.want.action.viewData").toStdString());
+
+        Napi::Function callback = Napi::Function::New(jsWant.Env(), [](const Napi::CallbackInfo& info) {
+            if (info.Length() < 1) {
+                LOGW("startAbility failed, error unkonwn");
+                return;
+            }
+            Napi::Object error = info[0].As<Napi::Object>();
+            int code = (int)error.Get("code").ToNumber();
+            if (code != 0)
+                LOGW("startAbility failed, code is %{public}d, message is %{public}s", code, error.Get("message").ToString().Utf8Value().c_str());
+        });
+        context->startAbility(jsWant, callback);
+    });
+    return true;
+}
+
+#define FLAG_AUTH_READ_URI_PERMISSION 0x00000001
+#define FLAG_AUTH_WRITE_URI_PERMISSION 0x00000002
+bool QOhPlatformServices::openDocument(const QUrl &url)
+{
+    QJsContext *context = qNativeWindowManager->context();
+    if (context == nullptr)
+        return false;
+
+    QtOh::runOnJsUIThreadAndWait([=]{
+        QFileInfo info(url.toLocalFile());
+        bool isDir = info.isDir();
+        QString path = info.absoluteFilePath();
+        QString data = QtOh::uriFromPath(path);
+        if (data.isEmpty())
+            return;
+        Napi::Object jsWant = Napi::Object::New(QtOh::uiEnv());
+        if (isDir) {
+            jsWant.Set("abilityName", QString("MainAbility").toStdString());
+            jsWant.Set("bundleName", QString("com.huawei.hmos.filemanager").toStdString());
+            Napi::Object parameters = Napi::Object::New(jsWant.Env());
+            parameters.Set("fileUri", data.toStdString());
+            jsWant.Set("parameters", parameters);
+        } else {
+            jsWant.Set("action", QString("ohos.want.action.viewData").toStdString());
+            jsWant.Set("uri", data.toStdString());
+            // 给打开的应用对uri授权
+            jsWant.Set("flags", FLAG_AUTH_READ_URI_PERMISSION);
+        }
+        context->startAbility(jsWant);
+    });
+    return true;
+}
+
+bool QOhPlatformServices::openUri(const QUrl &url, bool isDir)
+{
+    QJsContext *context = qNativeWindowManager->context();
+    if (context == nullptr)
+        return false;
+
+    QtOh::runOnJsUIThreadAndWait([=]{
+        QString path = url.toString();
+        const char *cpath = path.toLocal8Bit().constData();
+        Napi::Object jsWant = Napi::Object::New(QtOh::uiEnv());
+        if (isDir) {
+            jsWant.Set("abilityName", QString("MainAbility").toStdString());
+            jsWant.Set("bundleName", QString("com.huawei.hmos.filemanager").toStdString());
+            Napi::Object parameters = Napi::Object::New(jsWant.Env());
+            parameters.Set("fileUri", cpath);
+            jsWant.Set("parameters", parameters);
+        } else {
+            jsWant.Set("action", QString("ohos.want.action.viewData").toStdString());
+            jsWant.Set("uri", cpath);
+            // 给打开的应用对uri授权
+            jsWant.Set("flags", FLAG_AUTH_READ_URI_PERMISSION);
+        }
+        context->startAbility(jsWant);
+    });
+    return true;
+}
+
+//TODO
+QByteArray QOhPlatformServices::desktopEnvironment() const
+{
+    return QByteArray();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohplatformservices.h b/src/plugins/platforms/openharmony/qohplatformservices.h
new file mode 100644
index 00000000000..a363f3c4538
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformservices.h
@@ -0,0 +1,21 @@
+#ifndef QOHPLATFORMSERVICES_H
+#define QOHPLATFORMSERVICES_H
+
+#include <qpa/qplatformservices.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class QOhPlatformServices : public QPlatformServices
+{
+public:
+    bool openUrl(const QUrl &url) override;
+    bool openDocument(const QUrl &url) override;
+    bool openUri(const QUrl &url, bool isDir) override;
+    QByteArray desktopEnvironment() const override;
+};
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/openharmony/qohplatformtheme.cpp b/src/plugins/platforms/openharmony/qohplatformtheme.cpp
new file mode 100644
index 00000000000..a00d73f7c9e
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformtheme.cpp
@@ -0,0 +1,1484 @@
+#include <qcolor.h>
+#include <qpalette.h>
+#include <QCoreApplication>
+#include <QLoggingCategory>
+#include <QtCore/qjsmodule.h>
+#include <private/qopenharmony_p.h>
+#include <QtGui/private/qpainter_p.h>
+#include <qpa/qplatformintegration.h>
+#include <private/qguiapplication_p.h>
+#include <private/qohfontdatabase_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
+#include <QtGui/private/qabstractfileiconengine_p.h>
+
+#include <multimedia/image_framework/image/image_source_native.h>
+#include <multimedia/image_framework/image/pixelmap_native.h>
+#include <arkui/drawable_descriptor.h>
+#include <resourcemanager/ohresmgr.h>
+#include <resourcemanager/resmgr_common.h>
+#include "syscap_ndk.h"
+
+#include "qohauxiliary.h"
+#include "qohwindownode.h"
+#include "qohobjectholder.h"
+#include "qohplatformmenu.h"
+#include "qohplatformtheme.h"
+#include "qohsystemtrayicon.h"
+#include "qohnativewindowmanager.h"
+#include "qohplatformopenglwindow.h"
+#include "qohplatformdialoghelpers.h"
+
+Q_LOGGING_CATEGORY(ohosthem, "openharmony.theme");
+
+namespace {
+
+QFont makeMenuFont()
+{
+    auto font = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFont();
+    font.setPointSize(16);
+
+    return font;
+}
+
+QFont makeTitleFont()
+{
+    auto font = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFont();
+    font.setPointSize(20);
+    font.setBold(true);
+
+    return font;
+}
+
+QFont makePushButtonFont()
+{
+    auto font = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFont();
+    font.setPointSize(16);
+
+    return font;
+}
+
+QFont makeListViewFont()
+{
+    auto font = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFont();
+    font.setPointSize(16);
+
+    return font;
+}
+
+QFont makeTipLabelFont()
+{
+    auto font = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFont();
+    font.setPointSize(14);
+
+    return font;
+}
+
+QColor makeInactiveOrDisabledFromColor(const QColor &color)
+{
+    auto disabledColor = color;
+    disabledColor.setAlphaF(qBound(0.0, color.alphaF() * 0.4, 1.0));
+
+    return disabledColor;
+}
+
+class QAbstractTheme
+{
+public:
+    struct PalettesColors
+    {
+        QColor activeWindow;
+        QColor inactiveWindow;
+        QColor activeButtonText;
+        QColor inactiveButtonText;
+        QColor activeHighlight;
+        QColor inactiveHighlight;
+        QColor clickEffect;
+        QColor hover;
+        QColor foregroundContrary;
+        QColor highlighted;
+        QColor inactiveHighlighted;
+        QColor textPrimary;
+        QColor inactiveTextPrimary;
+        QColor inactiveText;
+        QColor componentNormal;
+        QColor componentActivated;
+        QColor indicatorArrow;
+        QColor scrollBarSlider;
+        QColor switchBgOff;
+        QColor switchOutlineOff;
+        QColor window;
+    };
+
+    struct SystemPaletteColors
+    {
+        QColor activeWindowFrame;
+        QColor inactiveWindowFrame;
+        QColor textHint;
+        QColor textTertiary;
+    };
+
+    struct MenuPaletteColors
+    {
+        QColor listSeparator;
+        QColor inactiveText;
+    };
+
+    struct HeaderPaletteColors
+    {
+        QColor activeButton;
+    };
+
+    struct TabBarPaletteColors
+    {
+        QColor activeWindowText;
+        QColor inactiveWindowText;
+        QColor disabledWindowText;
+    };
+
+    struct ButtonPaletteColors
+    {
+        QColor activeButton;
+        QColor inactiveButton;
+        QColor focusedOutline;
+        QColor enabledDefaultButtonText;
+    };
+
+    struct ToolButtonPaletteColors
+    {
+        QColor windowButtonBackground;
+    };
+
+    struct TextLineEditPaletteColors
+    {
+        QColor textEditBackground;
+        QColor inactiveTextEditBackground;
+    };
+
+    struct GroupboxPaletteColors
+    {
+        QColor background;
+        QColor groupBoxFrame;
+        QColor shadowXS;
+    };
+
+    struct TooltipPaletteColors
+    {
+        QColor toolTipBorder;
+        QColor toolTipBase;
+    };
+
+
+    struct AllPalletesColors
+    {
+        PalettesColors palettes;
+        ButtonPaletteColors button;
+        ToolButtonPaletteColors toolButton;
+        SystemPaletteColors system;
+        MenuPaletteColors menu;
+        TabBarPaletteColors tabBar;
+        TextLineEditPaletteColors textLineEdit;
+        GroupboxPaletteColors groupBox;
+        HeaderPaletteColors header;
+        TooltipPaletteColors toolTip;
+    };
+
+    using ThemeFonts = QHash<QPlatformTheme::Font, QFont>;
+    using ThemePalettes = QHash<QPlatformTheme::Palette, QPalette>;
+
+    explicit QAbstractTheme(ThemeFonts f, ThemePalettes p);
+    virtual ~QAbstractTheme();
+
+    virtual const QFont *font(QPlatformTheme::Font type) const;
+    virtual const QPalette *palette(QPlatformTheme::Palette type) const;
+
+protected:
+    static QPalette makeMenuPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeLabelPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeTabBarPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeButtonPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeSystemPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeHeaderPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeToolTipPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeTextEditPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeItemViewPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeComboBoxPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeGroupBoxPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeToolButtonPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeTextLineEditPalette(const AllPalletesColors &palettesColors);
+    static QPalette makeCheckBoxOrRadioButtonPalette(const AllPalletesColors &palettesColors);
+
+    static QPalette makePalette(
+            const QPalette &basePalette, std::initializer_list<std::tuple<QPalette::ColorGroup, QPalette::ColorRole, const QColor &>> brushEntries);
+
+    static QPalette makePalette(std::initializer_list<std::tuple<QPalette::ColorGroup, QPalette::ColorRole, const QColor &>> brushEntries);
+
+
+private:
+    ThemeFonts m_fonts;
+    ThemePalettes m_themesPalettes;
+};
+
+QAbstractTheme::QAbstractTheme(ThemeFonts f, ThemePalettes p)
+    : m_fonts(f)
+    , m_themesPalettes(p)
+{
+
+}
+
+QAbstractTheme::~QAbstractTheme()
+{
+    m_fonts.clear();
+    m_themesPalettes.clear();
+}
+
+const QFont *QAbstractTheme::font(QPlatformTheme::Font type) const
+{
+    const auto fontIter = m_fonts.find(type);
+    return fontIter != m_fonts.end()
+            ? &fontIter.value()
+            : nullptr;
+}
+
+const QPalette *QAbstractTheme::palette(QPlatformTheme::Palette type) const
+{
+    const auto it = m_themesPalettes.find(type);
+    if (it != m_themesPalettes.end()) {
+        return &it.value();
+    }
+    return nullptr;
+}
+
+QPalette QAbstractTheme::makeMenuPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            {
+                    {QPalette::Active, QPalette::Window, palettesColors.palettes.activeWindow},
+                    {QPalette::Inactive, QPalette::Base, palettesColors.palettes.switchBgOff},
+                    {QPalette::Inactive, QPalette::Button, palettesColors.palettes.switchOutlineOff},
+                    {QPalette::Active, QPalette::Button, palettesColors.palettes.highlighted},
+
+                    {QPalette::Active, QPalette::Text, palettesColors.palettes.textPrimary},
+                    {QPalette::Disabled, QPalette::Text, palettesColors.menu.inactiveText},
+                    {QPalette::Inactive, QPalette::Text, palettesColors.menu.inactiveText},
+
+                    {QPalette::Active, QPalette::Light, palettesColors.palettes.hover},
+                    {QPalette::Active, QPalette::Dark, palettesColors.palettes.clickEffect},
+
+                    {QPalette::Active, QPalette::Mid, palettesColors.menu.listSeparator}
+            });
+}
+
+QPalette QAbstractTheme::makeLabelPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            {
+              {QPalette::Active, QPalette::WindowText, palettesColors.palettes.highlighted},
+              {QPalette::Inactive, QPalette::WindowText, palettesColors.palettes.inactiveText},
+              {QPalette::Disabled, QPalette::WindowText, palettesColors.palettes.inactiveHighlighted},
+
+              {QPalette::Active, QPalette::Text, palettesColors.palettes.highlighted},
+              {QPalette::Disabled, QPalette::Text, palettesColors.palettes.inactiveText},
+              {QPalette::Inactive, QPalette::Text, palettesColors.palettes.inactiveHighlighted},
+              });
+}
+
+QPalette QAbstractTheme::makeTabBarPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            {
+              {QPalette::Active, QPalette::WindowText, palettesColors.tabBar.activeWindowText},
+              {QPalette::Inactive, QPalette::WindowText, palettesColors.tabBar.inactiveWindowText},
+              {QPalette::Disabled, QPalette::WindowText, palettesColors.tabBar.disabledWindowText},
+
+              {QPalette::Active, QPalette::Window, palettesColors.palettes.activeWindow},
+              {QPalette::Inactive, QPalette::Window, palettesColors.palettes.inactiveWindow},
+              {QPalette::Disabled, QPalette::Window, palettesColors.palettes.inactiveWindow},
+
+              {QPalette::Active, QPalette::Highlight, palettesColors.palettes.activeHighlight},
+              {QPalette::Inactive, QPalette::Highlight, palettesColors.palettes.inactiveHighlight},
+              {QPalette::Disabled, QPalette::Highlight, palettesColors.palettes.inactiveHighlight},
+              });
+}
+
+QPalette QAbstractTheme::makeButtonPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            {
+                    {QPalette::Active, QPalette::AlternateBase, palettesColors.palettes.componentActivated},
+
+                    {QPalette::Active, QPalette::Button, palettesColors.button.activeButton},
+                    {QPalette::Disabled, QPalette::Button, palettesColors.button.inactiveButton},
+                    {QPalette::Inactive, QPalette::Button, palettesColors.button.inactiveButton},
+
+                    {QPalette::Active, QPalette::ButtonText, palettesColors.palettes.activeButtonText},
+                    {QPalette::Disabled, QPalette::ButtonText, palettesColors.palettes.inactiveButtonText},
+                    {QPalette::Inactive, QPalette::ButtonText, palettesColors.palettes.inactiveButtonText},
+
+                    {QPalette::All, QPalette::BrightText, palettesColors.button.enabledDefaultButtonText},
+
+                    {QPalette::Active, QPalette::Light, palettesColors.palettes.hover},
+                    {QPalette::Active, QPalette::Dark, palettesColors.palettes.clickEffect},
+
+                    {QPalette::Active, QPalette::Highlight, palettesColors.button.focusedOutline},
+                    {QPalette::Active, QPalette::WindowText, palettesColors.palettes.indicatorArrow}
+            });
+}
+
+QPalette QAbstractTheme::makeSystemPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            {
+              {QPalette::Active, QPalette::Window, palettesColors.palettes.activeWindow},
+              {QPalette::Disabled, QPalette::Window, palettesColors.palettes.inactiveWindow},
+              {QPalette::Inactive, QPalette::Window, palettesColors.palettes.inactiveWindow},
+
+              {QPalette::Active, QPalette::WindowText, palettesColors.palettes.highlighted},
+              {QPalette::Disabled, QPalette::WindowText, palettesColors.palettes.inactiveText},
+              {QPalette::Inactive, QPalette::WindowText, palettesColors.palettes.inactiveHighlighted},
+
+              {QPalette::Active, QPalette::Text, palettesColors.palettes.highlighted},
+              {QPalette::Disabled, QPalette::Text, palettesColors.palettes.inactiveText},
+              {QPalette::Inactive, QPalette::Text, palettesColors.palettes.inactiveHighlighted},
+
+              {QPalette::Active, QPalette::Base, palettesColors.system.activeWindowFrame},
+              {QPalette::Disabled, QPalette::Base, palettesColors.system.inactiveWindowFrame},
+              {QPalette::Inactive, QPalette::Base, palettesColors.system.inactiveWindowFrame},
+
+              {QPalette::Active, QPalette::AlternateBase, palettesColors.palettes.textPrimary},
+
+              {QPalette::Active, QPalette::Highlight, palettesColors.palettes.highlighted},
+
+              {QPalette::All, QPalette::PlaceholderText, palettesColors.system.textHint},
+              {QPalette::Disabled, QPalette::PlaceholderText, palettesColors.system.textTertiary},
+
+              {QPalette::Active, QPalette::Midlight, palettesColors.palettes.scrollBarSlider},
+
+              {QPalette::Active, QPalette::Mid, palettesColors.palettes.componentNormal},
+              });
+}
+
+
+QPalette QAbstractTheme::makeHeaderPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            {
+              {QPalette::Active, QPalette::Button, palettesColors.header.activeButton},
+              {QPalette::Inactive, QPalette::Button, palettesColors.header.activeButton},
+              {QPalette::Disabled, QPalette::Button, palettesColors.palettes.inactiveWindow},
+
+              {QPalette::Current, QPalette::ButtonText, palettesColors.palettes.activeButtonText},
+              {QPalette::Active, QPalette::ButtonText, palettesColors.palettes.activeButtonText},
+              {QPalette::Inactive, QPalette::ButtonText, palettesColors.palettes.activeButtonText},
+              {QPalette::Disabled, QPalette::ButtonText, palettesColors.palettes.inactiveButtonText},
+              });
+}
+
+QPalette QAbstractTheme::makeToolTipPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            {
+              {QPalette::All, QPalette::Base, palettesColors.toolTip.toolTipBorder},
+              {QPalette::All, QPalette::ToolTipBase, palettesColors.toolTip.toolTipBase},
+              {QPalette::All, QPalette::ToolTipText, palettesColors.palettes.highlighted},
+              });
+}
+
+QPalette QAbstractTheme::makeTextEditPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            makeTextLineEditPalette(palettesColors),
+            {
+              {QPalette::All, QPalette::Base, palettesColors.palettes.activeWindow},
+              });
+}
+
+QPalette QAbstractTheme::makeItemViewPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            {
+              {QPalette::Active, QPalette::Base, palettesColors.palettes.window},
+              {QPalette::Inactive, QPalette::Base, palettesColors.palettes.window},
+              {QPalette::Disabled, QPalette::Base, palettesColors.palettes.window},
+
+              {QPalette::Active, QPalette::AlternateBase, palettesColors.palettes.activeWindow},
+              {QPalette::Inactive, QPalette::AlternateBase, palettesColors.palettes.activeWindow},
+              {QPalette::Disabled, QPalette::AlternateBase, palettesColors.palettes.inactiveWindow},
+              {QPalette::Current, QPalette::AlternateBase, palettesColors.palettes.activeWindow},
+
+              {QPalette::Active, QPalette::Highlight, palettesColors.palettes.activeHighlight},
+              {QPalette::Inactive, QPalette::Highlight, palettesColors.palettes.activeHighlight},
+              {QPalette::Disabled, QPalette::Highlight, palettesColors.palettes.inactiveHighlight},
+
+              {QPalette::Active, QPalette::Window, palettesColors.palettes.activeWindow},
+              {QPalette::Inactive, QPalette::Window, palettesColors.palettes.activeWindow},
+              {QPalette::Disabled, QPalette::Window, palettesColors.palettes.inactiveWindow},
+
+              {QPalette::Active, QPalette::Text, palettesColors.palettes.activeHighlight},
+              {QPalette::Inactive, QPalette::Text, palettesColors.palettes.activeHighlight},
+              {QPalette::Disabled, QPalette::Text, palettesColors.palettes.inactiveHighlight},
+
+              {QPalette::Active, QPalette::HighlightedText, palettesColors.palettes.activeWindow},
+              {QPalette::Inactive, QPalette::HighlightedText, palettesColors.palettes.activeWindow},
+              {QPalette::Disabled, QPalette::HighlightedText, palettesColors.palettes.inactiveWindow},
+
+              {QPalette::Active, QPalette::Dark, palettesColors.palettes.activeWindow},
+              {QPalette::Inactive, QPalette::Dark, palettesColors.palettes.activeWindow},
+              {QPalette::Disabled, QPalette::Dark, palettesColors.palettes.inactiveWindow},
+              {QPalette::Current, QPalette::Dark, palettesColors.palettes.activeWindow},
+              {QPalette::All, QPalette::Dark, palettesColors.palettes.activeWindow},
+
+              {QPalette::Active, QPalette::Light, palettesColors.palettes.hover},
+              {QPalette::Inactive, QPalette::Light, palettesColors.palettes.activeWindow},
+              {QPalette::Disabled, QPalette::Light, palettesColors.palettes.inactiveWindow},
+
+              {QPalette::Active, QPalette::Mid, palettesColors.palettes.activeWindow},
+              {QPalette::Inactive, QPalette::Mid, palettesColors.palettes.activeWindow},
+              {QPalette::Disabled, QPalette::Mid, palettesColors.palettes.inactiveWindow},
+              {QPalette::Current, QPalette::Mid, palettesColors.palettes.activeWindow},
+              {QPalette::All, QPalette::Mid, palettesColors.palettes.activeWindow},
+              });
+}
+
+QPalette QAbstractTheme::makeComboBoxPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            {
+                    {QPalette::Active, QPalette::AlternateBase, palettesColors.palettes.componentActivated},
+                    {QPalette::All, QPalette::Base, palettesColors.palettes.window},
+                    {QPalette::All, QPalette::Window, palettesColors.palettes.window},
+                    {QPalette::Active, QPalette::Text, palettesColors.palettes.highlighted},
+                    {QPalette::Disabled, QPalette::Text, palettesColors.palettes.inactiveText},
+                    {QPalette::Inactive, QPalette::Text, palettesColors.palettes.inactiveHighlighted},
+                    {QPalette::Active, QPalette::Light, palettesColors.palettes.hover},
+                    {QPalette::Active, QPalette::Dark, palettesColors.palettes.clickEffect},
+                    {QPalette::Active, QPalette::WindowText, palettesColors.palettes.indicatorArrow}
+            });
+}
+
+QPalette QAbstractTheme::makeGroupBoxPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            {
+                    {QPalette::Active, QPalette::Button, palettesColors.palettes.highlighted},
+                    {QPalette::Inactive, QPalette::Button, palettesColors.palettes.switchOutlineOff},
+                    {QPalette::Active, QPalette::Base, palettesColors.groupBox.groupBoxFrame},
+                    {QPalette::Inactive, QPalette::Base, palettesColors.palettes.switchBgOff},
+                    {QPalette::Active, QPalette::AlternateBase, palettesColors.palettes.foregroundContrary},
+//                    {QPalette::Active, QPalette::Background, palettesColors.groupBox.background},
+//                    {QPalette::Inactive, QPalette::Background, palettesColors.groupBox.background},
+                    {QPalette::Active, QPalette::Window, palettesColors.palettes.window},
+                    {QPalette::Disabled, QPalette::Window, palettesColors.palettes.window},
+                    {QPalette::Active, QPalette::Text, palettesColors.palettes.highlighted},
+                    {QPalette::Inactive, QPalette::Text, palettesColors.palettes.highlighted},
+                    {QPalette::Disabled, QPalette::Text, palettesColors.palettes.inactiveHighlighted},
+                    {QPalette::Current, QPalette::Text, palettesColors.palettes.highlighted},
+                    {QPalette::Disabled, QPalette::WindowText, palettesColors.palettes.inactiveHighlighted},
+                    {QPalette::Active, QPalette::ButtonText, palettesColors.palettes.textPrimary},
+                    {QPalette::Disabled, QPalette::ButtonText, palettesColors.palettes.inactiveHighlighted},
+                    {QPalette::Active, QPalette::Dark, palettesColors.palettes.clickEffect},
+                    {QPalette::Active, QPalette::Light, palettesColors.palettes.hover},
+                    {QPalette::Active, QPalette::Shadow, palettesColors.groupBox.shadowXS},
+                    {QPalette::Active, QPalette::Midlight, palettesColors.palettes.scrollBarSlider},
+                    {QPalette::Active, QPalette::Mid, palettesColors.palettes.componentNormal}
+            });
+}
+
+QPalette QAbstractTheme::makeToolButtonPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            makeButtonPalette(palettesColors),
+            {
+              {QPalette::Active, QPalette::AlternateBase, palettesColors.toolButton.windowButtonBackground},
+              });
+}
+
+QPalette QAbstractTheme::makeTextLineEditPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            makeSystemPalette(palettesColors),
+            {
+              {QPalette::Active, QPalette::AlternateBase, palettesColors.palettes.componentActivated},
+              {QPalette::All, QPalette::Base, palettesColors.textLineEdit.textEditBackground},
+              {QPalette::Disabled, QPalette::Base, palettesColors.textLineEdit.inactiveTextEditBackground},
+              {QPalette::All, QPalette::Text, palettesColors.palettes.textPrimary},
+              {QPalette::Disabled, QPalette::Text, palettesColors.palettes.inactiveTextPrimary},
+              });
+}
+
+QPalette QAbstractTheme::makeCheckBoxOrRadioButtonPalette(const AllPalletesColors &palettesColors)
+{
+    return makePalette(
+            {
+              {QPalette::Inactive, QPalette::Base, palettesColors.palettes.switchBgOff},
+              {QPalette::Inactive, QPalette::Button, palettesColors.palettes.switchOutlineOff},
+              {QPalette::Active, QPalette::Button, palettesColors.palettes.highlighted},
+              {QPalette::Active, QPalette::WindowText, palettesColors.palettes.highlighted},
+              {QPalette::Inactive, QPalette::WindowText, palettesColors.palettes.inactiveText},
+              {QPalette::Disabled, QPalette::WindowText, palettesColors.palettes.inactiveHighlighted},
+              {QPalette::Active, QPalette::Light, palettesColors.palettes.hover},
+              {QPalette::Active, QPalette::Dark, palettesColors.palettes.clickEffect},
+              });
+}
+
+QPalette QAbstractTheme::makePalette(const QPalette &basePalette, std::initializer_list<std::tuple<QPalette::ColorGroup, QPalette::ColorRole, const QColor &> > brushEntries)
+{
+    auto palette = basePalette;
+
+    for (const auto &brushEntry : brushEntries) {
+        palette.setBrush(
+                std::get<QPalette::ColorGroup>(brushEntry),
+                std::get<QPalette::ColorRole>(brushEntry),
+                std::get<const QColor &>(brushEntry));
+    }
+    return palette;
+}
+
+QPalette QAbstractTheme::makePalette(std::initializer_list<std::tuple<QPalette::ColorGroup, QPalette::ColorRole, const QColor &> > brushEntries)
+{
+    return makePalette(QPalette(), brushEntries);
+}
+
+class QOhDarkTheme : public QAbstractTheme
+{
+public:
+    explicit QOhDarkTheme();
+    ~QOhDarkTheme();
+
+private:
+    static PalettesColors makePalettesColorsDark();
+    static AllPalletesColors makeAllPalettesColorsDark();
+    static ButtonPaletteColors makeButtonPaletteColorsDark();
+    static TabBarPaletteColors makeTabBarPaletteColorsDark();
+    static HeaderPaletteColors makeHeaderPaletteColorsDark();
+    static TooltipPaletteColors makeTooltipPaletteColorsDark();
+    static GroupboxPaletteColors makeGroupboxPaletteColorsDark();
+    static SystemPaletteColors makeSystemButtonPaletteColorsDark();
+    static ToolButtonPaletteColors makeToolButtonPaletteColorsDark();
+    static TextLineEditPaletteColors makeTextLineEditPaletteColorsDark();
+    static MenuPaletteColors makeMenuPaletteColorsDark(const PalettesColors &palettes);
+};
+
+QOhDarkTheme::QOhDarkTheme() : QAbstractTheme({
+                       {QPlatformTheme::MenuFont, makeMenuFont()},
+                       {QPlatformTheme::MenuBarFont, makeMenuFont()},
+                       {QPlatformTheme::MenuItemFont, makeMenuFont()},
+                       {QPlatformTheme::TipLabelFont, makeTipLabelFont()},
+                       {QPlatformTheme::ListViewFont, makeListViewFont()},
+                       {QPlatformTheme::GroupBoxTitleFont, makeTitleFont()},
+                       {QPlatformTheme::DockWidgetTitleFont, makeTitleFont()},
+                       {QPlatformTheme::PushButtonFont, makePushButtonFont()},
+                       }, {
+                             []()->ThemePalettes {
+                                 const AllPalletesColors palettesColors = makeAllPalettesColorsDark();
+                                 return {
+                                          {QPlatformTheme::ButtonPalette, makeButtonPalette(palettesColors)},
+                                          {QPlatformTheme::CheckBoxPalette, makeCheckBoxOrRadioButtonPalette(palettesColors)},
+                                          {QPlatformTheme::ComboBoxPalette, makeComboBoxPalette(palettesColors)},
+                                          {QPlatformTheme::GroupBoxPalette, makeGroupBoxPalette(palettesColors)},
+                                          {QPlatformTheme::HeaderPalette, makeHeaderPalette(palettesColors)},
+                                          {QPlatformTheme::ItemViewPalette, makeItemViewPalette(palettesColors)},
+                                          {QPlatformTheme::LabelPalette, makeLabelPalette(palettesColors)},
+                                          {QPlatformTheme::MenuPalette, makeMenuPalette(palettesColors)},
+                                          {QPlatformTheme::RadioButtonPalette, makeCheckBoxOrRadioButtonPalette(palettesColors)},
+                                          {QPlatformTheme::SystemPalette, makeSystemPalette(palettesColors)},
+                                          {QPlatformTheme::TabBarPalette, makeTabBarPalette(palettesColors)},
+                                          {QPlatformTheme::TextEditPalette, makeTextEditPalette(palettesColors)},
+                                          {QPlatformTheme::TextLineEditPalette, makeTextLineEditPalette(palettesColors)},
+                                          {QPlatformTheme::ToolButtonPalette, makeToolButtonPalette(palettesColors)},
+                                          {QPlatformTheme::ToolTipPalette, makeToolTipPalette(palettesColors)},
+                                          };
+                             }()
+                     })
+{
+
+}
+
+QOhDarkTheme::~QOhDarkTheme()
+{
+
+}
+
+QAbstractTheme::PalettesColors QOhDarkTheme::makePalettesColorsDark()
+{
+    const auto activeWindow = QColor("#18181A");
+    const auto activeButtonText = QColor("#3F97E9");
+    const auto activeHighlight = QColor("#006CDE");
+    const auto highlighted = QColor("#3F97E9");
+    const auto textPrimary = QColor("#DBFFFFFF");
+
+    return {
+        .activeWindow = activeWindow,
+        .inactiveWindow = makeInactiveOrDisabledFromColor(activeWindow),
+        .activeButtonText = activeButtonText,
+        .inactiveButtonText = makeInactiveOrDisabledFromColor(activeButtonText),
+        .activeHighlight = activeHighlight,
+        .inactiveHighlight = makeInactiveOrDisabledFromColor(activeHighlight),
+        .clickEffect = QColor("#26FFFFFF"),
+        .hover = QColor("#19FFFFFF"),
+        .foregroundContrary = QColor("#E5E5E5"),
+        .highlighted = highlighted,
+        .inactiveHighlighted = makeInactiveOrDisabledFromColor(highlighted),
+        .textPrimary = textPrimary,
+        .inactiveTextPrimary = makeInactiveOrDisabledFromColor(textPrimary),
+        .inactiveText = QColor("#E6FFFFFF"),
+        .componentNormal = QColor("#19FFFFFF"),
+        .componentActivated = QColor("#3F97E9"),
+        .indicatorArrow = QColor("#DBFFFFFF"),
+        .scrollBarSlider = QColor("#FFFFFF"),
+        .switchBgOff = QColor("#33000000"),
+        .switchOutlineOff = QColor("#66FFFFFF"),
+        .window = QColor("#FF000000"),
+    };
+}
+
+QAbstractTheme::AllPalletesColors QOhDarkTheme::makeAllPalettesColorsDark()
+{
+    const auto palettes = makePalettesColorsDark();
+
+    return {
+        .palettes = palettes,
+        .button = makeButtonPaletteColorsDark(),
+        .toolButton = makeToolButtonPaletteColorsDark(),
+        .system = makeSystemButtonPaletteColorsDark(),
+        .menu = makeMenuPaletteColorsDark(palettes),
+        .tabBar = makeTabBarPaletteColorsDark(),
+        .textLineEdit = makeTextLineEditPaletteColorsDark(),
+        .groupBox = makeGroupboxPaletteColorsDark(),
+        .header = makeHeaderPaletteColorsDark(),
+        .toolTip = makeTooltipPaletteColorsDark(),
+    };
+}
+
+QAbstractTheme::ButtonPaletteColors QOhDarkTheme::makeButtonPaletteColorsDark()
+{
+    const auto activeButton = QColor("#19FFFFFF");
+
+    return {
+        .activeButton = activeButton,
+        .inactiveButton = makeInactiveOrDisabledFromColor(activeButton),
+        .focusedOutline = QColor("#3F97E9"),
+        .enabledDefaultButtonText = QColor("#E5E5E5"),
+    };
+}
+
+QAbstractTheme::TabBarPaletteColors QOhDarkTheme::makeTabBarPaletteColorsDark()
+{
+    const auto inactiveWindowText = QColor("#99FFFFFF");
+
+    return {
+        .activeWindowText = QColor("#FF3F97E9"),
+        .inactiveWindowText = inactiveWindowText,
+        .disabledWindowText = makeInactiveOrDisabledFromColor(inactiveWindowText),
+    };
+}
+
+QAbstractTheme::HeaderPaletteColors QOhDarkTheme::makeHeaderPaletteColorsDark()
+{
+    return {
+        .activeButton = QColor("#FF18181A"),
+    };
+}
+
+QAbstractTheme::TooltipPaletteColors QOhDarkTheme::makeTooltipPaletteColorsDark()
+{
+    return {
+        .toolTipBorder = QColor("#1AFFFFFF"),
+        .toolTipBase = QColor("#404040"),
+    };
+}
+
+QAbstractTheme::GroupboxPaletteColors QOhDarkTheme::makeGroupboxPaletteColorsDark()
+{
+    return {
+        .background = QColor("#00000000"),
+        .groupBoxFrame = QColor("#66FFFFFF"),
+        .shadowXS = QColor("#19FFFFFF"),
+    };
+}
+
+QAbstractTheme::SystemPaletteColors QOhDarkTheme::makeSystemButtonPaletteColorsDark()
+{
+    return {
+        .activeWindowFrame = QColor("#FF000000"),
+        .inactiveWindowFrame = QColor("#FF18181A"),
+        .textHint = QColor("#99FFFFFF"),
+        .textTertiary = QColor("#66FFFFFF"),
+    };
+}
+
+QAbstractTheme::ToolButtonPaletteColors QOhDarkTheme::makeToolButtonPaletteColorsDark()
+{
+    return {
+        .windowButtonBackground = QColor("#FFD0CFD5"),
+    };
+}
+
+QAbstractTheme::TextLineEditPaletteColors QOhDarkTheme::makeTextLineEditPaletteColorsDark()
+{
+    const auto textEditBackground = QColor("#19FFFFFF");
+    return {
+        .textEditBackground = textEditBackground,
+        .inactiveTextEditBackground = makeInactiveOrDisabledFromColor(textEditBackground),
+    };
+}
+
+QAbstractTheme::MenuPaletteColors QOhDarkTheme::makeMenuPaletteColorsDark(const PalettesColors &palettes)
+{
+    return {
+        .listSeparator = QColor("#33FFFFFF"),
+        .inactiveText = makeInactiveOrDisabledFromColor(palettes.textPrimary),
+    };
+}
+
+class QOhLightTheme : public QAbstractTheme
+{
+public:
+    explicit QOhLightTheme();
+    ~QOhLightTheme();
+
+private:
+    static PalettesColors makePalettesColorsLight();
+    static AllPalletesColors makeAllPalettesColorsLight();
+    static ButtonPaletteColors makeButtonPaletteColorsLight();
+    static TabBarPaletteColors makeTabBarPaletteColorsLight();
+    static HeaderPaletteColors makeHeaderPaletteColorsLight();
+    static TooltipPaletteColors makeTooltipPaletteColorsLight();
+    static GroupboxPaletteColors makeGroupboxPaletteColorsLight();
+    static SystemPaletteColors makeSystemButtonPaletteColorsLight();
+    static ToolButtonPaletteColors makeToolButtonPaletteColorsLight();
+    static TextLineEditPaletteColors makeTextLineEditPaletteColorsLight();
+    static MenuPaletteColors makeMenuPaletteColorsLight(const PalettesColors &palettes);
+};
+
+QOhLightTheme::QOhLightTheme() : QAbstractTheme({
+                       {QPlatformTheme::MenuFont, makeMenuFont()},
+                       {QPlatformTheme::MenuBarFont, makeMenuFont()},
+                       {QPlatformTheme::MenuItemFont, makeMenuFont()},
+                       {QPlatformTheme::TipLabelFont, makeTipLabelFont()},
+                       {QPlatformTheme::ListViewFont, makeListViewFont()},
+                       {QPlatformTheme::GroupBoxTitleFont, makeTitleFont()},
+                       {QPlatformTheme::DockWidgetTitleFont, makeTitleFont()},
+                       {QPlatformTheme::PushButtonFont, makePushButtonFont()},
+                       }, {
+                             []()->ThemePalettes {
+                                 const AllPalletesColors palettesColors = makeAllPalettesColorsLight();
+                                 return {
+                                          {QPlatformTheme::ButtonPalette, makeButtonPalette(palettesColors)},
+                                          {QPlatformTheme::CheckBoxPalette, makeCheckBoxOrRadioButtonPalette(palettesColors)},
+                                          {QPlatformTheme::ComboBoxPalette, makeComboBoxPalette(palettesColors)},
+                                          {QPlatformTheme::GroupBoxPalette, makeGroupBoxPalette(palettesColors)},
+                                          {QPlatformTheme::HeaderPalette, makeHeaderPalette(palettesColors)},
+                                          {QPlatformTheme::ItemViewPalette, makeItemViewPalette(palettesColors)},
+                                          {QPlatformTheme::LabelPalette, makeLabelPalette(palettesColors)},
+                                          {QPlatformTheme::MenuPalette, makeMenuPalette(palettesColors)},
+                                          {QPlatformTheme::RadioButtonPalette, makeCheckBoxOrRadioButtonPalette(palettesColors)},
+                                          {QPlatformTheme::SystemPalette, makeSystemPalette(palettesColors)},
+                                          {QPlatformTheme::TabBarPalette, makeTabBarPalette(palettesColors)},
+                                          {QPlatformTheme::TextEditPalette, makeTextEditPalette(palettesColors)},
+                                          {QPlatformTheme::TextLineEditPalette, makeTextLineEditPalette(palettesColors)},
+                                          {QPlatformTheme::ToolButtonPalette, makeToolButtonPalette(palettesColors)},
+                                          {QPlatformTheme::ToolTipPalette, makeToolTipPalette(palettesColors)},
+                                          };
+                             }()
+                     })
+{
+
+}
+
+QOhLightTheme::~QOhLightTheme()
+{
+
+}
+
+QAbstractTheme::PalettesColors QOhLightTheme::makePalettesColorsLight()
+{
+    const auto activeWindow = QColor("#FFFFFFFF");
+    const auto activeButtonText = QColor("#0A59F7");
+    const auto activeHighlight = QColor("#FF007DFF");
+    const auto highlighted = QColor("#FF0A59F7");
+    const auto textPrimary = QColor("#FF182431");
+
+    return {
+        .activeWindow = activeWindow,
+        .inactiveWindow = makeInactiveOrDisabledFromColor(activeWindow),
+        .activeButtonText = activeButtonText,
+        .inactiveButtonText = makeInactiveOrDisabledFromColor(activeButtonText),
+        .activeHighlight = activeHighlight,
+        .inactiveHighlight = makeInactiveOrDisabledFromColor(activeHighlight),
+        .clickEffect = QColor("#1A000000"),
+        .hover = QColor("#0D000000"),
+        .foregroundContrary = QColor("#FFFFFF"),
+        .highlighted = highlighted,
+        .inactiveHighlighted = makeInactiveOrDisabledFromColor(highlighted),
+        .textPrimary = textPrimary,
+        .inactiveTextPrimary = makeInactiveOrDisabledFromColor(textPrimary),
+        .inactiveText = QColor("#E6000000"),
+        .componentNormal = QColor("#19182431"),
+        .componentActivated = QColor("#007DFF"),
+        .indicatorArrow = QColor("#E5182431"),
+        .scrollBarSlider = QColor("#182431"),
+        .switchBgOff = QColor("#33FFFFFF"),
+        .switchOutlineOff = QColor("#66182431"),
+        .window = QColor("#FFF1F3F5"),
+    };
+};
+
+QAbstractTheme::AllPalletesColors QOhLightTheme::makeAllPalettesColorsLight()
+{
+    const auto palettes = makePalettesColorsLight();
+
+    return {
+        .palettes = palettes,
+        .button = makeButtonPaletteColorsLight(),
+        .toolButton = makeToolButtonPaletteColorsLight(),
+        .system = makeSystemButtonPaletteColorsLight(),
+        .menu = makeMenuPaletteColorsLight(palettes),
+        .tabBar = makeTabBarPaletteColorsLight(),
+        .textLineEdit = makeTextLineEditPaletteColorsLight(),
+        .groupBox = makeGroupboxPaletteColorsLight(),
+        .header = makeHeaderPaletteColorsLight(),
+        .toolTip = makeTooltipPaletteColorsLight(),
+    };
+}
+
+QAbstractTheme::ButtonPaletteColors QOhLightTheme::makeButtonPaletteColorsLight()
+{
+    const auto activeButton = QColor("#0C182431");
+
+    return {
+        .activeButton = activeButton,
+        .inactiveButton = makeInactiveOrDisabledFromColor(activeButton),
+        .focusedOutline = QColor("#007DFF"),
+        .enabledDefaultButtonText = QColor("#FFFFFFFF"),
+    };
+};
+
+QAbstractTheme::TabBarPaletteColors QOhLightTheme::makeTabBarPaletteColorsLight()
+{
+    const auto inactiveWindowText = QColor("#99182431");
+
+    return {
+        .activeWindowText = QColor("#FF007DFF"),
+        .inactiveWindowText = inactiveWindowText,
+        .disabledWindowText = makeInactiveOrDisabledFromColor(inactiveWindowText),
+    };
+};
+
+QAbstractTheme::HeaderPaletteColors QOhLightTheme::makeHeaderPaletteColorsLight()
+{
+    return {
+        .activeButton = QColor("#FFFFFFFF"),
+    };
+};
+
+QAbstractTheme::TooltipPaletteColors QOhLightTheme::makeTooltipPaletteColorsLight()
+{
+    return {
+        .toolTipBorder = QColor("#1A000000"),
+        .toolTipBase = QColor("#FFFFFFFF"),
+    };
+};
+
+QAbstractTheme::GroupboxPaletteColors QOhLightTheme::makeGroupboxPaletteColorsLight()
+{
+    return {
+        .background = QColor("#00000000"),
+        .groupBoxFrame = QColor("#66000000"),
+        .shadowXS = QColor("#19000000"),
+    };
+};
+
+QAbstractTheme::SystemPaletteColors QOhLightTheme::makeSystemButtonPaletteColorsLight()
+{
+    return {
+        .activeWindowFrame = QColor("#FFE4E4E4"),
+        .inactiveWindowFrame = QColor("#FFF2F3F5"),
+        .textHint = QColor("#99182431"),
+        .textTertiary = QColor("#66182431"),
+    };
+};
+
+QAbstractTheme::ToolButtonPaletteColors QOhLightTheme::makeToolButtonPaletteColorsLight()
+{
+    return {
+        .windowButtonBackground = QColor("#FFD0CFD5"),
+    };
+};
+
+QAbstractTheme::TextLineEditPaletteColors QOhLightTheme::makeTextLineEditPaletteColorsLight()
+{
+    const auto textEditBackground = QColor("#0C182431");
+    return {
+        .textEditBackground = textEditBackground,
+        .inactiveTextEditBackground = makeInactiveOrDisabledFromColor(textEditBackground),
+    };
+};
+
+QAbstractTheme::MenuPaletteColors QOhLightTheme::makeMenuPaletteColorsLight(const PalettesColors &palettes)
+{
+    return {
+        .listSeparator = QColor("#1A000000"),
+        .inactiveText = makeInactiveOrDisabledFromColor(palettes.textPrimary),
+    };
+};
+
+static QPalette qt_harmonyPalette()
+{
+    QColor base(250, 250, 250);
+    QColor text(24, 36, 49);
+    QColor background(250, 250, 250);
+    QColor light = background.lighter(150);
+    QColor mid(background.darker(130));
+    QColor midLight = mid.lighter(110);
+    QColor disabledBase(background);
+    QColor dark = background.darker(150);
+    QColor darkDisabled = dark.darker(110);
+    QColor highlightedText = Qt::black;
+    QColor disabledText = QColor(190, 190, 190);
+    QColor button(241, 241, 241);
+    QColor shadow(201, 201, 201);
+    QColor highlight(0, 120, 215);
+    QColor disabledShadow = shadow.lighter(150);
+
+    QPalette harmonyPalette = QPalette(Qt::black, background, light, dark, mid, text, base);
+    harmonyPalette.setBrush(QPalette::Button, button);
+    harmonyPalette.setBrush(QPalette::Shadow, shadow);
+    harmonyPalette.setBrush(QPalette::Midlight, midLight);
+    harmonyPalette.setBrush(QPalette::HighlightedText, highlightedText);
+    harmonyPalette.setColor(QPalette::Disabled, QPalette::Text, Qt::gray);
+    harmonyPalette.setColor(QPalette::Disabled, QPalette::ButtonText, Qt::gray);
+
+    harmonyPalette.setBrush(QPalette::Disabled, QPalette::Text, disabledText);
+    harmonyPalette.setBrush(QPalette::Disabled, QPalette::Base, disabledBase);
+    harmonyPalette.setBrush(QPalette::Disabled, QPalette::Dark, darkDisabled);
+    harmonyPalette.setBrush(QPalette::Disabled, QPalette::Shadow, disabledShadow);
+    harmonyPalette.setBrush(QPalette::Disabled, QPalette::WindowText, disabledText);
+    harmonyPalette.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledText);
+
+    harmonyPalette.setBrush(QPalette::Active, QPalette::Highlight, highlight);
+    harmonyPalette.setBrush(QPalette::Inactive, QPalette::Highlight, highlight);
+    harmonyPalette.setBrush(QPalette::Disabled, QPalette::Highlight, highlight.lighter(150));
+    return harmonyPalette;
+}
+
+class QOhDefaultTheme : public QAbstractTheme
+{
+public:
+    explicit QOhDefaultTheme();
+    ~QOhDefaultTheme();
+
+private:
+    static PalettesColors makePalettesColorsDefault();
+    static AllPalletesColors makeAllPalettesColorsDefault();
+    static ButtonPaletteColors makeButtonPaletteColorsDefault();
+    static TabBarPaletteColors makeTabBarPaletteColorsDefault();
+    static HeaderPaletteColors makeHeaderPaletteColorsDefault();
+    static TooltipPaletteColors makeTooltipPaletteColorsDefault();
+    static GroupboxPaletteColors makeGroupboxPaletteColorsDefault();
+    static SystemPaletteColors makeSystemButtonPaletteColorsDefault();
+    static ToolButtonPaletteColors makeToolButtonPaletteColorsDefault();
+    static TextLineEditPaletteColors makeTextLineEditPaletteColorsDefault();
+    static MenuPaletteColors makeMenuPaletteColorsDefault(const PalettesColors &palettes);
+};
+/* TODO 暂时用同一种配色? */
+QOhDefaultTheme::QOhDefaultTheme() : QAbstractTheme({
+                             []()->ThemeFonts {
+                                 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
+                                 const auto *fontDatabase = static_cast<QOhFontDatabase *>(platformIntegration->fontDatabase());
+                                 return fontDatabase->themeFonts();
+                             }()
+                     }, {
+                             []()->ThemePalettes {
+                                 const AllPalletesColors palettesColors = makeAllPalettesColorsDefault();
+                                 Q_UNUSED(palettesColors)
+                                 return {
+                                          {QPlatformTheme::ButtonPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::CheckBoxPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::ComboBoxPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::GroupBoxPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::HeaderPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::ItemViewPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::LabelPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::MenuPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::RadioButtonPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::SystemPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::TabBarPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::TextEditPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::TextLineEditPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::ToolButtonPalette, qt_harmonyPalette()},
+                                          {QPlatformTheme::ToolTipPalette, qt_harmonyPalette()},
+                                          };
+                             }()
+                     })
+{
+
+}
+
+QOhDefaultTheme::~QOhDefaultTheme()
+{
+
+}
+
+QAbstractTheme::PalettesColors QOhDefaultTheme::makePalettesColorsDefault()
+{
+    const auto activeWindow = QColor("#f0f0f0");
+    const auto activeButtonText = QColor("#353535");
+    const auto activeHighlight = QColor("#3daee9");
+    const auto highlighted = QColor("#3daee9");
+    const auto textPrimary = QColor("#353535");
+
+    return {
+        .activeWindow = activeWindow,
+        .inactiveWindow = QColor("#e0e0e0"),
+        .activeButtonText = activeButtonText,
+        .inactiveButtonText = QColor("#7f8c8d"),
+        .activeHighlight = activeHighlight,
+        .inactiveHighlight = QColor("#93cde9"),
+        .clickEffect = QColor("#1a000000"),
+        .hover = QColor("#0d3daee9"),
+        .foregroundContrary = QColor("#ffffff"),
+        .highlighted = highlighted,
+        .inactiveHighlighted = QColor("#93cde9"),
+        .textPrimary = textPrimary,
+        .inactiveTextPrimary = QColor("#7f8c8d"),
+        .inactiveText = QColor("#7f8c8d"),
+        .componentNormal = QColor("#e0e0e0"),
+        .componentActivated = QColor("#3daee9"),
+        .indicatorArrow = QColor("#353535"),
+        .scrollBarSlider = QColor("#c0c0c0"),
+        .switchBgOff = QColor("#e6e6e6"),
+        .switchOutlineOff = QColor("#b1b1b1"),
+        .window = QColor("#eff0f1"),
+    };
+}
+
+QAbstractTheme::AllPalletesColors QOhDefaultTheme::makeAllPalettesColorsDefault()
+{
+    const auto palettes = makePalettesColorsDefault();
+
+    return {
+        .palettes = palettes,
+        .button = makeButtonPaletteColorsDefault(),
+        .toolButton = makeToolButtonPaletteColorsDefault(),
+        .system = makeSystemButtonPaletteColorsDefault(),
+        .menu = makeMenuPaletteColorsDefault(palettes),
+        .tabBar = makeTabBarPaletteColorsDefault(),
+        .textLineEdit = makeTextLineEditPaletteColorsDefault(),
+        .groupBox = makeGroupboxPaletteColorsDefault(),
+        .header = makeHeaderPaletteColorsDefault(),
+        .toolTip = makeTooltipPaletteColorsDefault(),
+    };
+}
+
+QAbstractTheme::ButtonPaletteColors QOhDefaultTheme::makeButtonPaletteColorsDefault()
+{
+    const auto activeButton = QColor("#fcfcfc");
+
+    return {
+        .activeButton = activeButton,
+        .inactiveButton = QColor("#e0e0e0"),
+        .focusedOutline = QColor("#3daee9"),
+        .enabledDefaultButtonText = QColor("#353535"),
+    };
+};
+
+QAbstractTheme::TabBarPaletteColors QOhDefaultTheme::makeTabBarPaletteColorsDefault()
+{
+    return {
+        .activeWindowText = QColor("#3daee9"),
+        .inactiveWindowText = QColor("#7f8c8d"),
+        .disabledWindowText = QColor("#bdc3c7"),
+    };
+};
+
+QAbstractTheme::HeaderPaletteColors QOhDefaultTheme::makeHeaderPaletteColorsDefault()
+{
+    return {
+        .activeButton = QColor("#eff0f1"),
+    };
+};
+
+QAbstractTheme::TooltipPaletteColors QOhDefaultTheme::makeTooltipPaletteColorsDefault()
+{
+    return {
+        .toolTipBorder = QColor("#999999"),
+        .toolTipBase = QColor("#FFFFFF"),
+    };
+};
+
+QAbstractTheme::GroupboxPaletteColors QOhDefaultTheme::makeGroupboxPaletteColorsDefault()
+{
+    return {
+        .background = QColor("#00000000"),
+        .groupBoxFrame = QColor("#999999"),
+        .shadowXS = QColor("#19000000"),
+    };
+};
+
+QAbstractTheme::SystemPaletteColors QOhDefaultTheme::makeSystemButtonPaletteColorsDefault()
+{
+    return {
+        .activeWindowFrame = QColor("#e6e6e6"),
+        .inactiveWindowFrame = QColor("#eff0f1"),
+        .textHint = QColor("#999999"),
+        .textTertiary = QColor("#808080"),
+    };
+};
+
+QAbstractTheme::ToolButtonPaletteColors QOhDefaultTheme::makeToolButtonPaletteColorsDefault()
+{
+    return {
+        .windowButtonBackground = QColor("#E6E6E6"),
+    };
+};
+
+QAbstractTheme::TextLineEditPaletteColors QOhDefaultTheme::makeTextLineEditPaletteColorsDefault()
+{
+    const auto textEditBackground = QColor("#ffffff");
+    return {
+        .textEditBackground = textEditBackground,
+        .inactiveTextEditBackground = QColor("#eff0f1"),
+    };
+};
+
+QAbstractTheme::MenuPaletteColors QOhDefaultTheme::makeMenuPaletteColorsDefault(const PalettesColors &palettes)
+{
+    Q_UNUSED(palettes)
+    return {
+        .listSeparator = QColor("#e6e6e6"),
+        .inactiveText = QColor("#7f8c8d"),
+    };
+};
+constexpr int mouseDoubleClickDistance = 60;
+constexpr int mouseDoubleClickInterval = 300;
+
+}
+
+class QOhFileIconEngine : public QAbstractFileIconEngine
+{
+public:
+    explicit QOhFileIconEngine(const QFileInfo &info, QPlatformTheme::IconOptions opts) :
+        QAbstractFileIconEngine(info, opts) {
+
+    }
+
+    static QList<QSize> availableIconSizes()
+    {
+        // Todo get from system
+        const qreal devicePixelRatio = qGuiApp->devicePixelRatio();
+        const int sizes[] = {
+            qRound(16 * devicePixelRatio), qRound(32 * devicePixelRatio),
+            qRound(64 * devicePixelRatio), qRound(128 * devicePixelRatio),
+            qRound(256 * devicePixelRatio)
+        };
+        return QAbstractFileIconEngine::toSizeList(sizes, sizes + sizeof(sizes) / sizeof(sizes[0]));
+    }
+
+    QList<QSize> availableSizes(QIcon::Mode = QIcon::Normal, QIcon::State = QIcon::Off) override
+    { return QOhFileIconEngine::availableIconSizes(); }
+
+    static QJsModule *m_fileManagerService;
+protected:
+    QString cacheKey() const override;
+    QPixmap filePixmap(const QSize &size, QIcon::Mode mode, QIcon::State) override;
+};
+
+QJsModule *QOhFileIconEngine::m_fileManagerService = nullptr;
+
+QOhPlatformTheme::QOhPlatformTheme()
+    : m_colorMode(ColorMode::Default)
+    , m_themes{
+        {ColorMode::Dark, new QOhDarkTheme()},
+        {ColorMode::Light, new QOhLightTheme()},
+        {ColorMode::Default, new QOhDefaultTheme()}
+    }
+{
+    /*openharmony 无该能力*/
+    if(canIUse("SystemCapability.FileManagement.FileManagerService.Core")){
+        QOhFileIconEngine::m_fileManagerService = new QJsModule("@hms.filemanagement.fileManagerService");
+    }
+}
+
+QOhPlatformTheme::~QOhPlatformTheme()
+{
+    qDeleteAll(m_themes);
+    m_themes.clear();
+    if (QOhFileIconEngine::m_fileManagerService != nullptr)
+        delete QOhFileIconEngine::m_fileManagerService;
+}
+
+void QOhPlatformTheme::setColorMode(ColorMode mode)
+{
+    if (!m_themes.contains(mode)) {
+        qCWarning(ohosthem, "%s: unsupported ColorsTheme (%d), ignoring the call",
+                Q_FUNC_INFO, static_cast<int>(mode));
+        return;
+    }
+    m_colorMode = mode;
+}
+
+QOhPlatformTheme::ColorMode QOhPlatformTheme::colorMode() const
+{
+    return m_colorMode;
+}
+
+QString QOhPlatformTheme::standardButtonText(int button) const
+{
+    return QPlatformTheme::standardButtonText(button);
+}
+
+bool QOhPlatformTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const
+{
+    return type == QPlatformTheme::FileDialog;
+}
+
+const QPalette *QOhPlatformTheme::palette(Palette type) const
+{
+    QAbstractTheme *theme = m_themes.value(m_colorMode, nullptr);
+    if (nullptr != theme) {
+        return theme->palette(type);
+    }
+    return QPlatformTheme::palette(type);
+}
+
+QPlatformDialogHelper *QOhPlatformTheme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const
+{
+    return QOhPlatformDialogHelpers::createHelper(type);
+}
+
+const QFont *QOhPlatformTheme::font(Font type) const
+{
+    QAbstractTheme *theme = m_themes.value(m_colorMode, nullptr);
+    if (nullptr != theme) {
+        return theme->font(type);
+    }
+
+    return QPlatformTheme::font(type);
+}
+
+#ifndef QT_NO_SYSTEMTRAYICON
+QPlatformSystemTrayIcon *QOhPlatformTheme::createPlatformSystemTrayIcon() const
+{
+    return new QOhSystemTrayIcon();
+}
+#endif
+
+QPixmap QOhPlatformTheme::standardPixmap(QPlatformTheme::StandardPixmap sp, const QSizeF &size) const
+{
+    return QPlatformTheme::standardPixmap(sp, size);
+}
+
+QString QOhFileIconEngine::cacheKey() const
+{
+    // Cache directories unless custom or drives, which have custom icons depending on type
+    if ((options() & QPlatformTheme::DontUseCustomDirectoryIcons) && fileInfo().isDir() && !fileInfo().isRoot())
+        return QStringLiteral("qt_/directory/");
+    if (!fileInfo().isFile())
+        return QString();
+    // Return "" for .exe, .lnk and .ico extensions.
+    // It is faster to just look at the file extensions;
+    // avoiding slow QFileInfo::isExecutable() (QTBUG-13182)
+    QString suffix = fileInfo().suffix();
+    if (!suffix.compare(u"exe", Qt::CaseInsensitive)
+        || !suffix.compare(u"lnk", Qt::CaseInsensitive)
+        || !suffix.compare(u"ico", Qt::CaseInsensitive)) {
+        return QString();
+    }
+    return QLatin1String("qt_.")
+        + (suffix.isEmpty() ? fileInfo().fileName() : std::move(suffix).toUpper()); // handle "Makefile";)
+}
+
+class QOhDrawableDescriptor
+{
+public:
+    QOhDrawableDescriptor(ArkUI_DrawableDescriptor *descriptor)
+        : m_descriptor(new QOhObjectHolder<ArkUI_DrawableDescriptor>(descriptor, OH_ArkUI_DrawableDescriptor_Dispose))
+    {}
+
+    QPixmap toQPixmap(const QSize &size) const
+    {
+        auto pixelMap = OH_ArkUI_DrawableDescriptor_GetStaticPixelMap(m_descriptor->object());
+        if (pixelMap == nullptr)
+            return QPixmap();
+        QOhObjectHolder<OH_PixelmapNative> pixelMapHolder(pixelMap, OH_PixelmapNative_Release);
+        auto image = QtOh::UdmfHelper::createQImageFromPixelmapNative(pixelMap);
+        return QPixmap::fromImage(image.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation));
+    }
+
+private:
+    QScopedPointer<QOhObjectHolder<ArkUI_DrawableDescriptor>> m_descriptor;
+};
+
+std::vector<std::string> split(const std::string& s, char delimiter) {
+    std::vector<std::string> tokens;
+    size_t start = 0;
+    size_t end = s.find(delimiter);
+
+    while (end != std::string::npos) {
+        tokens.push_back(s.substr(start, end - start));
+        start = end + 1;
+        end = s.find(delimiter, start);
+    }
+
+    tokens.push_back(s.substr(start));
+    return tokens;
+}
+
+QPixmap QOhFileIconEngine::filePixmap(const QSize &size, QIcon::Mode, QIcon::State)
+{
+    const QString filePath = QDir::toNativeSeparators(fileInfo().filePath());
+    QPixmap pixmap = QtOh::runOnJsUIThreadWithResult([](const QString &suffix, const QSize &size){
+        static QJsModule uniformTypeDescriptor("@ohos.data.uniformTypeDescriptor");
+        QString ohosSuffix = "." + suffix;
+        Napi::Value id = uniformTypeDescriptor.call("getUniformDataTypeByFilenameExtension", {Napi::String::New(uniformTypeDescriptor.env(), ohosSuffix.toStdString())});
+        if (id.IsEmpty() && !m_fileManagerService)
+            return QPixmap();
+        Napi::Value result = m_fileManagerService->call(QString::fromUtf8("getFileIconSync"), {id});
+        std::string uri;
+        ResourceManager_ErrorCode code = SUCCESS;
+        auto mgr = qNativeWindowManager->resourceManager();
+        QJsObject jsMgr(qNativeWindowManager->jsResourceManager().ToObject());
+        ArkUI_DrawableDescriptor *descriptor = nullptr;
+        Napi::Value jsDescriptor = Napi::Value();
+        if (result.IsString()) {
+            uri = result.ToString().Utf8Value();
+
+            /*note:c接口最后的OH_ArkUI_DrawableDescriptor_GetStaticPixelMap获取失败,使用ts接口*/
+            jsDescriptor = jsMgr.call("getDrawableDescriptorByName",
+                       { Napi::String::New(jsMgr.env(), uri.c_str()),
+                         Napi::Number::New(jsMgr.env(), uint8_t(0)),
+                         Napi::Number::New(jsMgr.env(), uint8_t(1))});
+
+            // code = OH_ResourceManager_GetDrawableDescriptorDataByName(mgr, uri.c_str(),
+            //                                                 &descriptor, 0, 0);
+        } else if (result.IsObject()) {
+            Napi::Object obj = result.As<Napi::Object>();
+            int id = (int32_t)obj.Get("id").ToNumber();
+            if (id != -1 ) {
+
+                jsDescriptor = jsMgr.call("getDrawableDescriptor",
+                                                      { Napi::Number::New(jsMgr.env(), uint8_t(id)),
+                                                        Napi::Number::New(jsMgr.env(), uint8_t(0)),
+                                                        Napi::Number::New(jsMgr.env(), uint8_t(1))});
+
+                // code = OH_ResourceManager_GetDrawableDescriptor(mgr, id, &descriptor);
+            } else {
+                Napi::Array params = obj.Get("params").As<Napi::Array>();
+                Napi::Value name = params[uint32_t(0)];
+                Napi::String nameString = name.As<Napi::String>();
+                auto names = split(nameString.Utf8Value(), '.');
+                if (names.size() != 3) {
+                    qWarning() << "GetDrawableDescriptor failed, resource name is invalid";
+                    return QPixmap();
+                }
+
+                qWarning() << "filePixmap resource udmf type:" <<  names.back().c_str();
+                jsDescriptor = jsMgr.call("getDrawableDescriptorByName",
+                                          { Napi::String::New(jsMgr.env(), names.back().c_str()),
+                                            Napi::Number::New(jsMgr.env(), uint8_t(0)),
+                                            Napi::Number::New(jsMgr.env(), uint8_t(1)) });
+
+                // code = OH_ResourceManager_GetDrawableDescriptorDataByName(mgr,names.back().c_str(),
+                //                                                           &descriptor, 0, 1);
+            }
+        }
+        // if (code != SUCCESS) {
+        //     qWarning() << "GetDrawableDescriptor failed: error code" << code;
+        //     return QPixmap();
+        // }
+        // QOhDrawableDescriptor drawableDescriptor(descriptor);
+        // return drawableDescriptor.toQPixmap(size);
+
+        if(jsDescriptor.IsObject()){
+            Napi::Value pixelMap = QJsObject(jsDescriptor.ToObject()).call("getPixelMap");
+            OH_PixelmapNative *pixelmapNative = nullptr;
+            OH_PixelmapNative_ConvertPixelmapNativeFromNapi(jsMgr.env(), pixelMap, &pixelmapNative);
+            if (pixelmapNative != nullptr) {
+                QOhObjectHolder<OH_PixelmapNative> pixelMapHolder(pixelmapNative, OH_PixelmapNative_Release);
+                auto image = QtOh::UdmfHelper::createQImageFromPixelmapNative(pixelmapNative);
+                return QPixmap::fromImage(image.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation));
+            }
+        }
+        return QPixmap();
+    }, fileInfo().suffix().toLower(), size);
+    if (pixmap.isNull()) {
+        qWarning("QOhFileIconEngine::filePixmap() no icon found");
+    }
+    return pixmap;
+}
+
+QIcon QOhPlatformTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const
+{
+    if (QtOh::apiVersion() >= 17) {
+        return QIcon(new QOhFileIconEngine(fileInfo, iconOptions));
+    }
+
+    return QPlatformTheme::fileIcon(fileInfo, iconOptions);
+}
+
+bool QOhPlatformTheme::darkThemeEnabled() const
+{
+    return this->colorMode() == QOhPlatformTheme::ColorMode::Dark;
+}
+
+void QOhPlatformTheme::setThemeColorMode(int colorMode)
+{
+    setColorMode(ColorMode(colorMode));
+
+    const auto allWindows = qGuiApp->allWindows();
+    if (allWindows.empty()) {
+        QWindowSystemInterface::handleThemeChange(nullptr);
+    } else {
+        for (auto *window : allWindows) {
+
+            /* NOTE quickwindow窗口不能设置XComponent背景色
+             * 设置后可能导致渲染异常
+             */
+            if (QSurface::OpenGLSurface != window->surfaceType()) {
+                if (auto handle = dynamic_cast<QOhPlatformOpenGLWindow*>(window->handle())) {
+                    QVariant var = window->property("_q_background");
+                    QBrush brush = var.value<QBrush>();
+
+                    /* NOTE 窗口没有设置过XComponent背景色才应用主题色 */
+                    if (Qt::NoBrush == brush.style()) {
+                        const QColor &cr = m_themes.value(ColorMode(colorMode))->palette(Palette::SystemPalette)->color(QPalette::Window);
+                        handle->nativeWindowNode()->setBackgroundColor(cr);
+                    } else {
+                        handle->nativeWindowNode()->setBackgroundColor(qbrush_color(brush));
+                    }
+                }
+            }
+            QWindowSystemInterface::handleThemeChange(window);
+        }
+    }
+}
+
+QVariant QOhPlatformTheme::themeHint(ThemeHint hint) const
+{
+    switch (hint) {
+    case WheelScrollLines:
+        return QVariant(wheelScrollLines);
+    case StyleNames:
+        return QVariant(QStringList{ "harmonyos", "openharmony" }); /* FIXME 暂时认为OpenHarmony HarmonyOS是两种不同的主题样式 */
+    case MouseDoubleClickDistance:
+    case TouchDoubleTapDistance:
+    {
+        auto *primaryScreen = qGuiApp->primaryScreen();
+        auto *platformScreen = primaryScreen != nullptr
+                ? primaryScreen->handle()
+                : nullptr;
+        return platformScreen != nullptr
+                ? QHighDpi::fromNativePixels(
+                          QHighDpi::toNative(
+                                mouseDoubleClickDistance, QtOh::densityPixels(platformScreen)),
+                          platformScreen)
+                : mouseDoubleClickDistance;
+    }
+    case MouseDoubleClickInterval:
+        return mouseDoubleClickInterval;
+    case UseFullScreenForPopupMenu:
+        return QVariant(QtOh::isTabletDevice());
+    default:
+        return QPlatformTheme::themeHint(hint);
+    }
+}
diff --git a/src/plugins/platforms/openharmony/qohplatformtheme.h b/src/plugins/platforms/openharmony/qohplatformtheme.h
new file mode 100644
index 00000000000..e2f05c1647d
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformtheme.h
@@ -0,0 +1,53 @@
+#ifndef QOHPLATFORMTHEME_H
+#define QOHPLATFORMTHEME_H
+
+#include <QtCore/qvariant.h>
+#include <QtCore/QMap>
+#include <QtCore/QHash>
+#include <qpa/qplatformtheme.h>
+
+namespace {
+class QAbstractTheme;
+}
+
+class QOhPlatformTheme: public QPlatformTheme
+{
+    friend class QOhEventDispatcherPrivate;
+public:
+    enum class ColorMode {        
+        Dark,
+        Light,
+        Default
+    };
+
+    QOhPlatformTheme();
+    ~QOhPlatformTheme();
+
+    ColorMode colorMode() const;
+    void setColorMode(ColorMode mode);
+
+    QVariant themeHint(ThemeHint hint) const override;
+    virtual QString standardButtonText(int button) const override;
+    bool usePlatformNativeDialog(DialogType type) const override;
+    const QPalette *palette(Palette type = SystemPalette) const override;
+    QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override;
+    virtual const QFont *font(Font type = SystemFont) const override;
+#ifndef QT_NO_SYSTEMTRAYICON
+    virtual QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
+#endif
+    virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override;
+    virtual QIcon fileIcon(const QFileInfo &fileInfo,
+                           QPlatformTheme::IconOptions iconOptions = { }) const override;
+
+    bool darkThemeEnabled() const override;
+    void setThemeColorMode(int colorMode) override;
+
+private:
+    ColorMode m_colorMode;
+    inline static int wheelScrollLines = 3;
+    QMap<ColorMode, QAbstractTheme*> m_themes;
+    mutable QHash<QPlatformTheme::Font, QFont> m_fonts;
+    QMap<ColorMode, QHash<Palette, QPalette>> m_themesPalettes;
+};
+
+#endif // QOHPLATFORMTHEME_H
diff --git a/src/plugins/platforms/openharmony/qohplatformvulkaninstance.cpp b/src/plugins/platforms/openharmony/qohplatformvulkaninstance.cpp
new file mode 100644
index 00000000000..498178a2dc0
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformvulkaninstance.cpp
@@ -0,0 +1,52 @@
+#include <qopenharmonydefines.h>
+#include "qohplatformvulkaninstance.h"
+#include <vulkan/vulkan_ohos.h>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QOhPlatformVulkanInstance::QOhPlatformVulkanInstance(QVulkanInstance *instance)
+    : m_instance(instance)
+    , m_createSurface(nullptr)
+{
+    m_lib.setFileName(QStringLiteral("vulkan"));
+
+    if (!m_lib.load()) {
+        LOGW("Failed to load %{public}s", qPrintable(m_lib.fileName()));
+        return;
+    }
+
+    init(&m_lib);
+}
+
+void QOhPlatformVulkanInstance::createOrAdoptInstance()
+{
+    initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_OHOS_surface") << QByteArrayLiteral("VK_KHR_surface"));
+}
+
+QOhPlatformVulkanInstance::~QOhPlatformVulkanInstance()
+{
+}
+
+VkSurfaceKHR QOhPlatformVulkanInstance::createSurface(void *window)
+{
+    VkSurfaceKHR surface = VK_NULL_HANDLE;
+    if (!m_createSurface) {
+        m_createSurface = reinterpret_cast<PFN_vkCreateSurfaceOHOS>(
+                m_vkGetInstanceProcAddr(m_vkInst, "vkCreateSurfaceOHOS"));
+    }
+    if (!m_createSurface) {
+        qWarning("Failed to find vkCreateSurfaceOHOS");
+        return surface;
+    }
+    VkSurfaceCreateInfoOHOS surfaceCreateInfo = {};
+    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS;
+    surfaceCreateInfo.window = reinterpret_cast<OHNativeWindow *>(window);
+    int err = m_createSurface(m_vkInst, &surfaceCreateInfo, NULL, &surface);
+    if (err != VK_SUCCESS) {
+        qWarning() << "create vulkan surface failed";
+    }
+    return surface;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohplatformvulkaninstance.h b/src/plugins/platforms/openharmony/qohplatformvulkaninstance.h
new file mode 100644
index 00000000000..139efaa2b82
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformvulkaninstance.h
@@ -0,0 +1,27 @@
+#ifndef QOHPLATFORMVULKANINSTANCE_H
+#define QOHPLATFORMVULKANINSTANCE_H
+
+#include <QtGui/private/qbasicvulkanplatforminstance_p.h>
+#include <QLibrary>
+#include <vulkan/vulkan_ohos.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOhPlatformVulkanInstance : public QBasicPlatformVulkanInstance
+{
+public:
+    QOhPlatformVulkanInstance(QVulkanInstance *instance);
+    ~QOhPlatformVulkanInstance();
+
+    void createOrAdoptInstance() override;
+    VkSurfaceKHR createSurface(void *window);
+
+private:
+    QVulkanInstance *m_instance;
+    QLibrary m_lib;
+    PFN_vkCreateSurfaceOHOS m_createSurface;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHPLATFORMVULKANINSTANCE_H
diff --git a/src/plugins/platforms/openharmony/qohplatformwindow.cpp b/src/plugins/platforms/openharmony/qohplatformwindow.cpp
new file mode 100644
index 00000000000..c1f645f4e33
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformwindow.cpp
@@ -0,0 +1,416 @@
+#include <QDebug>
+#include <QMetaObject>
+#include <qguiapplication.h>
+#include <qpa/qplatformwindow_p.h>
+#include <QtGui/qguiapplication.h>
+#include <private/qguiapplication_p.h>
+#include <QtCore/qopenharmonydefines.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
+
+#include "qohevent.h"
+#include "qohmain.h"
+#include "qohauxiliary.h"
+#include "qohwindownode.h"
+#include "qohplatformwindow.h"
+#include "qohplatformscreen.h"
+#include "qoheventdispatcher.h"
+#include "qohnativewindowmanager.h"
+#include "qohplatforminputcontext.h"
+#include "qohnativewindow.h"
+#include "qohwindowcontext.h"
+
+QT_BEGIN_NAMESPACE
+
+#define FullUpdateRequest QEvent::User + 1
+
+QOhPlatformWindow::QOhPlatformWindow(QWindow *window)
+    : QPlatformWindow(window)
+    , m_node(nullptr)
+{
+    m_windowState = window->windowState();
+}
+
+QOhPlatformWindow::~QOhPlatformWindow()
+{
+    deleteNativeWindowNode();
+    QOhWindowContext::removeWindow(this);
+}
+
+void QOhPlatformWindow::initialize()
+{
+    QOhWindowContext::appendWindow(this);
+}
+
+void QOhPlatformWindow::setOpacity(qreal level)
+{
+    /* TODO 需要控制整个窗体的透明度
+     * 鸿蒙因安全问题,不开放此权限
+     */
+    QPlatformWindow::setOpacity(level);
+}
+
+Qt::WindowModality QOhPlatformWindow::modality() const
+{
+    Qt::WindowModality m = window()->modality();
+    return m;
+}
+
+bool QOhPlatformWindow::isExposed() const
+{
+    return m_isExposed;
+}
+
+WId QOhPlatformWindow::winId() const
+{
+    if (!m_node) return (WId)nullptr;
+    return m_node->id();
+}
+
+QSize QOhPlatformWindow::xcomponentSize() const
+{
+    if (m_node) {
+        QSize size = QHighDpi::fromNativePixels(m_node->surfaceSize(), window());
+        return size;
+    }
+    return QPlatformWindow::xcomponentSize();
+}
+
+void QOhPlatformWindow::lower()
+{
+    if (m_node != nullptr) {
+        m_node->lower();
+    }
+    QOhWindowContext::lowerWindow(this);
+}
+
+void QOhPlatformWindow::raise()
+{
+    if (m_node != nullptr) {
+        m_node->raise();
+    }
+    QOhWindowContext::raiseWindow(this);
+}
+
+void QOhPlatformWindow::setGeometry(const QRect &rect)
+{
+    QPlatformWindow::setGeometry(rect);
+    if (m_node != nullptr) {
+        m_node->setGeometry(rect);
+    }
+}
+
+bool QOhPlatformWindow::isTopLevelWindow() const
+{
+    return window()->isTopLevel();
+}
+
+bool QOhPlatformWindow::hasFrame() const
+{
+    return detectionWindowHasFrame();
+}
+
+bool QOhPlatformWindow::isModal() const
+{
+    return window()->isModal();
+}
+
+bool QOhPlatformWindow::showWithoutActive() const
+{
+    const QVariant showWithoutActivating = window()->property("_q_showWithoutActivating");
+    bool without = showWithoutActivating.isValid() && showWithoutActivating.toBool();
+
+    Qt::WindowType type = window()->type();
+    // 添加QMenu显示不获取焦点 QMenu type为Qt::Popup
+    return type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool || without;
+}
+
+bool QOhPlatformWindow::canSetFocus() const
+{
+    Qt::WindowType type = window()->type();
+
+    /* QDockWidget窗口类型为Qt::Tool,可以获取焦点 */
+    bool result = (type != Qt::Popup)
+            && (type != Qt::ToolTip);
+    return result;
+}
+
+QString QOhPlatformWindow::parentWindowName() const
+{
+    QOhPlatformWindow *p = dynamic_cast<QOhPlatformWindow *>(parent());
+    if (p == nullptr)
+        return QString();
+    return p->windowName();
+}
+
+QString QOhPlatformWindow::transientParentName() const
+{
+    QWindow *w = this->window();
+    if (Q_NULLPTR == w)
+        return QString();
+
+    QWindow * transient = w->transientParent();
+    if (transient) {
+        if (QOhPlatformWindow *p = dynamic_cast<QOhPlatformWindow*>(transient->handle())) {
+            return p->windowName();
+        }
+    }
+    return QString();
+}
+
+QOhPlatformScreen *QOhPlatformWindow::platformScreen() const
+{
+    return static_cast<QOhPlatformScreen *>(screen());
+}
+
+QString QOhPlatformWindow::windowTitle() const
+{
+    QString title = window()->title();
+    return formatWindowTitle(title, " - ");
+}
+
+void QOhPlatformWindow::setWindowName(const QString &name)
+{
+    m_name = name;
+}
+
+QString QOhPlatformWindow::windowName() const
+{
+    if (m_name.isEmpty()) {
+        m_name = QOhWindowContext::uniqueName(this);
+    }
+    return m_name;
+}
+
+bool QOhPlatformWindow::isRaster() const
+{
+    if (isForeignWindow())
+        return false;
+
+    return window()->surfaceType() == QSurface::RasterSurface
+            || window()->surfaceType() == QSurface::RasterGLSurface;
+}
+
+void QOhPlatformWindow::applicationStateChanged(Qt::ApplicationState)
+{
+    QRegion region;
+    if (isExposed())
+        region = QRect(QPoint(), geometry().size());
+
+    fireExpose(region);
+    QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+void QOhPlatformWindow::attachRootComponent(void *component)
+{
+    if (m_node != nullptr)
+        m_node->attachRootComponent(component);
+}
+
+QString QOhPlatformWindow::componentName() const
+{
+    if (m_node != nullptr)
+        return m_node->componentName();
+    return QString();
+}
+
+void QOhPlatformWindow::setVisible(bool visible)
+{
+    if (visible) {
+        fireFullExpose(true);
+        showNativeNode();
+    } else {
+        hideNativeNode();
+        if (QOhWindowContext::mouseGrabberWindow() == window())
+            QOhWindowContext::setMouseGrabberWindow(nullptr);
+        fireExpose(QRegion());
+    }
+    // QPlatformWindow::setVisible(visible);中调用了QWindowSystemInterface::flushWindowSystemEvents();
+    // 会先处理系统消息,比如鼠标事件,这用会导致时序错误等问题,比如菜单栏上移动鼠标,当前活动菜单项隐藏之后会调用该接口
+    // 如果使用flushWindowSystemEvents会导致又去处理鼠标事件,导致菜单项隐藏后续操作在处理系统鼠标之后,发生逻辑混乱问题
+    //QPlatformWindow::setVisible(visible);    
+}
+
+bool QOhPlatformWindow::setMouseGrabEnabled(bool grab)
+{
+    QOhWindowContext::setMouseGrabberWindow(grab ? window() : nullptr);
+    return true;
+}
+
+bool QOhPlatformWindow::setKeyboardGrabEnabled(bool grab)
+{
+    QOhWindowContext::setKeyGrabberWindow(grab ? window() : nullptr);
+    return true;
+}
+
+void QOhPlatformWindow::handleWindowStatusEvent(QtOh::WindowStatusType event)
+{
+    HiTracer tracer("QOhPlatformWindow::handleWindowStatusEvent");
+    switch (event) {
+    case QtOh::WindowStatusType::UNDEFINED:
+        return;
+    case QtOh::WindowStatusType::MINIMIZE:
+        handleWindowStateChange(m_windowState | Qt::WindowMinimized);
+        break;
+    case QtOh::WindowStatusType::MAXIMIZE:
+        handleWindowStateChange(Qt::WindowMaximized | (m_windowState.testFlag(Qt::WindowFullScreen) ? Qt::WindowFullScreen : Qt::WindowNoState));
+        break;
+    case QtOh::WindowStatusType::FLOATING:
+        handleWindowStateChange(Qt::WindowNoState);
+        break;
+    case QtOh::WindowStatusType::SPLIT_SCREEN:
+    case QtOh::WindowStatusType::FULL_SCREEN:
+        handleWindowStateChange(Qt::WindowFullScreen | (m_windowState.testFlag(Qt::WindowMaximized) ? Qt::WindowMaximized : Qt::WindowNoState));
+        break;
+    case QtOh::WindowStatusType::SURFACE_SHOW:
+        /* STATUS_SURFACE_SHOW暂不处理,最小化窗口或获取winId的窗口在显示时会额外触发多个窗口回调,
+         * 由windowStatusChange进行通知 */
+        return;
+    default:
+        return;
+    }
+}
+
+Qt::WindowStates QOhPlatformWindow::windowStates() const
+{
+    return m_windowState;
+}
+
+void QOhPlatformWindow::fireFullExpose(bool async)
+{
+    m_isExposed = true;
+    if (async) {
+        fireExpose(QRect(QRect(QPoint(), geometry().size())));
+    } else {
+        QWindow *w = window();
+        QEvent *e = new QEvent(w->inherits("QQuickWindow") ? QEvent::Type(FullUpdateRequest) : QEvent::UpdateRequest);
+        QCoreApplication::postEvent(w, e, Qt::HighEventPriority);
+    }
+}
+
+void QOhPlatformWindow::fireExpose(const QRegion &region)
+{
+    m_isExposed = !region.isEmpty();
+    QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(window(), region);
+}
+
+QOhWindowNode *QOhPlatformWindow::nativeWindowNode() const
+{
+    return m_node;
+}
+
+void QOhPlatformWindow::createNativeWindowNode(WId nativeHandle)
+{
+    if (nativeHandle) {
+        m_node = QOhWindowNode::fromId(nativeHandle);
+    } else {
+        QOhPlatformWindow *parentWindow = dynamic_cast<QOhPlatformWindow*>(parent());
+        m_node = new QOhWindowNode(parentWindow == nullptr ? nullptr : parentWindow->nativeWindowNode());
+    }
+    if (m_node != nullptr)
+        m_node->attachPlatformWindow(this);
+}
+
+void QOhPlatformWindow::deleteNativeWindowNode()
+{
+    if (m_node != nullptr) {
+        m_node->attachPlatformWindow(nullptr);
+        delete m_node;
+        m_node = nullptr;
+    }
+}
+
+void QOhPlatformWindow::showNativeNode()
+{
+    if (m_node != nullptr) {
+        m_node->setVisible(true);
+    }
+}
+
+void QOhPlatformWindow::hideNativeNode()
+{
+    if (m_node != nullptr) {
+        m_node->setVisible(false);
+    }
+}
+
+bool QOhPlatformWindow::detectionWindowHasFrame() const
+{
+    bool topLevel = isTopLevelWindow();
+    Qt::WindowFlags flags = window()->flags();
+    Qt::WindowType type = static_cast<Qt::WindowType>(int(flags) & Qt::WindowType_Mask);
+    bool dialog = false;
+    bool tool = false;
+    bool popup = false;
+    switch (type) {
+    case Qt::Dialog:
+    case Qt::Sheet:
+        dialog = true;
+        break;
+    case Qt::Drawer:
+    case Qt::Tool:
+        tool = true;
+        break;
+    case Qt::Popup:
+        popup = true;
+        break;
+    default:
+        break;
+    }
+
+    if ((flags & Qt::MSWindowsFixedSizeDialogHint))
+        dialog = true;
+
+    if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) {
+        return false;
+    } else if (topLevel) {
+        if (flags & Qt::FramelessWindowHint)
+            return false;                // no border
+        else
+            return true;
+    } else {
+        return false;
+    }
+    return false;
+}
+
+void QOhPlatformWindow::setParent(const QPlatformWindow *window)
+{
+    if (m_node == nullptr)
+        return;
+
+    QOhWindowNode *parentNode = nullptr;
+    if (window != nullptr){
+        WId parentWid = window->winId();
+        parentNode = QOhWindowNode::fromId(parentWid);
+    }
+
+    m_node->setParent(parentNode);
+    m_node->raise();
+}
+
+void QOhPlatformWindow::handleWindowStateChange(Qt::WindowStates states)
+{
+    if (Qt::Popup == window()->type()) {
+        /* FIXME 鸿蒙最小化状态和Qt不一致
+         * 造成QMenu菜单显示异常
+         */
+        return;
+    }
+
+    QWindowSystemInterface::handleWindowStateChanged(window(), states, m_windowState);
+    m_windowState = states;
+    if (states.testFlag(Qt::WindowMinimized)) {
+        QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
+    }
+}
+
+void QOhPlatformWindow::setNativeNodeRenderFit(QOpenHarmonyWindow::NativeNodeRenderFit fit)
+{
+    if (nullptr != m_node)
+        m_node->setRenderFit(static_cast<ArkUI_RenderFit>(fit));
+    else
+        window()->setProperty(QOpenHarmonyWindow::NativeNodeFitIdentifier, QVariant(static_cast<int>(fit)));
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohplatformwindow.h b/src/plugins/platforms/openharmony/qohplatformwindow.h
new file mode 100644
index 00000000000..cdc5cdd5684
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohplatformwindow.h
@@ -0,0 +1,90 @@
+#ifndef QOHPLATFORMWINDOW_H
+#define QOHPLATFORMWINDOW_H
+#include <qrect.h>
+#include <qobject.h>
+#include <qscopedpointer.h>
+#include <qpa/qplatformwindow.h>
+#include <qpa/qplatformwindow_p.h> /* Qt6 only modify */
+
+#include "qohauxiliary.h"
+
+QT_BEGIN_NAMESPACE
+class QOhWindowNode;
+class QOhPlatformScreen;
+class QOhPlatformBackingStore;
+struct OH_NativeXComponent;
+struct QCursorInfo;
+
+class QOhPlatformWindow : public QPlatformWindow,
+                          public QNativeInterface::Private::QOpenHarmonyWindow /* Qt6 only modify */
+{
+
+public:
+    explicit QOhPlatformWindow(QWindow *window);
+    ~QOhPlatformWindow();
+
+    void initialize() override;
+    void setOpacity(qreal level) override;
+    virtual Qt::WindowModality modality() const;
+    virtual bool isExposed() const override;
+    WId winId() const override;
+    QSize xcomponentSize() const override;
+    void lower() override;
+    void raise() override;
+    void setGeometry(const QRect &rect) override;
+    QOhPlatformScreen *platformScreen() const;
+
+    QString windowTitle() const;
+    void setWindowName(const QString &name);
+    QString windowName() const;
+
+    bool isRaster() const;
+
+    virtual void applicationStateChanged(Qt::ApplicationState);
+    virtual void setFrameMargins(const QMargins &margins){Q_UNUSED(margins);}
+    virtual void attachRootComponent(void *component);
+    virtual QString componentName() const;
+    virtual void setCursor(QCursorInfo *cursor) {Q_UNUSED(cursor);}
+    virtual QCursorInfo *cursor() const { return nullptr; }
+    void setVisible(bool visible) override;
+    bool setMouseGrabEnabled(bool grab) override;
+    bool setKeyboardGrabEnabled(bool grab) override;
+    void setNativeNodeRenderFit(QOpenHarmonyWindow::NativeNodeRenderFit fit) override; /* Qt6 only modify */
+
+    bool isTopLevelWindow() const;
+
+    bool hasFrame() const;
+
+    bool isModal() const;
+
+    bool showWithoutActive() const;
+
+    bool canSetFocus() const;
+
+    QString parentWindowName() const;
+    QString transientParentName() const;
+
+    void handleWindowStatusEvent(QtOh::WindowStatusType event);
+    Qt::WindowStates windowStates() const;
+    void setParent(const QPlatformWindow *window) override;
+    virtual int32_t nativeWindowId() const { return 0; }
+
+    void fireFullExpose(bool async = false);
+    void fireExpose(const QRegion &region = QRegion());
+    QOhWindowNode *nativeWindowNode() const;
+protected:
+    virtual void createNativeWindowNode(WId nativeHandle = 0);
+    void deleteNativeWindowNode();
+    virtual void showNativeNode();
+    virtual void hideNativeNode();
+    bool detectionWindowHasFrame() const;
+    virtual void handleWindowStateChange(Qt::WindowStates states);
+
+    mutable QString m_name;
+    Qt::WindowStates m_windowState = Qt::WindowNoState;
+    bool m_isExposed = false;
+    QOhWindowNode *m_node;
+};
+
+QT_END_NAMESPACE
+#endif // QOHPLATFORMWINDOW_H
diff --git a/src/plugins/platforms/openharmony/qohsystemtrayicon.cpp b/src/plugins/platforms/openharmony/qohsystemtrayicon.cpp
new file mode 100644
index 00000000000..878e87f540a
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohsystemtrayicon.cpp
@@ -0,0 +1,571 @@
+#include "qohsystemtrayicon.h"
+#include "qohnativewindowmanager.h"
+#include "qohplatformmenu.h"
+#include <QDataStream>
+#include <QDateTime>
+#include <QTimer>
+#include <QDebug>
+#include "qjscontext.h"
+#include "qohutility.h"
+#include "qohjsonlistener.h"
+#include <functional>
+#include <private/qguiapplication_p.h>
+#include "qohauxiliary.h"
+#include <qpa/qplatformtheme.h>
+#include <multimedia/image_framework/image/pixelmap_native.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+    \class QOhSystemTrayIcon
+    \brief openHarmony native system tray icon
+
+    \internal
+*/
+
+QOhSystemTrayIcon::QOhSystemTrayIcon()
+    :m_isInit(false)
+{
+    qRegisterMetaType<QPlatformSystemTrayIcon::ActivationReason>("QPlatformSystemTrayIcon::ActivationReason");
+
+}
+
+QOhSystemTrayIcon::~QOhSystemTrayIcon()
+{
+    if (m_statusManage) {
+        delete m_statusManage;
+        m_statusManage = nullptr;
+    }
+
+    if (m_isInit)
+        g_hasTrayIcon = false;
+
+    m_isInit = false;
+}
+
+void QOhSystemTrayIcon::init()
+{
+    if (!isSystemTrayAvailable()) {
+        qWarning() << "Creating tray icon on a tablet or phone is not supported!";
+        return;
+    }
+
+    if (g_hasTrayIcon || m_isInit)
+        return;
+
+    if (m_iconLight.isNull() || m_iconDark.isNull())
+        return;
+
+    QtOh::runOnJsUIThreadAndWait([this]{
+        m_statusManage = new QJsModule("@hms.pcService.statusBarManager");
+        Napi::Object icon = toNativeTrayIcon();
+        if (icon.IsNull() || icon.IsEmpty())
+            return;
+
+        QString abilityName = QtOh::apiVersion() >= 14 ? "" : qNativeWindowManager->getAbilityName();
+        QString moduleName = qNativeWindowManager->getModuleName();
+        Napi::Object operation = Napi::Object::New(QtOh::uiEnv());
+        operation.Set("abilityName", abilityName.toStdString());
+        operation.Set("title", m_toolTip.toStdString());
+        operation.Set("height", 50);
+        operation.Set("moduleName", moduleName.toStdString());
+
+        /*添加菜单项*/
+        Napi::Array menus = m_menu ? createOhMenu(m_menu) : createDefaultMenu();
+
+        /* 添加托盘图标 */
+        Napi::Object item = Napi::Object::New(QtOh::uiEnv());
+        item.Set("icons", icon);
+        item.Set("quickOperation", operation);
+        item.Set("statusBarGroupMenu", menus);
+
+        QJsContext *context = qNativeWindowManager->context();
+        if (context) {
+            m_statusManage->call("addToStatusBar", {context->object(), item});
+
+            if (m_statusManage->hasError()) {
+                qWarning() << "addToStatusBar failed:" << m_statusManage->lastError();
+                return;
+            }
+            g_hasTrayIcon = true;
+            m_isInit = true;
+        }
+
+        /* 设置回调 */
+        if (QtOh::apiVersion() >= 14) {
+            QJsObject::QNapiCallBack func1, func2;
+            func1 = std::bind(&QOhSystemTrayIcon::onStatusBarIconClick, this, std::placeholders::_1);
+            func2 = std::bind(&QOhSystemTrayIcon::onRightMenuClick, this, std::placeholders::_1);
+
+            m_statusBarIconClickListener = new QOhJsOnListener(m_statusManage, "statusBarIconClick", func1);
+            m_statusBarIconClickListener->on();
+            m_rightMenuClickListener = new QOhJsOnListener(m_statusManage, "rightMenuClick", func2);
+            m_rightMenuClickListener->on();
+        }
+    });
+}
+
+void QOhSystemTrayIcon::cleanup()
+{
+    if (m_statusManage) {
+        QtOh::runOnJsUIThreadAndWait([this]{
+            if (m_statusBarIconClickListener != nullptr) {
+                m_statusBarIconClickListener->off();
+                delete m_statusBarIconClickListener;
+                m_statusBarIconClickListener = nullptr;
+            }
+            if (m_rightMenuClickListener != nullptr) {
+                m_rightMenuClickListener->off();
+                delete m_rightMenuClickListener;
+                m_rightMenuClickListener = nullptr;
+            }
+
+            QJsContext *context = qNativeWindowManager->context();
+            if (context) {
+                m_statusManage->call("removeFromStatusBar", {context->object()});
+            }
+        });
+
+        delete m_statusManage;
+        m_statusManage = nullptr;
+    }
+
+    if (m_isInit)
+        g_hasTrayIcon = false;
+
+    m_isInit = false;
+}
+
+void QOhSystemTrayIcon::updateIcon(const QIcon &iconLight, const QIcon &iconDark)
+{
+    if (iconLight.availableSizes().isEmpty() && iconDark.availableSizes().isEmpty()) {
+        qWarning() << "Trayicon available sizes is empty, please check the icon plugin!";
+        return;
+    }
+
+    if (iconLight.isNull() && iconDark.isNull()) {
+        return;
+    }
+
+    m_iconLight = iconLight;
+    m_iconDark = iconDark;
+
+    if (m_iconLight.isNull()) {
+        m_iconLight = m_iconDark;
+    } else if (m_iconDark.isNull()) {
+        m_iconDark = m_iconLight;
+    }
+
+    if (!m_isInit || !m_statusManage)
+        return;
+
+    QtOh::runOnJsUIThreadAndWait([this]{
+        Napi::Object icon = toNativeTrayIcon();
+        if (icon.IsNull() || icon.IsEmpty())
+            return;
+
+        QJsContext *context = qNativeWindowManager->context();
+        if (context) {
+            m_statusManage->call("updateStatusBarIcon", {context->object(), icon});
+
+            if (m_statusManage->hasError()) {
+                qWarning() << "updateStatusBarIcon failed:" << m_statusManage->lastError();
+            }
+        }
+    });
+
+}
+
+void QOhSystemTrayIcon::updateIcon(const QIcon &icon)
+{
+    updateIcon(icon, icon);
+}
+
+void QOhSystemTrayIcon::updateToolTip(const QString &tooltip)
+{
+    //todo:鸿蒙上系统托盘图标暂不支持ToolTip(beta6)
+    m_toolTip = tooltip;
+    if (!tooltip.isEmpty())
+        qWarning() << "Not support to set tray tooltip on openharmony" << this;
+}
+
+QRect QOhSystemTrayIcon::geometry() const
+{
+    //todo:鸿蒙上暂只能获取到height(beta6)
+    QRect result(0,0,0,0);
+    return result;
+}
+
+void QOhSystemTrayIcon::showMessage(const QString &title, const QString &messageIn,
+                                         const QIcon &icon,
+                                         QPlatformSystemTrayIcon::MessageIcon iconType,
+                                         int msecsIn)
+{
+    /* 该接口需要通知权限 */
+    QtOh::runOnJsUIThreadAndWait([&]{
+        QJsModule notificationManager("@ohos.notificationManager");
+
+        static int notificationId = 0;
+        Napi::Object notificationRequest = Napi::Object::New(notificationManager.env());
+        notificationRequest.Set("id", notificationId++);
+        Napi::Object content = Napi::Object::New(notificationManager.env());
+
+        content.Set("notificationContentType", (int)BASIC_TEXT);
+        Napi::Object normal = Napi::Object::New(notificationManager.env());
+        normal.Set("title", title.toStdString());
+        normal.Set("text", messageIn.toStdString());
+        content.Set("normal", normal);
+
+        notificationRequest.Set("content", content);
+        // notificationRequest.Set("notificationSlotType", (int)SERVICE_INFORMATION);
+        QSize validSize(128, 128);
+        if (icon.isNull()) {
+            QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
+
+            QPixmap pixmap;
+            switch(iconType) {
+            case MessageIcon::Information:
+                pixmap = theme->standardPixmap(QPlatformTheme::MessageBoxInformation, validSize);
+                break;
+            case MessageIcon::Warning:
+                pixmap = theme->standardPixmap(QPlatformTheme::MessageBoxWarning, validSize);
+                break;
+            case MessageIcon::Critical:
+                pixmap = theme->standardPixmap(QPlatformTheme::MessageBoxCritical, validSize);
+                break;
+            default:
+                break;
+            }
+
+            if (!pixmap.isNull()) {
+                Napi::Value nativePix = pixFromQPixmap(pixmap);
+                notificationRequest.Set("smallIcon", nativePix);
+                notificationRequest.Set("largeIcon", nativePix);
+            }
+        } else {
+            Napi::Value nativePix = pixFromQIcon(icon, validSize);
+            notificationRequest.Set("smallIcon", nativePix);
+            notificationRequest.Set("largeIcon", nativePix);
+        }
+
+        if (msecsIn > 0)
+            notificationRequest.Set("autoDeletedTime", QDateTime::currentMSecsSinceEpoch() + msecsIn);
+
+        Napi::Function callback = Napi::Function::New(QtOh::uiEnv(), [](const Napi::CallbackInfo& info) {
+            if (info.Length() < 1) {
+                LOGW("QSystemTrayIcon::showMessage failed, error unkonwn");
+                return;
+            }
+            Napi::Object error = info[0].As<Napi::Object>();
+            if (error.IsEmpty() || error.IsNull())
+                return;
+
+            Napi::Value code = error.Get("code");
+            if (!code.IsNumber())
+                return;
+
+            if (int errCode = (int)code.ToNumber())
+                LOGW("QSystemTrayIcon::showMessage failed, code is %{public}d, message is %{public}s",\
+                     errCode, error.Get("message").ToString().Utf8Value().c_str());
+        });
+
+        notificationManager.call("publish", {notificationRequest, callback});
+    });
+}
+
+bool QOhSystemTrayIcon::isSystemTrayAvailable() const
+{
+    QtOh::Utility::DeviceType type = QtOh::Utility::type();
+    if (type == QtOh::Utility::Tablet && QtOh::apiVersion() >= 20) {
+        return true;
+    }
+
+    return type == QtOh::Utility::PC;
+}
+
+QPlatformMenu *QOhSystemTrayIcon::createMenu() const
+{
+    return new QOhPlatformMenu();
+}
+
+bool QOhSystemTrayIcon::hasTrayIcon()
+{
+    return g_hasTrayIcon || g_tsTryIcon;
+}
+
+Napi::Value QOhSystemTrayIcon::pixFromQIcon(const QIcon &icon, const QSize &size)
+{
+    QSize iconSize = getClosestIconSize(icon, size);
+    QPixmap pixmap = icon.pixmap(iconSize);
+    if (iconSize != size) {
+        pixmap = pixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+    }
+
+    return pixFromQPixmap(pixmap);
+}
+
+Napi::Value QOhSystemTrayIcon::pixFromQPixmap(const QPixmap &pix)
+{
+    std::unique_ptr<OH_PixelmapNative, decltype(&::OH_PixelmapNative_Release)> nativePixel(QtOh::UdmfHelper::createNativePixelMapFromQImage(pix.toImage()),
+                                                                                           ::OH_PixelmapNative_Release);
+    napi_value pixelMap { nullptr };
+    int result = ::OH_PixelmapNative_ConvertPixelmapNativeToNapi(QtOh::uiEnv(), nativePixel.get(), &pixelMap);
+    if (Image_ErrorCode::IMAGE_SUCCESS != result) {
+        qWarning("%s convert trayicon pixmap failed. code: %d", Q_FUNC_INFO, result);
+    }
+
+    return Napi::Value::From(QtOh::uiEnv(), pixelMap);
+}
+
+Napi::Array QOhSystemTrayIcon::createOhMenu(QOhPlatformMenu *ohMenu)
+{
+    if (!ohMenu) {
+        return createDefaultMenu();
+    }
+
+    Napi::Array statusBarGroupMenus = Napi::Array::New(QtOh::uiEnv());
+
+    QList<QOhPlatformMenuItem *> actions = ohMenu->childItems();
+    Napi::Array menuItems = Napi::Array::New(QtOh::uiEnv());
+    for (int i = 0; i < actions.size(); ++i) {
+        QOhPlatformMenuItem *item = actions[i];
+        if (!item || !item->isVisible())
+            continue;
+
+        if (item->isSeparator()) {
+            if (menuItems.Length()) {
+                int statusBarCnt = statusBarGroupMenus.Length();
+                statusBarGroupMenus.Set(statusBarCnt, menuItems);
+                menuItems = Napi::Array::New(QtOh::uiEnv());
+            }
+            continue;
+        }
+
+        Napi::Object menuItem = Napi::Object::New(QtOh::uiEnv());
+        menuItem.Set("title", item->text().toStdString());
+
+        if (item->menu()) {
+            Napi::Array subMenus = createSubMenu(qobject_cast<QOhPlatformMenu *>(item->menu()));
+            menuItem.Set("subMenu", subMenus);
+        } else {
+            // QString abilityName = qNativeWindowManager->getAbilityName();
+            /* FIXME 需要点击菜单项不默认弹出窗口,暂时只能给一个错误的值 */
+            QString abilityName = "tempStr";
+            Napi::Object menuAction = Napi::Object::New(QtOh::uiEnv());
+            menuAction.Set("abilityName", abilityName.toStdString());
+            menuAction.Set("notifyOnly", Napi::Boolean::New(QtOh::uiEnv(), true));
+            menuAction.Set("menuCode", QString::number(item->tag(), 16).toStdString());
+
+            menuItem.Set("menuAction", menuAction);
+        }
+
+        int length = menuItems.Length();
+        menuItems.Set(length, menuItem);
+    }
+
+    if (menuItems.Length()) {
+        int statusBarCnt = statusBarGroupMenus.Length();
+        statusBarGroupMenus.Set(statusBarCnt, menuItems);
+    }
+
+    return statusBarGroupMenus;
+}
+
+Napi::Array QOhSystemTrayIcon::createSubMenu(QOhPlatformMenu *ohMenu)
+{
+    Napi::Array menuSubItems = Napi::Array::New(QtOh::uiEnv());
+    if (!ohMenu) {
+        return menuSubItems;
+    }
+
+    QList<QOhPlatformMenuItem *> actions = ohMenu->childItems();
+    for (int i = 0; i < actions.size(); ++i) {
+        QOhPlatformMenuItem *item = actions[i];
+        if (!item || !item->isVisible())
+            continue;
+
+        if (item->menu()) {
+            qWarning() << "Not support adding three-level menus on openharmony!";
+            continue;
+        }
+
+        if (item->isSeparator()) {
+            qWarning() << "Not support adding separator on secondary menus!";
+            continue;
+        }
+
+        Napi::Object menuItem = Napi::Object::New(QtOh::uiEnv());
+        menuItem.Set("subTitle", item->text().toStdString());
+
+        // QString abilityName = qNativeWindowManager->getAbilityName();
+        /* FIXME 需要点击菜单项不默认弹出窗口,暂时只能给一个错误的值 */
+        QString abilityName = "tempStr";
+        Napi::Object menuAction = Napi::Object::New(QtOh::uiEnv());
+        menuAction.Set("abilityName", abilityName.toStdString());
+        menuAction.Set("notifyOnly", Napi::Boolean::New(QtOh::uiEnv(), true));
+        menuAction.Set("menuCode", QString::number(item->tag(), 16).toStdString());
+
+        menuItem.Set("menuAction", menuAction);
+
+        int length = menuSubItems.Length();
+        menuSubItems.Set(length, menuItem);
+    }
+
+    return menuSubItems;
+}
+
+Napi::Array QOhSystemTrayIcon::createDefaultMenu()
+{
+    Napi::Array statusBarGroupMenus = Napi::Array::New(QtOh::uiEnv());
+
+    return statusBarGroupMenus;
+}
+
+Napi::Object QOhSystemTrayIcon::toNativeTrayIcon()
+{
+    return QtOh::runOnJsUIThreadWithResult([this]{
+        if (m_iconDark.isNull() || m_iconLight.isNull())
+            return Napi::Object();
+
+        Napi::Value pixLight = pixFromQIcon(m_iconLight, QSize(24, 24));
+        Napi::Value pixDark = pixFromQIcon(m_iconDark, QSize(24, 24));
+        if (pixLight.IsNull() || pixLight.IsEmpty() || pixDark.IsNull() || pixDark.IsEmpty()) {
+            qWarning() << "Load icon failed!";
+            return Napi::Object();
+        }
+
+        Napi::Object icon = Napi::Object::New(QtOh::uiEnv());
+        icon.Set("white", pixLight);
+        icon.Set("black", pixDark);
+
+        return icon;
+    });
+}
+
+QSize QOhSystemTrayIcon::getClosestIconSize(const QIcon &icon, const QSize &targetSize)
+{
+    QList<QSize> sizes = icon.availableSizes();
+    if (sizes.isEmpty()) {
+        return QSize(); // 没有可用尺寸,返回空 QSize
+    }
+
+    QSize closestSize = sizes.first(); // 先假设第一个是最接近的
+    int minDiff = qAbs(closestSize.width() - targetSize.width()) +
+            qAbs(closestSize.height() - targetSize.height());
+
+    for (const QSize &size : std::as_const(sizes)) {
+        int diff = qAbs(size.width() - targetSize.width()) +
+                qAbs(size.height() - targetSize.height());
+
+        if (diff < minDiff) {
+            closestSize = size;
+            minDiff = diff;
+        }
+    }
+
+    return closestSize;
+}
+
+void QOhSystemTrayIcon::onStatusBarIconClick(const Napi::CallbackInfo &info)
+{
+    if (info.Length() < 1 || !info[0].IsObject()) {
+        return;
+    }
+    Napi::Object eventData = info[0].As<Napi::Object>();
+    if (!eventData.Has("data") || !eventData.Get("data").IsObject()) {
+        return;
+    }
+
+    Napi::Object data = eventData.Get("data").As<Napi::Object>();
+    if (!data.Has("iconClickType") || !data.Get("iconClickType").IsString()) {
+        return;
+    }
+    QString iconClickType = QString::fromStdString(data.Get("iconClickType").ToString());
+    if (iconClickType == "leftClick") {
+        Q_EMIT activated(QPlatformSystemTrayIcon::Trigger);
+    }
+}
+
+void QOhSystemTrayIcon::onRightMenuClick(const Napi::CallbackInfo &info)
+{
+    if (info.Length() < 1 || !info[0].IsObject()) {
+        return;
+    }
+    Napi::Object eventData = info[0].As<Napi::Object>();
+    if (!eventData.Has("data") || !eventData.Get("data").IsObject()) {
+        return;
+    }
+
+    Napi::Object data = eventData.Get("data").As<Napi::Object>();
+    if (!data.Has("menuCode") || !data.Get("menuCode").IsString()) {
+        return;
+    }
+
+    QString menuCode = QString::fromStdString(data.Get("menuCode").ToString());
+    quintptr tag = static_cast<quintptr>(menuCode.toULongLong(nullptr, 16));
+    QPlatformMenuItem *item = m_menu->menuItemForTag(tag);
+    if (item)
+        Q_EMIT item->activated();
+}
+
+void QOhSystemTrayIcon::updateMenu(QPlatformMenu *menu)
+{
+    if (!menu) {
+        m_menu = nullptr;
+        return;
+    }
+
+    QOhPlatformMenu *ohMenu = qobject_cast<QOhPlatformMenu *>(menu);
+    if (m_menu != ohMenu) {
+        disconnect(m_menu, 0, this , 0);
+        m_menu = ohMenu;
+        connect(ohMenu, &QOhPlatformMenu::menuUpdated, this, [this]() { updateMenu(m_menu); });
+    }
+
+    if (m_updateMenuPending == true)
+        return;
+
+    updateMenu_sys(ohMenu);
+}
+
+void QOhSystemTrayIcon::updateMenu_sys(QOhPlatformMenu *ohMenu)
+{
+    static qint64 lastCall = 0;
+    if (QDateTime::currentMSecsSinceEpoch() - lastCall < 20) {
+        qDebug() << "The interface is called too frequently, and the update has been delayed.";
+        m_updateMenuPending = true;
+        QTimer::singleShot(20, this, [this]() { updateMenu_sys(m_menu); });
+        return;
+    }
+
+    m_updateMenuPending = false;
+    if (!m_isInit || !m_statusManage)
+        return;
+
+    lastCall = QDateTime::currentMSecsSinceEpoch();
+    QtOh::runOnJsUIThreadAndWait([this, ohMenu]{
+        Napi::Array menus = createOhMenu(ohMenu);
+
+        QJsContext *context = qNativeWindowManager->context();
+        if (context) {
+            m_statusManage->call("updateStatusBarMenu", {context->object(), menus});
+
+            if (m_statusManage->hasError()) {
+                qWarning() << "updateStatusBarMenu failed:" << m_statusManage->lastError();
+            }
+        }
+    });
+}
+
+Napi::Value tsStatuBarActivate(const Napi::CallbackInfo& info) {
+    Napi::Env env = info.Env();
+    QOhSystemTrayIcon::setTsStatuActivate();
+    return Napi::Boolean::New(env, true);
+}
+
+void QOhSystemTrayIcon::init(Napi::Env env, Napi::Object exports)
+{
+    exports.Set(Napi::String::New(env, "tsStatuBarActivate"), Napi::Function::New(env, tsStatuBarActivate));
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohsystemtrayicon.h b/src/plugins/platforms/openharmony/qohsystemtrayicon.h
new file mode 100644
index 00000000000..72d55a600e1
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohsystemtrayicon.h
@@ -0,0 +1,91 @@
+#ifndef QOHSYSTEMTRAYICON_H
+#define QOHSYSTEMTRAYICON_H
+
+#include <QtGui/qicon.h>
+#include <QtGui/qpa/qplatformsystemtrayicon.h>
+#include <QJsObject>
+#include <QJsModule>
+
+QT_BEGIN_NAMESPACE
+
+class QDebug;
+class QOhPlatformMenu;
+class QOhJsOnListener;
+class QOpenHarmonyPopupMenu;
+
+class QOhSystemTrayIcon : public QPlatformSystemTrayIcon
+{
+    Q_OBJECT
+
+    enum ContentType {
+        BASIC_TEXT = 0,             /* 普通类型 */
+        LONG_TEXT,                  /* 长文本类型 */
+        PICTURE,                    /* 图片类型 */
+        CONVERSATION,               /* 不支持 */
+        MULTILINE,                  /* 多行文本类型 */
+    };
+
+    enum SlotType {
+        UNKNOWN_TYPE = 0,           /* 未知类型,LEVEL_MIN,仅通知中心 */
+        SOCIAL_COMMUNICATION,       /* 社交通信,LEVEL_HIGH,状态栏显示图标,有横幅提示音 */
+        SERVICE_INFORMATION,        /* 服务提醒,LEVEL_HIGH */
+        CONTENT_INFORMATION,        /* 内容资讯,LEVEL_MIN*/
+        OTHER_TYPES = 0xFFFF        /* 其他, */
+    };
+
+public:
+    QOhSystemTrayIcon();
+    ~QOhSystemTrayIcon() override;
+
+    void init() override;
+    void cleanup() override;
+    void updateIcon(const QIcon &iconLight, const QIcon &iconDark) override;
+    void updateIcon(const QIcon &icon) override;
+    void updateToolTip(const QString &tooltip) override;
+    QRect geometry() const override;
+    void showMessage(const QString &title, const QString &msg,
+                     const QIcon &icon, MessageIcon iconType, int msecs) override;
+    bool isSystemTrayAvailable() const override;
+    bool supportsMessages() const override { return true; }
+    QPlatformMenu *createMenu() const override;
+
+    static bool hasTrayIcon();
+    static void setTsStatuActivate(){g_tsTryIcon = true;}
+
+    static void init(Napi::Env env, Napi::Object exports);
+public slots:
+    void updateMenu(QPlatformMenu *) override;
+
+private:
+    Napi::Value pixFromQIcon(const QIcon &icon, const QSize &size);
+    Napi::Value pixFromQPixmap(const QPixmap &pix);
+    Napi::Array createOhMenu(QOhPlatformMenu *);
+    Napi::Array createSubMenu(QOhPlatformMenu *);
+    Napi::Array createDefaultMenu();
+    Napi::Object toNativeTrayIcon();
+    QSize getClosestIconSize(const QIcon &icon, const QSize &size);
+
+    void updateMenu_sys(QOhPlatformMenu *ohMenu);
+
+    void onStatusBarIconClick(const Napi::CallbackInfo &);
+    void onRightMenuClick(const Napi::CallbackInfo &);
+private:
+    QIcon m_iconLight;
+    QIcon m_iconDark;
+    QOhPlatformMenu *m_menu = nullptr;
+    QString m_toolTip;
+
+    bool m_updateMenuPending = false;
+
+    bool m_isInit;
+    static inline bool g_hasTrayIcon = false;
+    static inline bool g_tsTryIcon = false;
+
+    QJsModule *m_statusManage = nullptr;
+    QOhJsOnListener *m_statusBarIconClickListener = nullptr;
+    QOhJsOnListener *m_rightMenuClickListener = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHSYSTEMTRAYICON_H
diff --git a/src/plugins/platforms/openharmony/qohwindowcontext.cpp b/src/plugins/platforms/openharmony/qohwindowcontext.cpp
new file mode 100644
index 00000000000..baa8ea994ba
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohwindowcontext.cpp
@@ -0,0 +1,319 @@
+#include "qohwindowcontext.h"
+#include "qohplatformscreen.h"
+#include "qohplatformwindow.h"
+#include "qohplatformcursor.h"
+#include "qohplatformopenglwindow.h"
+#include "qohnormalwindow.h"
+#include "qohdisplay.h"
+#include <private/qopenharmony_p.h>
+#include <private/qjspromise_p.h>
+#include <QScreen>
+#include <QJsModule>
+#include <QAccessibleInterface>
+#include <QGuiApplication>
+#include <QRegularExpression>
+#include <qpa/qwindowsysteminterface.h>
+
+QT_BEGIN_NAMESPACE
+
+QList<QOhPlatformWindow *> QOhWindowContext::allWindows()
+{
+    return m_allWindows;
+}
+
+void QOhWindowContext::setFocusWindow(QWindow *window)
+{
+    if (window == m_focusWindow) {
+        return;
+    }
+    m_focusWindow = window;
+    if (m_focusWindow != nullptr && m_focusWindow->parent() == nullptr)
+        raiseWindow(dynamic_cast<QOhPlatformWindow *>(m_focusWindow->handle()));
+    QWindowSystemInterface::handleWindowActivated(m_focusWindow);
+}
+
+QWindow *QOhWindowContext::focusWindow()
+{
+    return m_focusWindow;
+}
+
+void QOhWindowContext::appendWindow(QOhPlatformWindow *window)
+{
+    if (window == nullptr || m_allWindows.contains(window))
+        return;
+    m_allWindows.prepend(window);
+    m_names << window->windowName();
+}
+
+void QOhWindowContext::removeWindow(QOhPlatformWindow *window)
+{
+    if (window == nullptr || !m_allWindows.contains(window))
+        return;
+    m_allWindows.removeOne(window);
+    m_names.removeOne(window->windowName());
+}
+
+void QOhWindowContext::raiseWindow(QOhPlatformWindow *window)
+{
+    int index = m_allWindows.indexOf(window);
+    if (index <= 0)
+        return;
+    m_allWindows.move(index, 0);
+}
+
+void QOhWindowContext::lowerWindow(QOhPlatformWindow *window)
+{
+    int index = m_allWindows.indexOf(window);
+    if (index == -1 || index == (m_allWindows.size() - 1))
+        return;
+    m_allWindows.move(index, m_allWindows.size() - 1);
+}
+
+QOhPlatformWindow *QOhWindowContext::findWindow(const std::function<bool (QOhPlatformWindow *)> &function)
+{
+    auto it = std::find_if(m_allWindows.constBegin(), m_allWindows.constEnd(), function);
+    return it == m_allWindows.constEnd() ? nullptr : *it;
+}
+
+QOhPlatformWindow *QOhWindowContext::get(QWindow *window)
+{
+    return findWindow([window](QOhPlatformWindow *pw){
+        return pw->window() == window;
+    });
+}
+
+QOhPlatformWindow *QOhWindowContext::get(const QString &name)
+{
+    return findWindow([name](QOhPlatformWindow *pw){
+        return pw->componentName() == name;
+    });
+}
+
+QOhPlatformWindow *QOhWindowContext::getByWindowName(const QString &name)
+{
+    return findWindow([name](QOhPlatformWindow *pw){
+        return pw->windowName() == name;
+    });
+}
+
+QOhPlatformWindow *QOhWindowContext::getByWindowId(int32_t nativeWindowId)
+{
+    return findWindow([nativeWindowId](QOhPlatformWindow *pw){
+        return pw->nativeWindowId() == nativeWindowId;
+    });
+}
+
+QString QOhWindowContext::uniqueName(const QOhPlatformWindow *window)
+{
+    auto qWindow = window->window();
+    QString name = qWindow->objectName();
+
+    static QRegularExpression re("^[a-zA-Z0-9_]+$");
+    if (name.isEmpty() || !re.match(name).hasMatch()) {
+        auto mo = qWindow->metaObject();
+        name = QString::fromLatin1(mo->className()) + "Window";
+    }
+
+    int counter = 1;
+    QString newName;
+    do {
+        newName = QString("%1_%2").arg(name).arg(counter);
+        counter++;
+    } while (m_names.contains(newName));
+
+    return newName;
+}
+
+void QOhWindowContext::setMouseGrabberWindow(QWindow *window)
+{
+    m_mouseGrabber = window;
+    m_underMouseWindow = window;
+}
+
+QWindow *QOhWindowContext::mouseGrabberWindow()
+{
+    return m_mouseGrabber.data();
+}
+
+void QOhWindowContext::setUnderMouseWindow(QPointer<QWindow> window)
+{    
+    m_underMouseWindow = window;
+    if (window.isNull() || !m_mouseGrabber.isNull())
+        return;
+    if (QOhPlatformOpenGLWindow *pw = dynamic_cast<QOhPlatformOpenGLWindow *>(window->handle())) {
+        pw->applyCursor();
+    }
+}
+
+void QOhWindowContext::setUnderMouseWindow(QPointer<QWindow> window, const QPoint &local, const QPoint &global)
+{    
+    static auto applyCursor = [](QPointer<QWindow> window)
+    {
+        if (window.isNull())
+            return;
+        if (QOhPlatformOpenGLWindow *pw = dynamic_cast<QOhPlatformOpenGLWindow *>(window->handle())) {
+            pw->applyCursor();
+        }
+    };
+    
+    static auto handleEnterLeave = [](QPointer<QWindow> window, const QPoint &local, const QPoint &global)
+    {
+        if (m_underMouseWindow != window) {
+            QWindow *leave = m_underMouseWindow.data();
+            m_underMouseWindow = window;
+            QWindowSystemInterface::handleEnterLeaveEvent(window, leave, local, global);
+            applyCursor(window);
+        }
+    };
+
+    static QPointer<QWindow> currentUnderMouseWindow;
+    if (m_mouseGrabber.isNull()) {
+        handleEnterLeave(window, local, global);
+        currentUnderMouseWindow = nullptr;
+    } else {
+        bool showApplyCursor = false;
+        if (currentUnderMouseWindow != window) {
+            currentUnderMouseWindow = window;
+            showApplyCursor = true;
+        }
+
+        if (showApplyCursor && !m_mouseGrabber.isNull() && currentUnderMouseWindow != nullptr) {
+            QWindow *topLevelWindow = topLevelOf(currentUnderMouseWindow);
+            QOhPlatformOpenGLWindow *overrideWindow = dynamic_cast<QOhPlatformOpenGLWindow *>(topLevelWindow->handle());
+            QOhPlatformOpenGLWindow *cursorWindow = dynamic_cast<QOhPlatformOpenGLWindow *>(m_mouseGrabber->handle());
+            if (overrideWindow && cursorWindow) {
+                QOhPlatformCursor::setWindowOverrideCursor(overrideWindow->nativeWindowId(), cursorWindow->cursor());
+            }
+        }
+    }
+}
+
+QWindow *QOhWindowContext::underMouseWindow()
+{
+    return m_underMouseWindow.data();
+}
+
+void QOhWindowContext::setKeyGrabberWindow(QWindow *window)
+{
+    m_keyGrabber = window;
+}
+
+QWindow *QOhWindowContext::keyGrabberWindow()
+{
+    return m_keyGrabber.data();
+}
+
+QWindow *QOhWindowContext::topLevelOf(QWindow *w, QWindow::AncestorMode mode)
+{
+    while (QWindow *parent = w->parent(mode))
+        w = parent;
+    return w;
+}
+
+QWindow *QOhWindowContext::getWindowByCoordinate(QOhPlatformScreen *screen, const QPoint &p)
+{
+    QOhPlatformScreen *_screen = screen;
+    if (_screen == nullptr)
+        _screen = dynamic_cast<QOhPlatformScreen *>(QGuiApplication::primaryScreen()->handle());
+    if (_screen == nullptr)
+        return nullptr;
+
+    /* FIXME wanghao 频繁调用 getWindowsByCoordinate造成卡顿 */
+#if OHOS_SDK_VERSION >= 14
+       QPoint pt = p - _screen->geometry().topLeft();
+       auto id = QtOh::runOnJsUIThreadWithPromise<uint32_t>([&](auto p, uint32_t displayId, const QPoint &pt) {
+           // 查询1个窗口,该窗口为最上层显示的窗口
+           if (m_jsWindowNamespace.isNull())
+               m_jsWindowNamespace.reset(new QJsModule("@ohos.window"));
+
+           Napi::Value result = m_jsWindowNamespace->call("getWindowsByCoordinate", { QNapi::create(displayId),
+                                                                                      QNapi::create(1),
+                                                                                      QNapi::create(pt.x()),
+                                                                                      QNapi::create(pt.y()) });
+           if (result.IsEmpty() || !result.IsPromise()) {
+               p->set_value(-1);
+               return;
+           }
+
+           QJsPromise promise(result.As<Napi::Promise>());
+           promise.onThen([p](const Napi::CallbackInfo &info) {
+               if (info.Length() == 0) {
+                   p->set_value(-1);
+                   return;
+               }
+               auto id = -1;
+               Napi::Array windows = info[0].As<Napi::Array>();
+               if (windows.Length() >= 1) {
+                   Napi::Value first = windows[uint32_t(0)];
+                   id = QOhNormalWindow::getWindowProperties(first.As<Napi::Object>()).id();
+               }
+               p->set_value(id);
+           }).onCatch([p](const Napi::CallbackInfo &info) {
+               Q_UNUSED(info)
+               p->set_value(-1);
+           });
+       }, _screen->display()->id(), pt);
+
+       if (QOhPlatformWindow *pw = QOhWindowContext::getByWindowId(id)) {
+           QWindow *ret = pw->window();
+           while (ret && !ret->isTopLevel())
+               ret = ret->parent();
+
+           return ret;
+       }
+
+       return nullptr;
+#else
+    return nullptr;
+#endif
+}
+
+QWindow *QOhWindowContext::topLevelAt(QOhPlatformScreen *screen, const QPoint &p)
+{
+    QOhPlatformScreen *_screen = screen;
+    if (_screen == nullptr)
+        _screen = dynamic_cast<QOhPlatformScreen *>(QGuiApplication::primaryScreen()->handle());
+    if (_screen == nullptr)
+        return nullptr;
+    QWindow *ret = nullptr;
+	/* Qt 6 only modify  std::as_const */
+    for (QOhPlatformWindow *w : std::as_const(m_allWindows)) {
+        auto window = w->window();
+        if (window->parent())
+            continue;
+        if (w->windowFrameGeometry().contains(p, false) && window->isVisible()) {
+            ret = window;
+            break;
+        }
+    }
+    return ret;
+}
+
+QWindow *QOhWindowContext::windowForInterface(QAccessibleInterface *accessible)
+{
+    QWindow *window = accessible->window();
+    if (!window) {
+        const QAccessibleInterface *acc = accessible;
+        const QAccessibleInterface *par = accessible->parent();
+        while (par && par->isValid() && !window) {
+            window = par->window();
+            acc = par;
+            par = par->parent();
+        }
+        if (!window) {
+            const auto appWindows = QGuiApplication::topLevelWindows();
+            for (QWindow *w : appWindows) {
+                if (QAccessibleInterface *root = w->accessibleRoot()) {
+                    int count = root->childCount();
+                    for (int i = 0; i < count; ++i) {
+                        if (root->child(i) == acc)
+                            return w;
+                    }
+                }
+            }
+        }
+    }
+    return window;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohwindowcontext.h b/src/plugins/platforms/openharmony/qohwindowcontext.h
new file mode 100644
index 00000000000..0bfa0611e98
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohwindowcontext.h
@@ -0,0 +1,58 @@
+#ifndef QOHWIDOWCONTEXT_H
+#define QOHWIDOWCONTEXT_H
+
+#include <QWindow>
+#include <QList>
+#include <QPointer>
+
+QT_BEGIN_NAMESPACE
+class QJsModule;
+class QOhPlatformWindow;
+class QOhPlatformScreen;
+
+class QOhWindowContext
+{
+public:
+    static QList<QOhPlatformWindow *> allWindows();
+    static void setFocusWindow(QWindow *window);
+    static QWindow *focusWindow();
+    static void appendWindow(QOhPlatformWindow *window);
+    static void removeWindow(QOhPlatformWindow *window);
+    static void raiseWindow(QOhPlatformWindow *window);
+    static void lowerWindow(QOhPlatformWindow *window);
+
+    static QOhPlatformWindow *get(QWindow *window);
+    static QOhPlatformWindow *get(const QString &name);
+    static QOhPlatformWindow *getByWindowName(const QString &name);
+    static QOhPlatformWindow *getByWindowId(int32_t nativeWindowId);
+    static QString uniqueName(const QOhPlatformWindow *window);
+    static void setMouseGrabberWindow(QWindow *window);
+    static QWindow *mouseGrabberWindow();
+    static void setUnderMouseWindow(QPointer<QWindow> window);
+    static void setUnderMouseWindow(QPointer<QWindow> window, const QPoint &local, const QPoint &global);
+    static QWindow *underMouseWindow();
+    static void setKeyGrabberWindow(QWindow *window);
+    static QWindow *keyGrabberWindow();
+
+    static QWindow *topLevelOf(QWindow *w, QWindow::AncestorMode mode = QWindow::ExcludeTransients);
+
+    static QWindow *getWindowByCoordinate(QOhPlatformScreen *screen, const QPoint &p);
+
+    static QWindow *topLevelAt(QOhPlatformScreen *screen, const QPoint &p);
+
+    static QWindow *windowForInterface(QAccessibleInterface *accessible);
+
+private:
+    static QOhPlatformWindow *findWindow(const std::function<bool(QOhPlatformWindow *)> &function);
+private:
+    static inline QWindow *m_focusWindow = nullptr;
+    static inline QList<QOhPlatformWindow *> m_allWindows = {};
+    static inline QStringList m_names = {};
+    static inline QPointer<QWindow> m_mouseGrabber = {};
+    static inline QPointer<QWindow> m_keyGrabber = {};
+    static inline QPointer<QWindow> m_underMouseWindow = {};
+    static inline QSharedPointer<QJsModule> m_jsWindowNamespace = {};
+};
+
+QT_END_NAMESPACE
+#endif // QOHWIDOWCONTEXT_H
diff --git a/src/plugins/platforms/openharmony/qohwindownode.cpp b/src/plugins/platforms/openharmony/qohwindownode.cpp
new file mode 100644
index 00000000000..fec35493e90
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohwindownode.cpp
@@ -0,0 +1,984 @@
+#include <QUrl>
+#include <QTimer>
+#include <QDebug>
+#include <cstdint>
+#include <qopenharmonydefines.h>
+#include <private/qguiapplication_p.h>
+#include <private/qopenharmony_p.h>
+
+#include "qohmain.h"
+#include "qohdrag.h"
+#include "qohevent.h"
+#include "qohnativewindow.h"
+#include "qohauxiliary.h"
+#include "qohwindownode.h"
+#include "qohxcomponent.h"
+#include "qohplatformscreen.h"
+#include "qohdisplaymanager.h"
+#include "qohplatformwindow.h"
+#include "qohnativenodeapi.h"
+#include "qohplatforminputcontext.h"
+#include "qohwindownodeeventhandler.h"
+#include "qohutility.h"
+
+#include <ace/xcomponent/native_interface_xcomponent.h>
+#include <arkui/drag_and_drop.h>
+
+
+QT_BEGIN_NAMESPACE
+
+#define Z_INDEX_MAX 2147483647
+#define Z_INDEX_SUBNODE_INIT 65536
+
+bool compare(QOhWindowNode *a, QOhWindowNode *b)
+{
+    return a->zIndex() < b->zIndex();
+}
+
+static QList<QOhWindowNode *> g_allNodes = QList<QOhWindowNode *>();
+
+constexpr char *xcIdstr = "window_component_";
+
+static QString XComponentName()
+{
+    static int index = 1;
+    static const QString prefix = QString::fromUtf8(xcIdstr);
+    return prefix + QString::number(index++);
+}
+
+QOhWindowNode::QOhWindowNode(QOhWindowNode *parent)
+    : m_parent(parent)
+    , m_eventHandler(nullptr)
+    , m_window(nullptr)
+    , m_ownerWindow(nullptr)
+    , m_component(nullptr)
+    , m_id(nullptr)
+{
+    g_allNodes << this;
+    QtOh::runOnJsUIThreadAndWait([=]{
+        m_nodeApi = QOhNativeNodeAPI::getOrCreateForNode(this);
+    });
+}
+
+QOhWindowNode::~QOhWindowNode()
+{
+    QtOh::runOnJsUIThreadAndWait([this]{
+        clear();
+    });
+
+    g_allNodes.removeOne(this);
+    for (int i = 0; i < m_deleteChildren.count(); ++i) {
+        auto subNode = m_deleteChildren.at(i);
+        delete subNode;
+    }
+    m_deleteChildren.clear();
+    if (m_component != nullptr) {
+        delete m_component;
+        m_component = nullptr;
+    }
+
+    if (m_eventHandler != nullptr) {
+        delete m_eventHandler;
+    }
+
+    if (m_eglSurface != EGL_NO_SURFACE)
+        eglDestroySurface(m_display, m_eglSurface);
+
+    if (m_id != nullptr && m_isIdCreateByQt) {
+        delete m_id;
+        m_id = nullptr;
+    }
+    if (m_parent != nullptr) {
+        m_parent->m_children.removeOne(this);
+    }
+}
+
+bool QOhWindowNode::nodeDestroyed(QOhWindowNode *node)
+{
+    return !g_allNodes.contains(node);
+}
+
+QOhWindowNode *QOhWindowNode::focusNode()
+{
+    for (int i = 0; i < g_allNodes.count(); ++i) {
+        auto node = g_allNodes.at(i);
+        bool f = node->isFocused();
+        if (f) {
+            return node;
+        }
+    }
+    return nullptr;
+}
+
+bool QOhWindowNode::isQtNode(const QString &name)
+{
+    return name.startsWith(QString(xcIdstr));
+}
+
+void QOhWindowNode::attachPlatformWindow(QOhPlatformWindow *window)
+{
+    m_window = window;
+    if (m_eventHandler != nullptr && window != nullptr)
+        m_eventHandler->setTargetWindow(window->window());
+}
+
+void QOhWindowNode::setOwnerWindow(QOhNativeWindow *window)
+{
+    m_ownerWindow = window;
+}
+
+static QOhWindowNode *topNode(QOhWindowNode *node)
+{
+    QOhWindowNode *n = node;
+    while (n->parent() != nullptr) {
+        n = n->parent();
+    }
+    return n;
+}
+
+QOhNativeWindow *QOhWindowNode::ownerWindow() const
+{
+    // 返回node所在的js窗口,子node返回顶层node的window
+    if (m_ownerWindow != nullptr)
+        return m_ownerWindow;
+    QOhWindowNode *top = topNode(const_cast<QOhWindowNode*>(this));
+    return top->m_ownerWindow;
+}
+
+void QOhWindowNode::attachRootComponent(void *component)
+{
+    if (component == nullptr)
+        return;
+
+    m_topComponent = reinterpret_cast<OH_NativeXComponent *>(component);
+    if (m_topComponent != nullptr) {
+        QtOh::runOnJsUIThreadNoWait([this]{
+            if (m_ownerWindow && m_ownerWindow->isDestroyed()) {
+                qWarning() << "attachRootComponent failed , native window is destroyed!";
+                return;
+            }
+
+            int32_t result = OH_NativeXComponent_AttachNativeRootNode(m_topComponent, m_stack);
+            if (result != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+                LOGE("%{public}s attach root node failed: %{public}d", qPrintable(componentName()), result);
+            } else {
+                move(0, 0);
+                setSizeAdaptive();
+                LOGI("%{public}s attach root node success", qPrintable(componentName()));
+            }
+        });
+    }
+}
+
+void QOhWindowNode::detachRootComponent(bool isDestroy)
+{
+    if (m_topComponent != nullptr) {
+        QtOh::runOnJsUIThreadAndWait([this]{
+            if (m_ownerWindow && m_ownerWindow->isDestroyed())
+                return;
+
+            int32_t result = OH_NativeXComponent_DetachNativeRootNode(m_topComponent, m_stack);
+            if (result != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+                LOGE("%{public}s detach root node failed: %{public}d", qPrintable(componentName()), result);
+            } else {
+                LOGI("%{public}s detach root node success", qPrintable(componentName()));
+            }
+        });
+
+        if (isDestroy)
+            m_topComponent = nullptr;
+    }
+}
+
+QString QOhWindowNode::componentName() const
+{
+    if (m_component == nullptr)
+        return QString();
+    return m_component->name();
+}
+
+void QOhWindowNode::setComponent(QOhXComponent *component)
+{
+    if (component == nullptr)
+        return;
+    m_component = component;
+}
+
+void QOhWindowNode::setNativeWindow(void *nativeWindow)
+{
+    m_nativeWindow = nativeWindow;
+    if (m_nativeWindow != nullptr) {
+        m_nativeWindowPromise.set_value();
+    }
+    if (m_id) {
+        WindowNode *wNode = reinterpret_cast<WindowNode *>(m_id);
+        wNode->window = nativeWindow;
+    }
+}
+
+OH_NativeXComponent *QOhWindowNode::component() const
+{
+    if (m_component == nullptr)
+        return nullptr;
+    return m_component->nativeComponent();
+}
+
+EGLSurface QOhWindowNode::eglSurface(EGLDisplay display, EGLConfig config)
+{
+    m_display = display;
+    if (m_nativeWindow == nullptr) {
+        return m_eglSurface;
+    }
+
+    if (m_eglSurface == EGL_NO_SURFACE) {
+        /*openharmony 上该段代码会导致eglSwapBuffers执行报错:EGL_BAD_ALLOC*/
+        if (!QtOh::isOpenHarmonyDevice()) {
+            EGLint native_visual_id(0);
+            if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &native_visual_id)) {
+                LOGE("eglGetConfigAttrib EGL_NATIVE_VISUAL_ID failed: [%{public}d]", eglGetError());
+            }
+            /* FIXME qml 弹窗黑屏 */
+            if (auto nativeWindow = reinterpret_cast<OHNativeWindow*>(m_nativeWindow)) {
+                int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, native_visual_id);
+                LOGI("call OH_NativeWindow_NativeWindowHandleOpt status: [%{public}d]", ret);
+            }
+        }
+
+        m_eglSurface = eglCreateWindowSurface(display,
+                                              config,
+                                              reinterpret_cast<EGLNativeWindowType>(m_nativeWindow), nullptr);
+        if (m_eglSurface == nullptr) {
+            LOGE("eglCreateWindowSurface: unable to create surface %{public}d", eglGetError());
+        }
+    }
+
+    return m_eglSurface;
+}
+
+QOhWindowNode *QOhWindowNode::parent() const
+{
+    return m_parent;
+}
+
+void QOhWindowNode::setParent(QOhWindowNode *parent)
+{
+    if (m_xcomponent == nullptr || m_stack == nullptr)
+        return;
+
+    QtOh::runOnJsUIThreadAndWait([&]{
+        if (m_parent == parent)
+            return;
+        if (!m_nodeApi->has(&ArkUI_NativeNodeAPI_1::removeChild) || !m_nodeApi->has(&ArkUI_NativeNodeAPI_1::addChild)) {
+            LOGE("setParent nodeAPI nullptr error");
+            return;
+        }
+
+        if (m_stack == nullptr) {
+            LOGE("setParent stack nullptr error");
+            return;
+        }
+
+        if (m_parent != nullptr && m_parent->m_stack != nullptr) {
+            m_nodeApi->removeChild(m_parent->m_stack, m_stack);
+            m_parent->m_children.removeOne(this);
+        } else {
+            LOGI("setParent the old parent do not need removeChild");
+        }
+
+        if (parent != nullptr) {
+            if (m_topComponent != nullptr) {
+                detachRootComponent();
+            }
+            auto newParentStack = parent->m_stack;
+            if (newParentStack != nullptr) {
+                m_nodeApi->addChild(newParentStack, m_stack);
+            } else {
+                LOGW("setParent the new parent addChild error");
+            }
+            parent->m_children << this;
+        } else if (m_parent != nullptr && m_topComponent) {
+            /*之前是rootNode,然后setParent(A),再次setParent(null)时,需要重新attach*/
+            attachRootComponent(m_topComponent);
+        }
+        m_parent = parent;
+    });
+}
+
+QOhWindowNode *QOhWindowNode::fromId(WId id)
+{
+    Node *node = reinterpret_cast<Node *>(id);
+    if (node == nullptr)
+        return nullptr;
+    if (std::strcmp(node->nodeOwner, "Qt") == 0) {
+        QOhWindowNode *wn = reinterpret_cast<QOhWindowNode *>(node->nodePrivate);
+        return wn;
+    } else {
+        for (int i = 0; i < g_allNodes.count(); ++i) {
+            auto temp = g_allNodes.at(i);
+            if (temp->m_stack == node->container && temp->m_xcomponent == node->node) {
+                if (temp->m_id != node) {
+                    if (temp->m_isIdCreateByQt) {
+                        delete temp->m_id;
+                    }
+                    temp->m_id = node;
+                    temp->m_isIdCreateByQt = (std::strcmp(node->nodeOwner, "QtInner") == 0);
+                }
+                return temp;
+            }
+        }
+        QOhWindowNode *wn = new QOhWindowNode;
+        wn->m_stack = node->container;
+        wn->m_xcomponent = node->node;
+        wn->m_id = node;
+        wn->m_isExternal = true;
+        wn->m_isIdCreateByQt = (std::strcmp(node->nodeOwner, "QtInner") == 0);
+        auto api = wn->nodeApi();
+        api->attach(wn->m_stack);
+        api->attach<QOhNativeNodeAPI::XCompoentType>(wn->m_xcomponent);
+        return QtOh::runOnJsUIThreadWithResult([=]{
+            if (wn->m_stack == nullptr) {
+                wn->m_stack = api->createNode(ARKUI_NODE_STACK);
+                api->setAttribute(NODE_ACCESSIBILITY_ROLE, (uint32_t)ARKUI_NODE_STACK);
+                api->setAttribute(NODE_STACK_ALIGN_CONTENT, ARKUI_ALIGNMENT_TOP_START);
+                // set NODE_Z_INDEX
+                api->setAttribute(NODE_Z_INDEX, Z_INDEX_SUBNODE_INIT);
+                node->container = wn->m_stack;
+                api->addChild(wn->m_stack, wn->m_xcomponent);
+            }
+            auto nativeParentStack = api->parent(wn->m_stack);
+            if (nativeParentStack != nullptr) {
+                for (int i = 0; i < g_allNodes.count(); ++i) {
+                    auto p = g_allNodes.at(i);
+                    if (nativeParentStack == p->m_stack) {
+                        wn->m_parent = p;
+                        p->m_children << wn;
+                    }
+                }
+            }
+            api->setLengthMetricUnit(ARKUI_LENGTH_METRIC_UNIT_PX);
+            wn->createNodeEventHandler();
+            wn->m_eventHandler->registerEvents({NODE_ON_MOUSE, NODE_ON_HOVER});
+            return wn;
+        });
+    }
+    // Todo other framework id
+    return nullptr;
+}
+
+void QOhWindowNode::setGeometry(const QRect &rect)
+{
+    if (m_parent == nullptr || m_window == nullptr)
+        return;
+    QRectF r(rect);
+    QtOh::runOnJsUIThreadAndWait([this, r]{
+        if (!m_nodeApi->has(&ArkUI_NativeNodeAPI_1::setAttribute)) {
+            LOGE("set geometry node nodeAPI nullptr error");
+            return;
+        }
+
+        m_nodeApi->setAttribute(NODE_WIDTH, static_cast<float>(r.width()));
+        m_nodeApi->setAttribute(NODE_HEIGHT, static_cast<float>(r.height()));
+        m_nodeApi->setAttribute(NODE_POSITION, static_cast<float>(r.x()), static_cast<float>(r.y()));
+        //m_nodeApi->setAttribute(NODE_XCOMPONENT_SURFACE_SIZE, static_cast<uint32_t>(r.width()), static_cast<uint32_t>(r.height()));
+#if OHOS_SDK_VERSION >= 18
+        m_nodeApi->setAttribute(NODE_XCOMPONENT_SURFACE_RECT, static_cast<int32_t>(r.x()), static_cast<int32_t>(r.y()),
+                                static_cast<int32_t>(r.width()), static_cast<int32_t>(r.height()));
+#endif
+    });
+}
+
+void QOhWindowNode::handleSurfaceChanged(const QSize &size)
+{
+    Q_UNUSED(size)
+    if (m_window == nullptr || m_parent != nullptr || m_ownerWindow == nullptr)
+        return;
+
+    // 如果QWidget主动设置大小,reportWindowGeometry不会导致窗口重新绘制,而Qt在主动设置大小之后绘制时,
+    // 由于异步系统窗口大小还未正确改变成设置的大小,导致绘制不完整,如果大小和Qt窗口大小一直,强制绘制。
+    QRect nativeRect = m_ownerWindow->geometry();
+    QMargins m = m_ownerWindow->frameMargins();
+    nativeRect -= m;
+    QRect qtRect = m_window->geometry();
+    if (qtRect.size() == nativeRect.size()) {
+        m_window->fireFullExpose();
+    }
+    m_ownerWindow->reportWindowGeometry();
+}
+
+void QOhWindowNode::setVisible(bool visible)
+{
+    if (visible && m_isExternal)
+        handleSubNodes(this);
+
+    if (m_stack == nullptr)
+        return;
+    QtOh::runOnJsUIThreadAndWait([&]{
+        m_nodeApi->setAttribute(NODE_VISIBILITY, visible ? ARKUI_VISIBILITY_VISIBLE : ARKUI_VISIBILITY_HIDDEN);
+    });
+}
+
+void QOhWindowNode::setNodeFocus(bool isFocus)
+{
+    if (m_xcomponent == nullptr)
+        return;
+
+    QtOh::runOnJsUIThreadAndWait([this, isFocus]{
+        m_nodeApi->setAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_FOCUS_STATUS, isFocus);
+    });
+}
+
+bool QOhWindowNode::isFocused() const
+{
+    if (m_xcomponent == nullptr)
+        return false;
+
+    return QtOh::runOnJsUIThreadWithResult([this]{
+        const ArkUI_AttributeItem *item = m_nodeApi->getAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_FOCUS_STATUS);
+        return item == nullptr ? false : item->value[0].i32 == 1;
+    });
+}
+
+bool QOhWindowNode::isVisible() const
+{
+    if (m_stack == nullptr)
+        return false;
+
+    return QtOh::runOnJsUIThreadWithResult([this]{
+        const ArkUI_AttributeItem *item = m_nodeApi->getAttribute(NODE_VISIBILITY);
+        return item == nullptr ? false : item->value[0].i32 == ARKUI_VISIBILITY_VISIBLE;
+    });
+}
+
+void QOhWindowNode::setSizeAdaptive()
+{
+    QtOh::runOnJsUIThreadAndWait([&]{
+        // set stack scale percent
+        m_nodeApi->setAttribute(NODE_WIDTH_PERCENT, 1.0f);
+        m_nodeApi->setAttribute(NODE_HEIGHT_PERCENT, 1.0f);
+    });
+}
+
+void QOhWindowNode::handleSubNodes(QOhWindowNode *parent)
+{
+    if (parent == nullptr || !QOhNativeNodeAPI::has(&ArkUI_NativeNodeAPI_1::getTotalChildCount)
+            || !QOhNativeNodeAPI::has(&ArkUI_NativeNodeAPI_1::getChildAt))
+        return;
+
+    auto nodeAPI = QOhNativeNodeAPI::nativeNodeAPI();
+    auto stack = parent->m_stack;
+    auto subCount = nodeAPI->getTotalChildCount(stack);
+    if (subCount <= 1)
+        return;
+
+    for (uint i = 1; i < subCount; i++) {
+        auto handle = nodeAPI->getChildAt(stack, i);
+        if (!handle)
+            continue;
+        if (OH_ArkUI_NodeUtils_GetNodeType(handle) != ARKUI_NODE_STACK)
+            continue;
+
+        auto count = nodeAPI->getTotalChildCount(handle);
+        if (count == 0)
+            continue;
+
+        auto xcomponent = nodeAPI->getChildAt(handle, 0);
+        if (!xcomponent)
+            continue;
+        if (exist(handle, xcomponent))
+            continue;
+
+        Node *id = new Node;
+        id->nodeType = ARKUI_NODE_XCOMPONENT;
+        id->node = handle;
+        id->container = xcomponent;
+        memset(id->nodeOwner, 0, 8);
+        // Qt internal
+        strcpy(id->nodeOwner, "QtInner");
+        auto wn = QOhWindowNode::fromId(reinterpret_cast<WId>(id));
+        parent->m_deleteChildren << wn;
+        handleSubNodes(wn);
+    }
+}
+
+bool QOhWindowNode::exist(ArkUI_NodeHandle stack, ArkUI_NodeHandle xcomponent)
+{
+    for (int i = 0; i < g_allNodes.count(); ++i) {
+        auto node = g_allNodes.at(i);
+        if (node->m_stack == stack && node->m_xcomponent == xcomponent)
+            return true;
+    }
+    return false;
+}
+
+WId QOhWindowNode::id() const
+{
+    WId ret = reinterpret_cast<WId>(m_id);
+    return ret;
+}
+
+OH_PixelmapNative *QOhWindowNode::grab()
+{
+#if OHOS_SDK_VERSION >= 15
+    if (m_stack == nullptr)
+        return nullptr;
+    auto option = OH_ArkUI_CreateSnapshotOptions();
+    OH_ArkUI_SnapshotOptions_SetScale(option, 1.0f);
+    OH_PixelmapNative *result = nullptr;
+    OH_ArkUI_GetNodeSnapshot(m_stack, option, &result);
+    OH_ArkUI_DestroySnapshotOptions(option);
+    return result;
+#else
+    if (m_nativeWindow == nullptr)
+        return nullptr;
+    return QtOh::runOnJsUIThreadWithResult([this]{
+        uint64_t surfaceId = 0;
+        OH_NativeWindow_GetSurfaceId(reinterpret_cast<OHNativeWindow *>(m_nativeWindow), &surfaceId);
+        static QJsModule image("@ohos.multimedia.image");
+        Napi::Value pixelMap = image.call("createPixelMapFromSurfaceSync", {Napi::String::New(image.env(), QString::number(surfaceId).toStdString())});
+        OH_PixelmapNative *result = nullptr;
+        OH_PixelmapNative_ConvertPixelmapNativeFromNapi(image.env(), pixelMap, &result);
+        return result;
+    });
+#endif
+}
+
+void QOhWindowNode::raise()
+{
+    if (m_stack == nullptr || m_parent == nullptr)
+        return;
+    QtOh::runOnJsUIThreadAndWait([&]{
+        if (m_parent == nullptr) {
+            LOGE("raise node parent nullptr error");
+            return;
+        }
+        int32_t newZIndex = subNodeMaxZIndex(m_parent);
+        if (newZIndex == m_zIndex) {
+            LOGI("node already on the top, index: %{public}d", newZIndex);
+            return;
+        }
+        if (newZIndex >= Z_INDEX_MAX) {
+            LOGE("raise node index invalid, index: %{public}d", newZIndex);
+            return;
+        }
+        if (!m_nodeApi->has(&ArkUI_NativeNodeAPI_1::setAttribute)) {
+            LOGE("raise nodeAPI nullptr error");
+            return;
+        }
+        newZIndex++;
+        m_nodeApi->setAttribute(NODE_Z_INDEX, newZIndex);
+        m_zIndex = newZIndex;
+        LOGI("raise node newZIndex = %{public}d", newZIndex);
+    });
+}
+
+void QOhWindowNode::lower()
+{
+    if (m_stack == nullptr || m_parent == nullptr)
+        return;
+    QtOh::runOnJsUIThreadAndWait([&]{
+        if (m_parent == nullptr) {
+            LOGE("lower node parent nullptr error");
+            return;
+        }
+        int32_t newZIndex = subNodeMinZIndex(m_parent);
+        if (newZIndex == m_zIndex) {
+            LOGI("lower node already at the bottom, index: %{public}d", newZIndex);
+            return;
+        }
+        if (newZIndex <= 1) {
+            LOGE("lower node node index error, index: %{public}d", newZIndex);
+            return;
+        }
+        if (!m_nodeApi->has(&ArkUI_NativeNodeAPI_1::setAttribute)) {
+            LOGE("lower nodeAPI nullptr error");
+            return;
+        }
+        newZIndex = newZIndex - 1;
+        m_nodeApi->setAttribute(NODE_Z_INDEX, newZIndex);
+        m_zIndex = newZIndex;
+        LOGI("lowerEWNode lowerNode = %{public}d", newZIndex);
+    });
+}
+
+void QOhWindowNode::move(int x, int y)
+{
+    if (m_stack == nullptr)
+        return;
+    QtOh::runOnJsUIThreadAndWait([&]{
+        if (!m_nodeApi->has(&ArkUI_NativeNodeAPI_1::setAttribute)) {
+            LOGE("move nodeAPI nullptr error");
+            return;
+        }
+
+        m_nodeApi->setAttribute(NODE_POSITION, static_cast<float>(x), static_cast<float>(y));
+    });
+}
+
+QRectF QOhWindowNode::geometry() const
+{
+    if (m_stack == nullptr)
+        return QRectF();
+    return QtOh::runOnJsUIThreadWithResult([this]{
+        float x = 0;
+        float y = 0;
+        float w = 0;
+        float h = 0;
+        const ArkUI_AttributeItem *item = m_nodeApi->getAttribute(NODE_WIDTH);  // NODE_WIDTH_PERCENT
+        if (item != nullptr && item->size == 1)
+            w = item->value[0].f32;
+        else {
+            item = m_nodeApi->getAttribute(NODE_WIDTH_PERCENT);
+            if (item != nullptr && item->size == 1)
+                w = item->value[0].f32;
+        }
+        item = m_nodeApi->getAttribute(NODE_HEIGHT);
+        if (item != nullptr && item->size == 1)
+            h = item->value[0].f32;
+        else {
+            item = m_nodeApi->getAttribute(NODE_HEIGHT_PERCENT);
+            if (item != nullptr && item->size == 1)
+                h = item->value[0].f32;
+        }
+        item = m_nodeApi->getAttribute(NODE_POSITION);
+        if (item != nullptr && item->size == 2) {
+            x = item->value[0].f32;
+            y = item->value[1].f32;
+        }
+        return QRect(x, y, w, h);
+    });
+}
+
+QSize QOhWindowNode::surfaceSize() const
+{
+    if (m_component == nullptr)
+        return QSize();
+
+    uint64_t w;
+    uint64_t h;
+    if (void *nativeW = reinterpret_cast<void*>(m_nativeWindow)) {
+        int32_t ret = OH_NativeXComponent_GetXComponentSize(m_component->nativeComponent(), nativeW, &w, &h);
+        if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+            LOGE("Get surface size failed");
+            return QSize();
+        }
+        return QSize(w, h);
+    }
+    return QSize();
+}
+
+QColor QOhWindowNode::backgroundColor() const
+{
+    if (m_xcomponent == nullptr)
+        return QColor();
+
+    return QtOh::runOnJsUIThreadWithResult([&]{
+        const ArkUI_AttributeItem *item = m_nodeApi->getAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_BACKGROUND_COLOR);
+        if (nullptr == item)
+            return QColor();
+
+        return QColor::fromRgba(item->value[0].u32);
+    });
+}
+
+void QOhWindowNode::setBackgroundColor(const QColor &color)
+{
+    if (m_xcomponent == nullptr)
+        return;
+
+
+    qInfo() << "set xc background-color:"<< color << QString::number(color.rgba(), 16);
+
+    QtOh::runOnJsUIThreadAndWait([&]{
+        m_nodeApi->setAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_BACKGROUND_COLOR, (uint32_t)color.rgba());
+    });
+}
+
+void QOhWindowNode::setWindowFlags(Qt::WindowFlags flags)
+{
+    if (flags.testFlag(Qt::WindowStaysOnTopHint)) {
+        m_zIndex = INT_MAX/2;
+        /* TODO up zIndex */
+    }
+
+    if (flags.testFlag(Qt::WindowStaysOnBottomHint)) {
+        m_zIndex = 0;
+        /* TODO down zIndex */
+    }
+    /* TODO other flags */
+}
+
+QOhPlatformWindow *QOhWindowNode::platformWindow() const
+{
+    return m_window;
+}
+
+bool QOhWindowNode::isExternal() const
+{
+    return m_isExternal;
+}
+
+int32_t QOhWindowNode::zIndex() const
+{
+    return m_zIndex;
+}
+
+void QOhWindowNode::createOSRootNode(const QString &id, const QRectF &rect, bool scale)
+{
+    createOSNode(nullptr, id, rect, scale);
+}
+
+void QOhWindowNode::createOSChildNode(QOhWindowNode *parentNode, const QString &id, const QRectF &rect, bool scale)
+{
+    createOSNode(parentNode, id, rect, scale);
+}
+
+void QOhWindowNode::createOSNode(QOhWindowNode *parentNode, const QString &id, const QRectF &rect, bool scale)
+{
+    QtOh::runOnJsUIThreadAndWait([=]{
+        LOGI("createEWNode enter");
+        if (!m_nodeApi->has(&ArkUI_NativeNodeAPI_1::createNode) || !m_nodeApi->has(&ArkUI_NativeNodeAPI_1::addChild)
+                || !m_nodeApi->has(&ArkUI_NativeNodeAPI_1::setAttribute) || !m_nodeApi->has(&ArkUI_NativeNodeAPI_1::disposeNode)) {
+            LOGE("native node api function nullptr error!");
+            return;
+        }
+        ArkUI_NodeHandle parentStack = nullptr;
+        int32_t curZINdex = Z_INDEX_SUBNODE_INIT;
+        if (parentNode != nullptr) {
+            LOGI("createNode: parentNode exits");
+            parentStack = parentNode->m_stack;
+            curZINdex = subNodeMaxZIndex(parentNode) + 1;
+            LOGI("createNode: curZINdex = %{public}d", curZINdex);
+        }
+
+        /* create stack */
+        ArkUI_NodeHandle stack = m_nodeApi->createNode(ARKUI_NODE_STACK);
+        if (stack == nullptr) {
+            LOGE("createNode: create stack nullptr error!");
+            return;
+        }
+
+        /* set metric unit */
+        m_nodeApi->setLengthMetricUnit(ARKUI_LENGTH_METRIC_UNIT_PX);
+        if (scale) {
+            /* set stack scale percent */
+            m_nodeApi->setAttribute(NODE_WIDTH_PERCENT, static_cast<float>(rect.width()));
+            m_nodeApi->setAttribute(NODE_HEIGHT_PERCENT, static_cast<float>(rect.height()));
+        } else {
+            /* set stack size */
+            m_nodeApi->setAttribute(NODE_WIDTH, static_cast<float>(rect.width()));
+            m_nodeApi->setAttribute(NODE_HEIGHT, static_cast<float>(rect.height()));
+        }
+
+        /* set NODE_STACK_ALIGN_CONTENT */
+        m_nodeApi->setAttribute(NODE_STACK_ALIGN_CONTENT, ARKUI_ALIGNMENT_TOP_START);
+        /* set NODE_Z_INDEX */
+        m_nodeApi->setAttribute(NODE_Z_INDEX, curZINdex);
+        /* set stack position */
+        m_nodeApi->setAttribute(NODE_POSITION, static_cast<float>(rect.x()), static_cast<float>(rect.y()));
+        /* set node clip */
+        m_nodeApi->setAttribute(NODE_CLIP, 1);
+
+        /* create xcomponent */
+        ArkUI_NodeHandle xc = m_nodeApi->createNode(ARKUI_NODE_XCOMPONENT);
+        if (xc == nullptr) {
+            m_nodeApi->disposeNode();
+            LOGE("createNode: createNode type ARKUI_NODE_XCOMPONENT failed!");
+            return;
+        }
+
+        /* set node id */
+        QByteArray idArray = id.toUtf8();
+        const char *_id = idArray.constData();
+        m_nodeApi->setAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_ID, _id);
+        /* set xcomponent id */
+        m_nodeApi->setAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_XCOMPONENT_ID, _id);
+        /* set xcomponent type */
+        m_nodeApi->setAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_XCOMPONENT_TYPE, ARKUI_XCOMPONENT_TYPE_SURFACE);
+        /* set xcomponent focusable */
+        m_nodeApi->setAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_FOCUSABLE, 1);
+        /* set xcomponent focus on touch */
+        m_nodeApi->setAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_FOCUS_ON_TOUCH, 1);
+        /* set node render fit */
+        m_nodeApi->setAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_RENDER_FIT, ARKUI_RENDER_FIT_TOP_LEFT);
+        /* set NODE_FOCUS_STATUS */
+        m_nodeApi->setAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_FOCUS_STATUS, 1);
+        /* set xcompoent Z Index */
+        m_nodeApi->setAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_Z_INDEX, 1);
+        m_nodeApi->addChild(stack, xc);
+        m_stack = stack;
+        m_xcomponent = xc;
+        m_zIndex = curZINdex;
+
+        if (parentStack != nullptr) {
+            m_nodeApi->addChild(parentStack, stack);
+        }
+
+        if (parentNode != nullptr) {
+            parentNode->m_children << this;
+        }
+        LOGI("createNode end");
+    });
+}
+
+void QOhWindowNode::createNodeEventHandler()
+{
+    m_eventHandler = new QOhWindowNodeEventHandler(this);
+    if (m_window != nullptr)
+        m_eventHandler->setTargetWindow(m_window->window());
+}
+
+void QOhWindowNode::setFocusOnTouch(bool focusOnTouch)
+{
+    QtOh::runOnJsUIThreadAndWait([&]{
+        m_nodeApi->setAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_FOCUS_ON_TOUCH, focusOnTouch);
+    });
+}
+
+int32_t QOhWindowNode::subNodeMaxZIndex(QOhWindowNode *node)
+{
+    if (node == nullptr) {
+        LOGW("getSubNodeMaxZIndex nullptr error");
+        return Z_INDEX_SUBNODE_INIT;
+    }
+    auto childList = node->m_children;
+    std::sort(childList.begin(), childList.end(), compare);
+
+    return childList.size() > 0 ? childList.back()->zIndex() : Z_INDEX_SUBNODE_INIT;
+}
+
+int32_t QOhWindowNode::subNodeMinZIndex(QOhWindowNode *node)
+{
+    if (node == nullptr) {
+        LOGW("getSubNodeMinZIndex nullptr error");
+        return 0;
+    }
+    auto childList = node->m_children;
+    std::sort(childList.begin(), childList.end(), compare);
+    return childList.size() > 0 ? childList.front()->zIndex() : Z_INDEX_SUBNODE_INIT;
+}
+
+QSharedPointer<QOhNativeNodeAPI> QOhWindowNode::nodeApi() const
+{
+    return m_nodeApi;
+}
+
+#if QT_CONFIG(vulkan)
+#include <qohplatformvulkaninstance.h>
+VkSurfaceKHR *QOhWindowNode::vkSurface() const
+{
+    if (m_vkSurface != VK_NULL_HANDLE) {
+        return &m_vkSurface;
+    }
+    if (m_window == nullptr)
+        return nullptr;
+    if (m_window->window()->surfaceType() == QSurface::VulkanSurface) {
+        QVulkanInstance *inst = m_window->window()->vulkanInstance();
+        if (inst)
+            m_vkSurface = static_cast<QOhPlatformVulkanInstance *>(inst->handle())->createSurface(m_nativeWindow);
+        else
+            qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?");
+        return &m_vkSurface;
+    }
+    return nullptr;
+}
+#endif
+
+void QOhWindowNode::setRenderFit(ArkUI_RenderFit fit)
+{
+    if (m_nodeApi)
+        m_nodeApi->setAttribute<QOhNativeNodeAPI::XCompoentType>(NODE_RENDER_FIT, fit);
+}
+
+void QOhWindowNode::clear()
+{
+    if (m_xcomponent == nullptr || m_stack == nullptr)
+        return;
+
+    m_eventHandler->unregisterEvents();
+    if (!m_nodeApi->has(&ArkUI_NativeNodeAPI_1::removeChild)) {
+        LOGE("remove child node function nullptr error");
+        return;
+    }
+    if (m_parent != nullptr) {
+        m_parent->m_children.removeOne(this);
+        auto parentStack = m_parent->m_stack;
+        if (parentStack != nullptr && m_stack != nullptr) {
+            m_nodeApi->removeChild(parentStack, m_stack);
+        }
+    }
+    if (!m_isExternal) {
+        if (m_stack != nullptr && m_xcomponent != nullptr) {
+            m_nodeApi->removeChild(m_stack, m_xcomponent);
+        }
+        if (m_stack != nullptr) {
+            m_nodeApi->disposeNode();
+        }
+        if (m_xcomponent != nullptr) {
+            m_nodeApi->disposeNode<QOhNativeNodeAPI::XCompoentType>();
+        }
+    }
+}
+
+void QOhWindowNode::createNode(const QRectF &rect, bool isFocusable)
+{
+    auto feature = m_nativeWindowPromise.get_future();
+    WindowNode *id = new WindowNode;
+    m_id = id;
+    id->nodeType = ARKUI_NODE_XCOMPONENT;
+    id->node = nullptr;
+    id->container = nullptr;
+    memset(id->nodeOwner, 0, 8);
+    strcpy(id->nodeOwner, "Qt");
+    id->nodePrivate = this;
+    id->window = nullptr;
+    QtOh::runOnJsUIThreadAndWait([this, rect, isFocusable]{
+        bool root = m_parent == nullptr;
+        if (root) {
+            QRectF r = QRectF(0, 0, 1.0f, 1.0f);
+            createOSRootNode(XComponentName(), r, root);
+        } else {
+            createOSChildNode(m_parent, XComponentName(), rect);
+        }
+
+        auto *nativeXComponent = OH_NativeXComponent_GetNativeXComponent(m_xcomponent);
+        QOhXComponent *component = new QOhXComponent(this, nativeXComponent);
+        setComponent(component);
+        setVisible(false);
+
+        /* 从cef窗口切换到同级的qt窗口输入框时需要获取焦点 */
+        setFocusOnTouch(isFocusable);
+        OH_ArkUI_SetNodeDraggable(m_xcomponent, false);
+        std::vector<ArkUI_NodeEventType> events = {NODE_ON_BLUR, NODE_ON_FOCUS, NODE_ON_HOVER, NODE_ON_MOUSE};
+#if OHOS_SDK_VERSION > 14
+        events.push_back(NODE_TOUCH_EVENT);
+#endif
+#if QT_CONFIG(draganddrop)
+        OH_ArkUI_AllowNodeAllDropDataTypes(m_xcomponent);
+        events.push_back(NODE_ON_DRAG_ENTER);
+        events.push_back(NODE_ON_DRAG_MOVE);
+        events.push_back(NODE_ON_DRAG_LEAVE);
+        events.push_back(NODE_ON_DROP);
+#endif
+#if OHOS_SDK_VERSION >= 17
+        events.push_back(NODE_ON_AXIS);
+        events.push_back(NODE_ON_KEY_EVENT);
+#endif
+        createNodeEventHandler();
+        m_eventHandler->registerEvents(events);
+    });
+    id->node = m_xcomponent;
+    id->container = m_stack;
+    const QWindowList &wl = qApp->topLevelWindows();
+    bool allInvisible = std::all_of(wl.begin(), wl.end(), [](const QWindow *obj) { return !obj->isVisible(); });
+
+    static bool isFirstWindow = true;
+    if (!allInvisible || isFirstWindow) { /* 窗口全部隐藏时onSurfaceCreated无法触发 */
+        isFirstWindow = false;
+        auto status = feature.wait_for(std::chrono::seconds(1));
+        if (status == std::future_status::timeout) {
+            qWarning() << "wait for native window handle time out";
+        }
+    }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohwindownode.h b/src/plugins/platforms/openharmony/qohwindownode.h
new file mode 100644
index 00000000000..4134ef83c31
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohwindownode.h
@@ -0,0 +1,121 @@
+#ifndef QOHWINDOWNODE_H
+#define QOHWINDOWNODE_H
+
+#include <EGL/egl.h>
+#include <QRect>
+#include <QtGui/qwindowdefs.h>
+#include <qpa/qplatformdrag.h>
+#include <napi/native_api.h>
+#include <arkui/native_node.h>
+#include <arkui/native_interface.h>
+#include <native_window/external_window.h>
+#include <future>
+#include <QPointer>
+#if QT_CONFIG(vulkan)
+#include <vulkan/vulkan.h>
+#endif
+
+struct OH_NativeXComponent;
+struct Node;
+struct OH_PixelmapNative;
+QT_BEGIN_NAMESPACE
+class QOhNativeWindow;
+class QOhXComponent;
+class QOhPlatformWindow;
+class QOhWindowNodeEventHandler;
+class QOhNativeNodeAPI;
+
+class QOhWindowNode
+{
+public:
+    explicit QOhWindowNode(QOhWindowNode *parent = nullptr);
+    virtual ~QOhWindowNode();
+
+    static bool nodeDestroyed(QOhWindowNode *node);
+    static QOhWindowNode *focusNode();
+    static bool isQtNode(const QString &name);
+    void setOwnerWindow(QOhNativeWindow *window);
+    QOhNativeWindow *ownerWindow() const;
+    void attachPlatformWindow(QOhPlatformWindow *window);
+    void attachRootComponent(void *component);
+    void detachRootComponent(bool isDestroy = false);
+    QString componentName() const;
+
+    void handleSurfaceChanged(const QSize &size);
+    void setComponent(QOhXComponent *component);
+    void setNativeWindow(void *nativeWindow);
+
+    OH_NativeXComponent *component() const;
+    EGLSurface eglSurface(EGLDisplay display, EGLConfig config);
+
+    QOhWindowNode *parent() const;
+    void setParent(QOhWindowNode *parent);
+
+    static QOhWindowNode *fromId(WId id);
+    WId id() const;
+
+    OH_PixelmapNative *grab();
+
+    void setGeometry(const QRect &rect);
+    void move(int x, int y);
+    QRectF geometry() const;
+    void setVisible(bool visible);
+    bool isVisible() const;
+    void raise();
+    void lower();
+    QSize surfaceSize() const;
+    QColor backgroundColor() const;
+    void setBackgroundColor(const QColor &color);
+    void setWindowFlags(Qt::WindowFlags flags);
+    void createNode(const QRectF &rect, bool isFocusable);
+    void clear();
+    void setNodeFocus(bool isFocus);
+    bool isFocused() const;
+    QOhPlatformWindow *platformWindow() const;
+    bool isExternal() const;
+
+    int32_t zIndex() const;
+    QSharedPointer<QOhNativeNodeAPI> nodeApi() const;
+#if QT_CONFIG(vulkan)
+    VkSurfaceKHR *vkSurface() const;
+#endif
+    void setRenderFit(ArkUI_RenderFit fit);
+private:
+    void createOSRootNode(const QString &id, const QRectF &rect, bool scale = false);
+    void createOSChildNode(QOhWindowNode *parentNode, const QString &id, const QRectF &rect, bool scale = false);
+    void createOSNode(QOhWindowNode *parentNode, const QString &id, const QRectF &rect, bool scale);
+    void createNodeEventHandler();
+    void setFocusOnTouch(bool focusOnTouch);
+    void setSizeAdaptive();
+    void handleSubNodes(QOhWindowNode *parent);
+    static bool exist(ArkUI_NodeHandle stack, ArkUI_NodeHandle xcomponent);
+    static int32_t subNodeMaxZIndex(QOhWindowNode *node);
+    static int32_t subNodeMinZIndex(QOhWindowNode *node);
+private:    
+    friend class QOhWindowNodeEventHandler;
+    QOhWindowNode *m_parent;
+    QOhWindowNodeEventHandler *m_eventHandler;
+    QOhPlatformWindow *m_window;
+    QOhNativeWindow *m_ownerWindow;
+    QOhXComponent *m_component;
+    OH_NativeXComponent *m_topComponent = nullptr;
+    void *m_nativeWindow = nullptr;
+    EGLSurface m_eglSurface = EGL_NO_SURFACE;
+    EGLDisplay m_display;
+    Node *m_id = nullptr;
+    QSharedPointer<QOhNativeNodeAPI> m_nodeApi;
+    ArkUI_NodeHandle m_stack = nullptr;
+    ArkUI_NodeHandle m_xcomponent = nullptr;
+    QList<QOhWindowNode *> m_children;
+    QList<QOhWindowNode *> m_deleteChildren;
+    int32_t m_zIndex = 0;
+    bool m_isExternal = false;
+    bool m_isIdCreateByQt = true;
+    std::promise<void> m_nativeWindowPromise;
+#if QT_CONFIG(vulkan)
+    mutable VkSurfaceKHR m_vkSurface = VK_NULL_HANDLE;
+#endif
+};
+
+QT_END_NAMESPACE
+#endif // QOHWINDOWNODE_H
diff --git a/src/plugins/platforms/openharmony/qohwindownodeeventhandler.cpp b/src/plugins/platforms/openharmony/qohwindownodeeventhandler.cpp
new file mode 100644
index 00000000000..3da84867e60
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohwindownodeeventhandler.cpp
@@ -0,0 +1,1314 @@
+#include "qohwindownodeeventhandler.h"
+#include "qohplatformwindow.h"
+#include "qoheventdispatcher.h"
+#include "qohdisplaymanager.h"
+#include "qohnativewindow.h"
+#include "qohauxiliary.h"
+#include "qohdrag.h"
+#include "qohkeys.h"
+#include "qohevent.h"
+#include "qohwindowcontext.h"
+#include "qohnativenodeapi.h"
+#include "qohplatformopenglwindow.h"
+#include "qohplatformscreen.h"
+
+#include <QTimer>
+#include <QGuiApplication>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformcursor.h>
+#include <qpa/qplatformscreen.h>
+#include <qopenharmonydefines.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qwindowsysteminterface_p.h>
+#include <private/qhighdpiscaling_p.h>
+
+#if OHOS_SDK_VERSION >= 17
+#include <arkui/native_key_event.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#define RUN_QT_THREAD 0
+
+static bool isGestureSupported()
+{
+    auto gestureApi = reinterpret_cast<ArkUI_NativeGestureAPI_1 *>(
+            OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_GESTURE, "ArkUI_NativeGestureAPI_1"));
+    return (gestureApi->createGroupGesture != nullptr);
+}
+
+QOhWindowNodeEventHandler::QOhWindowNodeEventHandler(QOhWindowNode *node)
+    : m_node(node)
+    , m_inHanding(false)
+{
+    m_nodeApi = QOhNativeNodeAPI::getOrCreateForNode(node);
+    if (!node->isExternal()) {
+        if (isGestureSupported()) {
+            createGestureRecognizerForNode(node->m_xcomponent);
+        }
+#if QT_CONFIG(draganddrop)
+        m_dropTarget = new QOhDropTarget(node);
+#endif
+    }
+}
+
+QOhWindowNodeEventHandler::~QOhWindowNodeEventHandler()
+{
+    while (m_inHanding.load(std::memory_order_acquire))
+        std::this_thread::yield();
+#if QT_CONFIG(draganddrop)
+    if (m_dropTarget != nullptr) {
+        delete m_dropTarget;
+        m_dropTarget = nullptr;
+    }
+#endif
+    m_window.clear();
+}
+
+void QOhWindowNodeEventHandler::registerEvents(const std::vector<ArkUI_NodeEventType> &events)
+{
+    static int32_t id = 1;
+    bool result = false;
+    for (auto event : events) {
+        result = m_nodeApi->registerNodeEvent<QOhNativeNodeAPI::XCompoentType>(event, id, this);
+        if (!result) {
+            continue;
+        }
+        m_events.push_back(event);
+        id++;
+    }
+    m_nodeApi->addNodeEventReceiver<QOhNativeNodeAPI::XCompoentType>(nodeEvent);
+}
+
+void QOhWindowNodeEventHandler::unregisterEvents()
+{
+    for (auto event : m_events) {
+        m_nodeApi->unregisterNodeEvent<QOhNativeNodeAPI::XCompoentType>(event);
+    }
+    m_nodeApi->removeNodeEventReceiver<QOhNativeNodeAPI::XCompoentType>(nodeEvent);
+}
+
+void QOhWindowNodeEventHandler::setTargetWindow(QWindow *window)
+{
+    m_window = window;
+}
+
+extern QPoint translatePoint(const QPointF &global, QWindow *w);
+
+struct AtomicHelper
+{
+    AtomicHelper(std::atomic<bool> *i):m_i(i) { m_i->store(true, std::memory_order_release); }
+    ~AtomicHelper() { m_i->store(false, std::memory_order_release); }
+    std::atomic<bool> *m_i;
+};
+
+void QOhWindowNodeEventHandler::nodeEvent(ArkUI_NodeEvent *event)
+{
+    QOhWindowNodeEventHandler *handler = (QOhWindowNodeEventHandler *)OH_ArkUI_NodeEvent_GetUserData(event);
+    if (handler == nullptr || handler->m_window.isNull()) {
+        return;
+    }
+
+    AtomicHelper helper(&handler->m_inHanding);
+    Q_UNUSED(helper)
+
+    ArkUI_NodeEventType type = OH_ArkUI_NodeEvent_GetEventType(event);
+    switch(type) {
+#if OHOS_SDK_VERSION > 14
+    case NODE_TOUCH_EVENT:
+    {
+        ArkUI_UIInputEvent *inputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event);
+        handler->touchEvent(inputEvent);
+    }
+        break;
+#endif
+    case NODE_ON_DROP:
+    case NODE_ON_DRAG_MOVE:
+    case NODE_ON_DRAG_ENTER:
+    case NODE_ON_DRAG_LEAVE:
+        handler->m_dropTarget->handleDragDropEvent(event);
+        break;
+    case NODE_ON_FOCUS:
+        handler->focusEvent(true);
+        break;
+    case NODE_ON_MOUSE:
+    {
+        ArkUI_UIInputEvent *inputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event);
+        handler->mouseEvent(inputEvent);
+    }
+        break;
+    case NODE_ON_BLUR: {
+        handler->focusEvent(false);
+    }
+    break;
+    case NODE_ON_CLICK: {
+    }
+    break;
+    case NODE_ON_HOVER:
+    {
+        ArkUI_NodeComponentEvent *componentEvent = OH_ArkUI_NodeEvent_GetNodeComponentEvent(event);
+        if (!componentEvent) {
+            LOGE("NODE_ON_HOVER OH_ArkUI_NodeEvent_GetNodeComponentEvent faild.");
+            return;
+        }
+        handler->hoverEvent(1 == componentEvent->data[0].i32);
+    }
+    break;
+#if OHOS_SDK_VERSION >= 17
+    case NODE_ON_KEY_EVENT:
+    {
+        ArkUI_UIInputEvent *inputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event);
+        handler->keyEvent(inputEvent);
+    }
+        break;
+    case NODE_ON_AXIS:
+    {
+        ArkUI_UIInputEvent *inputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event);
+        handler->wheelEvent(inputEvent);
+    }
+        break;
+#endif
+    default:
+        break;
+    }
+}
+
+void QOhWindowNodeEventHandler::hoverEvent(bool hover)
+{
+    if (m_window.isNull() || !QOhEventDispatcher::instance())
+        return;
+
+    QSharedPointer<QtOh::EnterLeaveEvent> e(new QtOh::EnterLeaveEvent());
+    e->enter = hover;
+    e->window = m_window;
+    QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance();
+    dispatcher->appendOhEvent(e);
+}
+
+#if OHOS_SDK_VERSION >= 17
+static inline Qt::KeyboardModifiers keyboardModifiersFromEvent(ArkUI_UIInputEvent *event)
+{
+    uint64_t keys = 0;
+    OH_ArkUI_UIInputEvent_GetModifierKeyStates(event, &keys);
+    return QOhKeys::ohKeys2Qt(keys) | QOhKeys::metaModifier();
+}
+#endif
+
+void QOhWindowNodeEventHandler::mouseEvent(ArkUI_UIInputEvent *event)
+{
+    if (!event) {
+        LOGE("NODE_ON_MOUSE OH_ArkUI_NodeEvent_GetInputEvent faild.");
+        return;
+    }
+    int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(event);
+    // Todo 非客户区
+    auto displayX = OH_ArkUI_PointerEvent_GetDisplayX(event);
+    auto displayY = OH_ArkUI_PointerEvent_GetDisplayY(event);
+
+//    // windowY包含了标题栏的高度,使用全局坐标转换
+//    auto windowX = OH_ArkUI_PointerEvent_GetWindowX(event);
+//    auto windowY = OH_ArkUI_PointerEvent_GetWindowY(event);
+    auto action  = OH_ArkUI_MouseEvent_GetMouseAction(event);
+    auto button  = OH_ArkUI_MouseEvent_GetMouseButton(event);
+#if OHOS_SDK_VERSION >= 17
+    auto keys = keyboardModifiersFromEvent(event);
+#endif
+
+#if 0
+    /* 移动事件处理:过滤事件 - 限制移动事件处理频率,6.0事件频率过高导致窗口移动卡顿 */
+    quint64 time = OH_ArkUI_UIInputEvent_GetEventTime(event);
+    if (action == UI_MOUSE_EVENT_ACTION_MOVE && QtOh::apiVersion() >= 20) {
+        static quint64 lastTimestamp = 0;
+        quint64 interval = time - lastTimestamp;
+        if (interval < MSTONS(15))
+            return;
+        lastTimestamp = time;
+    }
+#endif
+
+    if (!QOhEventDispatcher::instance())
+        return;
+    auto platformScreen = QOhDisplayManager::instance()->platformScreenOrNull(displayId);
+    if (Q_UNLIKELY(!platformScreen)) {
+        qDebug() << "platformScreen is null. displayId: " << displayId;
+        return;
+    }
+    // arkui节点的默认单位为vp,因此需要做单位变换
+    auto scale = 1.0f;
+    auto screenTopLeft = QPoint();
+    if (platformScreen) {
+        scale = QtOh::densityPixels(platformScreen);
+        screenTopLeft = platformScreen->geometry().topLeft();
+    }
+
+    auto globalPos = QPointF { displayX, displayY };
+    globalPos = globalPos * scale;
+    globalPos += screenTopLeft;
+
+    if (QOhNativeWindow *nativeWindow = m_node->ownerWindow()) {
+        // 如果是在系统按钮的区域内,由系统响应不上传给Qt
+        if (nativeWindow->hitTest(globalPos.toPoint(), scale) == QOhNativeWindow::SystemButton)
+            return;
+    }
+
+    QSharedPointer<QtOh::MouseEvent> mouseEvent(new QtOh::MouseEvent());
+    switch (action) {
+    case UI_MOUSE_EVENT_ACTION_MOVE:
+        mouseEvent->mouseEventType = QEvent::MouseMove;
+        break;
+    case UI_MOUSE_EVENT_ACTION_PRESS:
+        mouseEvent->mouseEventType = QEvent::MouseButtonPress;
+        break;
+    case UI_MOUSE_EVENT_ACTION_RELEASE:
+        mouseEvent->mouseEventType = QEvent::MouseButtonRelease;
+        break;
+#if OHOS_SDK_VERSION >= 18
+        /* Qt鼠标没有cancel类型,视作release处理  */
+    case UI_MOUSE_EVENT_ACTION_CANCEL:
+        mouseEvent->mouseEventType = QEvent::MouseButtonRelease;
+        break;
+#endif
+    default:
+        return;
+    }
+
+    switch (button) {
+    case UI_MOUSE_EVENT_BUTTON_NONE:
+        mouseEvent->mouseButton = Qt::NoButton;
+        break;
+    case UI_MOUSE_EVENT_BUTTON_LEFT:
+        mouseEvent->mouseButton = Qt::LeftButton;
+        break;
+    case UI_MOUSE_EVENT_BUTTON_MIDDLE:
+        mouseEvent->mouseButton = Qt::MiddleButton;
+        break;
+    case UI_MOUSE_EVENT_BUTTON_RIGHT:
+        mouseEvent->mouseButton = Qt::RightButton;
+        break;
+    case UI_MOUSE_EVENT_BUTTON_FORWARD:
+        mouseEvent->mouseButton = Qt::ForwardButton;
+        break;
+    case UI_MOUSE_EVENT_BUTTON_BACK:
+        mouseEvent->mouseButton = Qt::BackButton;
+        break;
+    }
+#if OHOS_SDK_VERSION >= 17
+    mouseEvent->keyboardModifiers = keys;
+#endif
+    if (m_node->isExternal()) {
+        handleExternalNodeMouseEvent(globalPos, mouseEvent->mouseEventType,
+                                     mouseEvent->mouseButton, mouseEvent->keyboardModifiers);
+        return;
+    }
+    QWindow *window = m_window.data();
+    while (window && (window->flags() & Qt::WindowTransparentForInput))
+        window = window->parent();
+    if (!window || !window->handle())
+        return;
+
+    QPointF localPos = window->handle()->mapFromGlobal(globalPos.toPoint());
+    mouseEvent->window = window;
+    mouseEvent->xcPos = localPos;
+    mouseEvent->scPos = globalPos;
+
+    QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance();
+    dispatcher->appendOhEvent(mouseEvent);
+}
+
+void QOhWindowNodeEventHandler::handleExternalNodeMouseEvent(const QPointF &global, QEvent::Type type,
+                                                             Qt::MouseButton button, Qt::KeyboardModifiers mod)
+{
+    if (QGuiApplicationPrivate::instance()->popupActive()) {
+        QWindow *grabber = QOhWindowContext::mouseGrabberWindow();
+        if (grabber == nullptr)
+            return;
+        QSharedPointer<QtOh::MouseEvent> synthesisEvent(new QtOh::MouseEvent());
+        synthesisEvent->mouseButton = button;
+        synthesisEvent->window = grabber;
+        synthesisEvent->xcPos = translatePoint(global, grabber);
+        synthesisEvent->scPos = global;
+        synthesisEvent->mouseEventType = type;
+        synthesisEvent->keyboardModifiers = mod;
+        if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance())
+            dispatcher->appendOhEvent(synthesisEvent);
+    } else {
+        auto screens = QGuiApplication::screens();
+        for (int i = 0; i < screens.count(); ++i) {
+            if (QPlatformCursor *cursor = screens.at(i)->handle()->cursor())
+                cursor->setPos(global.toPoint());
+        }
+    }
+}
+
+#if OHOS_SDK_VERSION > 14
+
+/* 轻量级触摸点数据结构,用于跨线程传递 
+ * 使用POD类型确保高效拷贝 */
+struct TouchPointData {
+    int32_t pointerId;
+    float displayX;
+    float displayY;
+    float pressure;
+    
+    TouchPointData() = default;
+    TouchPointData(int32_t id, float x, float y, float p) 
+        : pointerId(id), displayX(x), displayY(y), pressure(p) {}
+};
+
+void QOhWindowNodeEventHandler::translateMouseEvent(ArkUI_UIInputEvent *inputEvent)
+{   
+    auto pw = m_node->platformWindow();
+    if (Q_UNLIKELY(!pw)) {
+        return;
+    }
+
+    /* 快速过滤鼠标事件
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0
+     * UI_INPUT_EVENT_SOURCE_TYPE_MOUSE = 1
+     * UI_INPUT_EVENT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(inputEvent);
+    if (sourceType == UI_INPUT_EVENT_SOURCE_TYPE_MOUSE) {
+        return;
+    }
+
+    const int32_t action = OH_ArkUI_UIInputEvent_GetAction(inputEvent);
+    
+    /* 特殊事件处理:取消事件 - 立即处理并清除状态 */
+    if (Q_UNLIKELY(action == UI_TOUCH_EVENT_ACTION_CANCEL)) {
+        QWindow *window = pw->window();
+#if RUN_QT_THREAD
+        QtOh::runOnQtMainThread([this, window]{
+#endif
+            if (QOhWindowNode::nodeDestroyed(m_node))
+                return;
+            if (auto *dispatcher = QOhEventDispatcher::instance()) {
+                QSharedPointer<QtOh::TouchEvent> e(new QtOh::TouchEvent());
+                e->window = window;
+                e->actionType = UI_TOUCH_EVENT_ACTION_CANCEL;
+                dispatcher->appendOhEvent(e);
+            }
+            m_lastTouchPoints.clear();
+            m_pointerIdToTouchId.clear();
+
+#if RUN_QT_THREAD
+        });
+#endif
+
+        return;
+    }
+
+    const uint32_t pointCount = OH_ArkUI_PointerEvent_GetPointerCount(inputEvent);
+    if (Q_UNLIKELY(pointCount == 0)) {
+        return;
+    }
+
+    /* 在JS线程中只提取必要的原始数据 - 批量提取减少API调用 */
+    const int64_t time = OH_ArkUI_UIInputEvent_GetEventTime(inputEvent);
+    int32_t changedPointerId = 0;
+    if (Q_UNLIKELY(ARKUI_ERROR_CODE_NO_ERROR != OH_ArkUI_PointerEvent_GetChangedPointerId(inputEvent, (uint32_t*)&changedPointerId))) {
+        LOGE("get changedPointerId failed");
+        return;
+    }
+
+#if 0
+    /* 移动事件处理:过滤事件 - 限制移动事件处理频率,6.0事件频率过高导致窗口移动卡顿 */
+    if (action == UI_TOUCH_EVENT_ACTION_MOVE && QtOh::apiVersion() >= 20) {
+        static quint64 lastTimestamp = 0;
+        quint64 interval = time - lastTimestamp;
+        if (interval < MSTONS(15))
+            return;
+        lastTimestamp = time;
+    }
+#endif
+
+    const int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(inputEvent);
+    const int32_t toolType = OH_ArkUI_UIInputEvent_GetToolType(inputEvent);
+
+#if OHOS_SDK_VERSION >= 17
+    const Qt::KeyboardModifiers keys = keyboardModifiersFromEvent(inputEvent);
+#endif
+    /* 直接使用QVector,通过reserve预分配内存,Lambda捕获时会进行值拷贝 */
+    QVector<TouchPointData> rawPoints;
+    rawPoints.reserve(pointCount);
+    
+    for (uint32_t i = 0; i < pointCount; i++) {
+        rawPoints.append(TouchPointData(
+            OH_ArkUI_PointerEvent_GetPointerId(inputEvent, i),
+            OH_ArkUI_PointerEvent_GetDisplayXByIndex(inputEvent, i),
+            OH_ArkUI_PointerEvent_GetDisplayYByIndex(inputEvent, i),
+            OH_ArkUI_PointerEvent_GetPressure(inputEvent, i)
+        ));
+    }
+#if RUN_QT_THREAD
+    /* 将处理逻辑投递到Qt主线程
+     * rawPoints会被Lambda值捕获,确保数据在Qt线程中有效 */
+    QtOh::runOnQtMainThread([this, action, pointCount, changedPointerId, displayId, time, sourceType, toolType,
+                            rawPoints = std::move(rawPoints)
+#if OHOS_SDK_VERSION >= 17
+                            , keys
+#endif
+                            ]() mutable {
+#endif
+        if (Q_UNLIKELY(QOhWindowNode::nodeDestroyed(m_node) || !QOhEventDispatcher::instance()))
+            return;
+
+        auto platformScreen = QOhDisplayManager::instance()->platformScreenOrNull(displayId);
+        if (Q_UNLIKELY(!platformScreen)) {
+            return;
+        }
+
+        const qreal scale = QtOh::densityPixels(platformScreen);
+        const QRect screenGeometry = platformScreen->geometry();
+        const qreal screenWidth = screenGeometry.width();
+        const qreal screenHeight = screenGeometry.height();
+        const QPoint screenTopLeft = screenGeometry.topLeft();
+        const bool isDownAction = (action == UI_TOUCH_EVENT_ACTION_DOWN);
+        const bool isUpAction = (action == UI_TOUCH_EVENT_ACTION_UP);
+        const bool isMoveAction = (action == UI_TOUCH_EVENT_ACTION_MOVE);
+
+        /* 预分配内存,避免动态扩展 */
+        QList<QWindowSystemInterface::TouchPoint> touchPoints;
+        touchPoints.reserve(pointCount + m_lastTouchPoints.size());
+        
+        QSet<int> currentTouchIds;
+        currentTouchIds.reserve(pointCount);
+
+        /* 优化:合并阶段一和阶段二,减少循环次数 */
+        for (uint32_t i = 0; i < pointCount; i++) {
+            const TouchPointData &rawData = rawPoints[i];
+            const int32_t pointerId = rawData.pointerId;
+
+            /* 映射或创建touchId */
+            int touchId;
+            auto pointerIt = m_pointerIdToTouchId.find(pointerId);
+            if (pointerIt != m_pointerIdToTouchId.end()) {
+                touchId = pointerIt.value();
+            } else {
+                touchId = m_pointerIdToTouchId.size();
+                m_pointerIdToTouchId.insert(pointerId, touchId);
+            }
+            currentTouchIds.insert(touchId);
+
+            /* 计算位置 - 减少重复计算 */
+            const float displayX = rawData.displayX * scale;
+            const float displayY = rawData.displayY * scale;
+            const QPointF globalPointF(displayX, displayY);
+            const QPoint globalPos = globalPointF.toPoint() + screenTopLeft;
+
+            /* 构建触摸点 */
+            QWindowSystemInterface::TouchPoint touchPoint;
+            touchPoint.id = touchId;
+            touchPoint.pressure = rawData.pressure;
+            touchPoint.rotation = 0;
+            touchPoint.normalPosition = QPointF(globalPointF.x() / screenWidth, 
+                                                globalPointF.y() / screenHeight);
+            touchPoint.area.setSize(QSize(10, 10));
+            touchPoint.area.moveCenter(globalPos);
+            touchPoint.rawPositions = QVector<QPointF> { globalPos, globalPointF };
+
+            const bool isChangedPointer = (pointerId == changedPointerId);
+			/* Qt 6 only modify */
+            /* 优化:使用if-else代替多个独立if,减少判断次数 */
+            if (isDownAction) {
+                if (isChangedPointer) {
+                    touchPoint.state = QEventPoint::State::Pressed;
+                    m_lastTouchPoints.insert(touchId, touchPoint);
+                } else {
+                    touchPoint.state = m_lastTouchPoints.contains(touchId) 
+                        ? QEventPoint::State::Stationary
+                        : QEventPoint::State::Pressed;
+                    if (touchPoint.state == QEventPoint::State::Pressed) {
+                        m_lastTouchPoints.insert(touchId, touchPoint);
+                    }
+                }
+            } else if (isUpAction) {
+                if (isChangedPointer) {
+                    touchPoint.state = QEventPoint::State::Released;
+                    m_lastTouchPoints.remove(touchId);
+                    m_pointerIdToTouchId.remove(pointerId);
+                } else {
+                    touchPoint.state = QEventPoint::State::Stationary;
+                }
+            } else if (isMoveAction) {
+                /* 移动事件:参考Windows实现,直接比较归一化位置而非使用阈值 */
+                auto lastIt = m_lastTouchPoints.find(touchId);
+                if (lastIt != m_lastTouchPoints.end()) {
+                    const QPointF& lastNormalPos = lastIt.value().normalPosition;
+                    const bool stationaryTouchPoint = (touchPoint.normalPosition == lastNormalPos);
+                    
+                    if (stationaryTouchPoint) {
+                        /* 位置完全相同:复用上次的触摸点数据 */
+                        touchPoint.state = QEventPoint::State::Stationary;
+                        touchPoint.normalPosition = lastNormalPos;
+                        touchPoint.rawPositions = lastIt.value().rawPositions;
+                        touchPoint.area = lastIt.value().area;
+                    } else {
+                        /* 位置有变化:标记为移动并更新缓存 */
+                        touchPoint.state = QEventPoint::State::Updated;
+                        m_lastTouchPoints.insert(touchId, touchPoint);
+                    }
+                } else {
+                    /* 新的触摸点在MOVE事件中出现 */
+                    touchPoint.state = QEventPoint::State::Updated;
+                    m_lastTouchPoints.insert(touchId, touchPoint);
+                }
+            } else {
+                touchPoint.state = QEventPoint::State::Stationary;
+            }
+
+            touchPoints.append(touchPoint);
+        }
+
+        /* 优化:补充缺失触摸点 - 只在必要时才遍历 */
+        if (m_lastTouchPoints.size() > currentTouchIds.size()) {
+            for (auto it = m_lastTouchPoints.constBegin(); it != m_lastTouchPoints.constEnd(); ++it) {
+                if (!currentTouchIds.contains(it.key())) {
+                    QWindowSystemInterface::TouchPoint stationaryPoint = it.value();
+                    stationaryPoint.state = QEventPoint::State::Stationary;
+                    touchPoints.append(stationaryPoint);
+                }
+            }
+        }
+
+        if (touchPoints.isEmpty()) {
+            return;
+        }
+
+        /* 优化:清理映射 - 检查是否所有点都释放 */
+        if (isUpAction && m_lastTouchPoints.isEmpty()) {
+            m_pointerIdToTouchId.clear();
+        }
+
+        /* 优化:对于MOVE事件,快速检查是否有真正的移动 */
+        bool shouldDispatch = true;
+        if (isMoveAction) {
+            bool hasRealMovement = false;
+            for (const auto& point : touchPoints) {
+                if (point.state == QEventPoint::State::Updated) {
+                    hasRealMovement = true;
+                    break;
+                }
+            }
+            shouldDispatch = hasRealMovement;
+        }
+
+        if (shouldDispatch) {
+            auto *dispatcher = QOhEventDispatcher::instance();
+            if (!dispatcher) {
+                return;
+            }
+
+            /* 更新触摸点位置 - 只更新必要的点 */
+            if (isDownAction || isMoveAction) {
+                for (const auto &point : touchPoints) {
+                    if (point.state == QEventPoint::State::Updated || point.state == Qt::TouchPointPressed) {
+                        dispatcher->updateLastTouchPoints(point.id, point.rawPositions.first());
+                    }
+                }
+            }
+
+            QSharedPointer<QtOh::TouchEvent> e(new QtOh::TouchEvent());
+            e->id = changedPointerId;
+            e->touchPoints = touchPoints;
+            e->window = pw->window();
+            e->actionType = action;
+            e->timestamp = time;
+#if OHOS_SDK_VERSION >= 17
+            e->keyboardModifiers = keys;
+#endif
+			/* Qt 6 only modify */
+            e->deviceType = sourceType == UI_INPUT_EVENT_SOURCE_TYPE_TOUCH_SCREEN ?
+                    QPointingDevice::DeviceType::TouchScreen : QPointingDevice::DeviceType::Mouse;
+            e->pointerType = QPointingDevice::PointerType::Unknown;
+            switch (toolType) {
+            case UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD:
+            case UI_INPUT_EVENT_TOOL_TYPE_FINGER:
+                e->pointerType = QPointingDevice::PointerType::Finger;
+                break;
+            case UI_INPUT_EVENT_TOOL_TYPE_PEN:
+                e->pointerType = QPointingDevice::PointerType::Pen;
+                break;
+            case UI_INPUT_EVENT_TOOL_TYPE_JOYSTICK:
+            case UI_INPUT_EVENT_TOOL_TYPE_MOUSE:
+                e->pointerType = QPointingDevice::PointerType::Generic;
+                break;
+            default:
+                break;
+            }
+
+            dispatcher->appendOhEvent(e);
+        }
+#if RUN_QT_THREAD
+    });
+#endif
+}
+
+void QOhWindowNodeEventHandler::translatePenEvent(ArkUI_UIInputEvent *inputEvent)
+{
+    /* 在JS线程中提取必要的原始数据 */
+    const int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(inputEvent);
+    const int32_t action = OH_ArkUI_UIInputEvent_GetAction(inputEvent);
+    const int32_t deviceId = OH_ArkUI_UIInputEvent_GetDeviceId(inputEvent);
+    const int64_t time = OH_ArkUI_UIInputEvent_GetEventTime(inputEvent);
+    
+    const float displayX = OH_ArkUI_PointerEvent_GetDisplayXByIndex(inputEvent, 0);
+    const float displayY = OH_ArkUI_PointerEvent_GetDisplayYByIndex(inputEvent, 0);
+    const float pressure = OH_ArkUI_PointerEvent_GetPressure(inputEvent, 0);
+    const float tiltX = OH_ArkUI_PointerEvent_GetTiltX(inputEvent, 0);
+    const float tiltY = OH_ArkUI_PointerEvent_GetTiltY(inputEvent, 0);
+    
+#if OHOS_SDK_VERSION >= 17
+    double rotation = 0.f;
+    OH_ArkUI_PointerEvent_GetRollAngle(inputEvent, &rotation);
+#endif
+
+    QWindow *window = m_window;
+
+#if RUN_QT_THREAD
+    /* 将处理逻辑投递到Qt主线程 */
+    QtOh::runOnQtMainThread([this, window, displayId, action, deviceId, time, 
+                            displayX, displayY, pressure, tiltX, tiltY
+#if OHOS_SDK_VERSION >= 17
+                            , rotation
+#endif
+                            ]{
+#endif
+        if (Q_UNLIKELY(QOhWindowNode::nodeDestroyed(m_node) || !QOhEventDispatcher::instance()))
+            return;
+
+        auto platformScreen = QOhDisplayManager::instance()->platformScreenOrNull(displayId);
+        if (Q_UNLIKELY(!platformScreen)) {
+            return;
+        }
+
+        const qreal scale = QtOh::densityPixels(platformScreen);
+        const QRect screenGeometry = platformScreen->geometry();
+        
+        const float scaledX = displayX * scale;
+        const float scaledY = displayY * scale;
+        const QPointF globalPointF(scaledX, scaledY);
+        const QPoint globalPos = globalPointF.toPoint() + screenGeometry.topLeft();
+
+        QSharedPointer<QtOh::TabletEvent> e(new QtOh::TabletEvent());
+        e->timestamp = time;
+        e->presure = pressure;
+        e->global = globalPos;
+        e->uniqueID = deviceId;
+        e->btn = (action == UI_TOUCH_EVENT_ACTION_UP) ? Qt::NoButton : Qt::LeftButton;
+        e->window = window;
+#if OHOS_SDK_VERSION < 17
+        e->rotation = 0.f;
+#else
+        e->rotation = rotation;
+#endif
+
+        QOhEventDispatcher::instance()->appendOhEvent(e);
+#if RUN_QT_THREAD
+    });
+#endif
+}
+
+#endif
+
+#if OHOS_SDK_VERSION >= 17
+void QOhWindowNodeEventHandler::keyEvent(ArkUI_UIInputEvent *keyEvent)
+{
+    if (keyEvent == nullptr)
+        return;
+
+    auto type = OH_ArkUI_KeyEvent_GetType(keyEvent);
+    auto keyCode = OH_ArkUI_KeyEvent_GetKeyCode(keyEvent);
+    auto deviceId = OH_ArkUI_UIInputEvent_GetDeviceId(keyEvent);
+    auto text = QString::fromUtf8(OH_ArkUI_KeyEvent_GetKeyText(keyEvent));
+    auto keys = keyboardModifiersFromEvent(keyEvent);
+
+#if RUN_QT_THREAD
+    QtOh::runOnQtMainThread([this, type, keyCode, text, deviceId, keys] {
+#endif
+        if (QOhWindowNode::nodeDestroyed(m_node) || !QOhEventDispatcher::instance())
+            return;
+        QSharedPointer<QtOh::NewKeyEvent> e(new QtOh::NewKeyEvent());
+        e->window = m_window;
+        e->code = keyCode;
+        e->text = text;
+        e->type = type;
+        e->keyboardModifiers = keys;
+
+        QOhEventDispatcher::instance()->appendOhEvent(e);
+#if RUN_QT_THREAD
+    });
+#endif
+}
+
+void QOhWindowNodeEventHandler::wheelEvent(ArkUI_UIInputEvent *event)
+{
+    /* 获取特定接触点相对于当前应用窗口左上角的坐标 */
+    float lx = OH_ArkUI_PointerEvent_GetX(event);
+    float ly = OH_ArkUI_PointerEvent_GetY(event);
+
+    /* FIXME wanghao 多屏时获取当前输入回调的屏幕id错误 */
+#if 0
+    /* 从带有指向性的输入事件中获取相对于当前屏幕左上角的坐标 */
+    float gx = OH_ArkUI_PointerEvent_GetDisplayX(event);
+    float gy = OH_ArkUI_PointerEvent_GetDisplayY(event);
+    auto displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(event);
+    auto platformScreen = QOhDisplayManager::instance()->platformScreenOrNull(displayId);
+    if (platformScreen) {
+        gx += platformScreen->geometry().left();
+        gy += platformScreen->geometry().top();
+    }
+#endif
+
+    float scale = OH_ArkUI_AxisEvent_GetPinchAxisScaleValue(event);
+
+    /* 获取产生UI输入事件的工具类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_TOOL_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENT_TOOL_TYPE_FINGER = 1,
+     * UI_INPUT_EVENT_TOOL_TYPE_PEN = 2,
+     * UI_INPUT_EVENT_TOOL_TYPE_MOUSE = 3,
+     * UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD = 4,
+     * UI_INPUT_EVENT_TOOL_TYPE_JOYSTICK = 5
+     */
+    int32_t toolType = OH_ArkUI_UIInputEvent_GetToolType(event);
+
+#if OHOS_SDK_VERSION >= 15
+    int32_t axisAction = 0;
+    /* 获取当前轴事件的操作类型的值
+     * UI_AXIS_EVENT_ACTION_NONE = 0,   // The axis event is abnormal.
+     * UI_AXIS_EVENT_ACTION_BEGIN = 1,  // The axis event begins.
+     * UI_AXIS_EVENT_ACTION_UPDATE = 2, // The axis event is updated.
+     * UI_AXIS_EVENT_ACTION_END = 3,    // The axis event ends.
+     * UI_AXIS_EVENT_ACTION_CANCEL = 4, // The axis event is canceled.
+     */
+    axisAction = OH_ArkUI_AxisEvent_GetAxisAction(event);
+
+    /* NOTE 鼠标滚轮只处理UPDATE? */
+    if (UI_INPUT_EVENT_TOOL_TYPE_MOUSE == toolType &&
+        UI_AXIS_EVENT_ACTION_UPDATE != axisAction) {
+        return;
+    }
+#endif
+
+#if OHOS_SDK_VERSION >= 17
+    int32_t scrollStep = OH_ArkUI_AxisEvent_GetScrollStep(event);
+#endif
+
+    /* 获取UI输入事件发生的时间 */
+    int64_t timestamp = OH_ArkUI_UIInputEvent_GetEventTime(event);
+
+    /* 获取产生UI输入事件的来源类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(event);
+    double verticalValue = OH_ArkUI_AxisEvent_GetVerticalAxisValue(event);
+    double horizontalValue = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(event);
+    auto keys = keyboardModifiersFromEvent(event);
+
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+        QSharedPointer<QtOh::WheelEvent> e(new QtOh::WheelEvent());
+        e->pinchScale = scale;
+        e->toolType = toolType;
+        e->timestamp = timestamp;
+
+#if OHOS_SDK_VERSION >= 15
+        e->axisAction = axisAction;
+#endif
+
+#if OHOS_SDK_VERSION >= 17
+        e->scrollStep = scrollStep;
+#endif
+        e->sourceType = sourceType;
+        qreal dpr = QtOh::densityPixels(m_window->handle()->screen());
+        e->local = QPointF(lx * dpr, ly * dpr);
+        e->window = m_window;
+        e->global = e->window->handle()->mapToGlobal(e->local.toPoint());
+
+        e->verticalValue = verticalValue;
+        e->horizontalValue = horizontalValue;
+        e->keyboardModifiers = keys;
+        dispatcher->appendOhEvent(e);
+    }
+}
+#endif
+
+void QOhWindowNodeEventHandler::focusEvent(bool focusIn)
+{
+    // 焦点切换有时不触发, 顶层节点的焦点由窗口windowEvent处理
+    if (m_window.isNull() || m_window->parent() == nullptr)
+        return;
+    QWindow *nextActiveWindow = 0;
+    if (focusIn) {
+        auto w = m_window;
+        QWindow *topWindow = QOhWindowContext::topLevelOf(w);
+        QWindow *modalWindow = 0;
+        if (QGuiApplicationPrivate::instance()->isWindowBlocked(topWindow, &modalWindow) && topWindow != modalWindow) {
+            modalWindow->requestActivate();
+            return;
+        }
+        nextActiveWindow = w;
+    } else {
+        /* 是否有系统接口获取失去焦点时怎么查找系统的焦点node,
+         * 获取焦点的node要比失去焦点的node后发送foucsIn事件
+         */
+        QOhWindowNode *focusNode = QOhWindowNode::focusNode();
+        if (focusNode != nullptr) {
+            auto nextActivePlatformWindow = focusNode->m_window;
+            if (nextActivePlatformWindow)
+                nextActiveWindow = nextActivePlatformWindow->window();
+        }
+    }
+    QOhWindowContext::setFocusWindow(nextActiveWindow);
+}
+
+#if OHOS_SDK_VERSION > 14
+void QOhWindowNodeEventHandler::touchEvent(ArkUI_UIInputEvent *inputEvent)
+{
+    /* 产生输入事件的工具类型定义
+     * UI_INPUT_EVENT_TOOL_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENT_TOOL_TYPE_FINGER = 1,
+     * UI_INPUT_EVENT_TOOL_TYPE_PEN = 2,
+     * UI_INPUT_EVENT_TOOL_TYPE_MOUSE = 3,
+     * UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD = 4,
+     * UI_INPUT_EVENT_TOOL_TYPE_JOYSTICK = 5
+     */
+    int32_t toolType = OH_ArkUI_UIInputEvent_GetToolType(inputEvent);
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(inputEvent);
+    if (UI_INPUT_EVENT_TOOL_TYPE_PEN == sourceType &&
+        UI_INPUT_EVENT_TOOL_TYPE_FINGER != toolType) {
+        translatePenEvent(inputEvent);
+    } else {
+        translateMouseEvent(inputEvent);
+    }
+}
+#endif
+
+bool QOhWindowNodeEventHandler::isValidGestureEvent(ArkUI_GestureEvent *event, QOhWindowNodeEventHandler *handler)
+{
+    if ((nullptr == event) || (nullptr == handler) || handler->m_window.isNull())
+        return false;
+    return true;
+}
+
+void QOhWindowNodeEventHandler::createGestureRecognizerForNode(ArkUI_NodeHandle node)
+{
+    auto gestureApi = reinterpret_cast<ArkUI_NativeGestureAPI_1 *>(
+            OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_GESTURE, "ArkUI_NativeGestureAPI_1"));
+    /* 创建手势组 */
+    auto groupGesture = gestureApi->createGroupGesture(ArkUI_GroupGestureMode::PARALLEL_GROUP);
+
+    /* 创建拖动手势 */
+    auto panGesture = gestureApi->createPanGesture(1, GESTURE_DIRECTION_ALL, 5);
+    int32_t result = gestureApi->setGestureEventTarget(panGesture,
+                                                       GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE |
+                                                               GESTURE_EVENT_ACTION_END | GESTURE_EVENT_ACTION_CANCEL,
+                                                       this, QOhWindowNodeEventHandler::handlePanGestureEvent);
+
+    if (0 != result)
+        LOGE("set panGesture Target Failed.");
+
+    /* 创建捏合手势 */
+    auto pinchGesture = gestureApi->createPinchGesture(2, 0);
+    result = gestureApi->setGestureEventTarget(pinchGesture,
+                                               GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE |
+                                                       GESTURE_EVENT_ACTION_END | GESTURE_EVENT_ACTION_CANCEL,
+                                               this, QOhWindowNodeEventHandler::handlePinchGestureEvent);
+    if (0 != result)
+        LOGE("set pinchGesture Target Failed.");
+
+    /* 创建滑动手势 */
+    auto swipeGesture = gestureApi->createSwipeGesture(1, GESTURE_DIRECTION_ALL, 0);
+    result = gestureApi->setGestureEventTarget(swipeGesture,
+                                               GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE |
+                                                       GESTURE_EVENT_ACTION_END | GESTURE_EVENT_ACTION_CANCEL,
+                                               this, QOhWindowNodeEventHandler::handleSwipeGestureEvent);
+    if (0 != result)
+        LOGE("set swipeGesture Target Failed.");
+
+    /* 创建旋转手势 */
+    auto rotationGesture = gestureApi->createRotationGesture(2, 0);
+    result = gestureApi->setGestureEventTarget(rotationGesture,
+                                               GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE |
+                                                       GESTURE_EVENT_ACTION_END | GESTURE_EVENT_ACTION_CANCEL,
+                                               this, QOhWindowNodeEventHandler::handleRotationGestureEvent);
+
+    /* 创建长按手势 */
+    auto longPressGesture = gestureApi->createLongPressGesture(1, false, 500);
+    gestureApi->setGestureEventTarget(longPressGesture,
+                                      GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE |
+                                              GESTURE_EVENT_ACTION_END | GESTURE_EVENT_ACTION_CANCEL,
+                                      this, QOhWindowNodeEventHandler::handleLongPressGesture);
+
+    /* 将手势添加到手势组 */
+    if (gestureApi->addChildGesture) {
+        /* FIXME panGesture造成无边框时三键位置无响应 */
+        //gestureApi->addChildGesture(groupGesture, panGesture);
+        gestureApi->addChildGesture(groupGesture, pinchGesture);
+        gestureApi->addChildGesture(groupGesture, longPressGesture);
+        //gestureApi->addChildGesture(groupGesture, swipeGesture);
+        //gestureApi->addChildGesture(groupGesture, rotationGesture);
+    }
+
+    /* 将手势组设置到组件上 */
+    gestureApi->addGestureToNode(node, groupGesture, PARALLEL, NORMAL_GESTURE_MASK);
+}
+
+static QPointF fix_global_point(const QPointF &pt, int32_t displayId)
+{
+    auto platformScreen = QOhDisplayManager::instance()->platformScreenOrNull(displayId);
+    QPointF result = pt;
+    if (platformScreen) {
+        result += platformScreen->geometry().topLeft();
+    }
+    return result;
+}
+
+void QOhWindowNodeEventHandler::handlePanGestureEvent(ArkUI_GestureEvent *event, void *extraParam)
+{
+    QOhWindowNodeEventHandler *handler = reinterpret_cast<QOhWindowNodeEventHandler*>(extraParam);
+    if (!isValidGestureEvent(event, handler))
+        return;
+    handler->panGesture(event);
+}
+
+void QOhWindowNodeEventHandler::panGesture(ArkUI_GestureEvent *event)
+{
+    auto inputEvent = OH_ArkUI_GestureEvent_GetRawInputEvent(event);
+    float velocity = OH_ArkUI_PanGesture_GetVelocity(event);
+
+    /* GESTURE_EVENT_ACTION_END = 0x04
+     * GESTURE_EVENT_ACTION_ACCEPT = 0x01
+     * GESTURE_EVENT_ACTION_UPDATE = 0x02
+     * GESTURE_EVENT_ACTION_CANCEL = 0x08
+     */
+    ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);
+
+    /* 获取UI输入事件发生的时间 */
+    int64_t timestamp = OH_ArkUI_UIInputEvent_GetEventTime(inputEvent);
+
+    /* 从带有指向性的输入事件中获取相对于当前屏幕左上角的坐标 */
+    float gx = OH_ArkUI_PointerEvent_GetDisplayX(inputEvent);
+    float gy = OH_ArkUI_PointerEvent_GetDisplayY(inputEvent);
+    int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(inputEvent);
+
+    /* 获取特定接触点相对于当前应用窗口左上角的坐标 */
+    float lx = OH_ArkUI_PointerEvent_GetWindowX(inputEvent);
+    float ly = OH_ArkUI_PointerEvent_GetWindowY(inputEvent);
+
+    /* 获取产生UI输入事件的来源类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(inputEvent);
+    auto gestureType = [](int actionType) {
+        switch (actionType) {
+        case GESTURE_EVENT_ACTION_END:
+            return Qt::EndNativeGesture;
+        case GESTURE_EVENT_ACTION_ACCEPT:
+            return Qt::BeginNativeGesture;
+        default:
+            break;
+        }
+        return Qt::PanNativeGesture;
+    };
+
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+        QSharedPointer<QtOh::GestureEvent> e(new QtOh::GestureEvent());
+        e->value = velocity;
+        e->timestamp = timestamp;
+        e->local = QPointF(lx, ly);
+        e->global = fix_global_point(QPointF(gx,gy), displayId);
+        e->sourceType = sourceType;
+        e->gestureType = gestureType(actionType);
+        e->window = m_window;
+        dispatcher->appendOhEvent(e);
+    }
+}
+
+void QOhWindowNodeEventHandler::handleLongPressGesture(ArkUI_GestureEvent *event, void *extraParam)
+{
+    QOhWindowNodeEventHandler *handler = reinterpret_cast<QOhWindowNodeEventHandler*>(extraParam);
+    if (!isValidGestureEvent(event, handler))
+        return;
+
+    handler->longPressGesture(event);
+}
+
+void QOhWindowNodeEventHandler::longPressGesture(ArkUI_GestureEvent *event)
+{
+    auto inputEvent = OH_ArkUI_GestureEvent_GetRawInputEvent(event);
+    /* 获取产生UI输入事件的工具类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_TOOL_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENT_TOOL_TYPE_FINGER = 1,
+     * UI_INPUT_EVENT_TOOL_TYPE_PEN = 2,
+     * UI_INPUT_EVENT_TOOL_TYPE_MOUSE = 3,
+     * UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD = 4,
+     * UI_INPUT_EVENT_TOOL_TYPE_JOYSTICK = 5
+     */
+    int32_t toolType = OH_ArkUI_UIInputEvent_GetToolType(inputEvent);
+
+    float scale = OH_ArkUI_PinchGesture_GetScale(event);
+    /* GESTURE_EVENT_ACTION_ACCEPT = 0x01
+     * GESTURE_EVENT_ACTION_UPDATE = 0x02,
+     * GESTURE_EVENT_ACTION_END = 0x04,
+     * GESTURE_EVENT_ACTION_CANCEL = 0x08
+     */
+    ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);
+
+    /* 获取产生UI输入事件的来源类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(inputEvent);
+
+    /* 获取UI输入事件发生的时间 */
+    int64_t timestamp = OH_ArkUI_UIInputEvent_GetEventTime(inputEvent);
+
+    /* 从带有指向性的输入事件中获取相对于当前屏幕左上角的坐标 */
+    float gx = OH_ArkUI_PointerEvent_GetDisplayX(inputEvent);
+    float gy = OH_ArkUI_PointerEvent_GetDisplayY(inputEvent);
+    int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(inputEvent);
+
+    /* 获取特定接触点相对于当前应用窗口左上角的坐标 */
+    float lx = OH_ArkUI_PointerEvent_GetWindowX(inputEvent);
+    float ly = OH_ArkUI_PointerEvent_GetWindowY(inputEvent);
+    bool mouseTriggered = (UI_INPUT_EVENT_TOOL_TYPE_MOUSE == toolType || UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD == toolType);
+    /* NOTE 将长按手势绑定到Qt的QContextMenu事件
+     * 只处理开始的通知,避免重复发送事件通知
+     */
+    if (GESTURE_EVENT_ACTION_ACCEPT == actionType) {
+        // Todo 从event 获取mods
+        QWindowSystemInterface::handleContextMenuEvent(m_window,  mouseTriggered, QPointF(lx, ly).toPoint(), fix_global_point(QPointF(gx, gy), displayId).toPoint(),
+                                                       QOhKeys::keyboardModifiers());
+    }
+}
+
+void QOhWindowNodeEventHandler::handlePinchGestureEvent(ArkUI_GestureEvent *event, void *extraParam)
+{
+    QOhWindowNodeEventHandler *handler = reinterpret_cast<QOhWindowNodeEventHandler*>(extraParam);
+    if (!isValidGestureEvent(event, handler))
+        return;
+
+    handler->pinchGestureEvent(event);
+}
+
+void QOhWindowNodeEventHandler::pinchGestureEvent(ArkUI_GestureEvent *event)
+{
+    auto inputEvent = OH_ArkUI_GestureEvent_GetRawInputEvent(event);
+    /* 获取产生UI输入事件的工具类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_TOOL_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENT_TOOL_TYPE_FINGER = 1,
+     * UI_INPUT_EVENT_TOOL_TYPE_PEN = 2,
+     * UI_INPUT_EVENT_TOOL_TYPE_MOUSE = 3,
+     * UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD = 4,
+     * UI_INPUT_EVENT_TOOL_TYPE_JOYSTICK = 5
+     */
+    int32_t toolType = OH_ArkUI_UIInputEvent_GetToolType(inputEvent);
+
+    /* 过滤来自鼠标/触控板的系统手势 */
+    if (UI_INPUT_EVENT_TOOL_TYPE_MOUSE == toolType ||
+        UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD == toolType) {
+        return;
+    }
+
+    float scale = OH_ArkUI_PinchGesture_GetScale(event);
+    /* GESTURE_EVENT_ACTION_ACCEPT = 0x01
+     * GESTURE_EVENT_ACTION_UPDATE = 0x02,
+     * GESTURE_EVENT_ACTION_END = 0x04,
+     * GESTURE_EVENT_ACTION_CANCEL = 0x08
+     */
+    ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);
+
+    /* 获取产生UI输入事件的来源类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(inputEvent);
+
+    /* 获取UI输入事件发生的时间 */
+    int64_t timestamp = OH_ArkUI_UIInputEvent_GetEventTime(inputEvent);
+
+    /* 从带有指向性的输入事件中获取相对于当前屏幕左上角的坐标 */
+    float gx = OH_ArkUI_PointerEvent_GetDisplayX(inputEvent);
+    float gy = OH_ArkUI_PointerEvent_GetDisplayY(inputEvent);
+    int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(inputEvent);
+    /* 获取特定接触点相对于当前应用窗口左上角的坐标 */
+    float lx = OH_ArkUI_PointerEvent_GetWindowX(inputEvent);
+    float ly = OH_ArkUI_PointerEvent_GetWindowY(inputEvent);
+
+    auto gestureType = [](int actionType) {
+        switch (actionType) {
+        case GESTURE_EVENT_ACTION_END:
+            return Qt::EndNativeGesture;
+        case GESTURE_EVENT_ACTION_ACCEPT:
+            return Qt::BeginNativeGesture;
+        default:
+            break;
+        }
+        return Qt::ZoomNativeGesture;
+    };
+
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+        QSharedPointer<QtOh::GestureEvent> e(new QtOh::GestureEvent());
+        e->value = scale;
+        e->timestamp = timestamp;
+        e->local = QPointF(lx, ly);
+        e->global = fix_global_point(QPointF(gx, gy), displayId);
+        e->sourceType = sourceType;
+        e->gestureType = gestureType(actionType);
+        e->window = m_window;
+        dispatcher->appendOhEvent(e);
+    }
+}
+
+void QOhWindowNodeEventHandler::handleSwipeGestureEvent(ArkUI_GestureEvent *event, void *extraParam)
+{
+    QOhWindowNodeEventHandler *handler = reinterpret_cast<QOhWindowNodeEventHandler*>(extraParam);
+    if (!isValidGestureEvent(event, handler))
+        return;
+
+    handler->swipeGestureEvent(event);
+}
+
+void QOhWindowNodeEventHandler::swipeGestureEvent(ArkUI_GestureEvent *event)
+{
+    auto inputEvent = OH_ArkUI_GestureEvent_GetRawInputEvent(event);
+    float angle = OH_ArkUI_SwipeGesture_GetAngle(event);
+    float velocity = OH_ArkUI_SwipeGesture_GetVelocity(event);
+
+    /* GESTURE_EVENT_ACTION_ACCEPT = 0x01
+     * GESTURE_EVENT_ACTION_UPDATE = 0x02,
+     * GESTURE_EVENT_ACTION_END = 0x04,
+     * GESTURE_EVENT_ACTION_CANCEL = 0x08
+     */
+    ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);
+
+    /* 获取UI输入事件发生的时间 */
+    int64_t timestamp = OH_ArkUI_UIInputEvent_GetEventTime(inputEvent);
+
+    /* 获取产生UI输入事件的来源类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(inputEvent);
+
+    /* 从带有指向性的输入事件中获取相对于当前屏幕左上角的坐标 */
+    float gx = OH_ArkUI_PointerEvent_GetDisplayX(inputEvent);
+    float gy = OH_ArkUI_PointerEvent_GetDisplayY(inputEvent);
+    int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(inputEvent);
+    /* 获取特定接触点相对于当前应用窗口左上角的坐标 */
+    float lx = OH_ArkUI_PointerEvent_GetWindowX(inputEvent);
+    float ly = OH_ArkUI_PointerEvent_GetWindowY(inputEvent);
+
+    auto gestureType = [](int actionType) {
+        switch (actionType) {
+        case GESTURE_EVENT_ACTION_END:
+            return Qt::EndNativeGesture;
+        case GESTURE_EVENT_ACTION_ACCEPT:
+            return Qt::BeginNativeGesture;
+        default:
+            break;
+        }
+        return Qt::SwipeNativeGesture;
+    };
+
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+        QSharedPointer<QtOh::GestureEvent> e(new QtOh::GestureEvent());
+        e->value = velocity;
+        e->timestamp = timestamp;
+        e->local = QPointF(lx, ly);
+        e->global = fix_global_point(QPointF(gx, gy), displayId);
+        e->sourceType = sourceType;
+        e->gestureType = gestureType(actionType);
+        e->window = m_window;
+        dispatcher->appendOhEvent(e);
+    }
+}
+
+void QOhWindowNodeEventHandler::handleRotationGestureEvent(ArkUI_GestureEvent *event, void *extraParam)
+{
+    QOhWindowNodeEventHandler *handler = reinterpret_cast<QOhWindowNodeEventHandler*>(extraParam);
+    if (!isValidGestureEvent(event, handler))
+        return;
+    handler->rotationGestureEvent(event);
+}
+
+void QOhWindowNodeEventHandler::rotationGestureEvent(ArkUI_GestureEvent *event)
+{
+    auto inputEvent = OH_ArkUI_GestureEvent_GetRawInputEvent(event);
+#if 1
+    /* 获取产生UI输入事件的工具类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_TOOL_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENT_TOOL_TYPE_FINGER = 1,
+     * UI_INPUT_EVENT_TOOL_TYPE_PEN = 2,
+     * UI_INPUT_EVENT_TOOL_TYPE_MOUSE = 3,
+     * UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD = 4,
+     * UI_INPUT_EVENT_TOOL_TYPE_JOYSTICK = 5
+     */
+    int32_t toolType = OH_ArkUI_UIInputEvent_GetToolType(inputEvent);
+
+    /* 过滤来自鼠标/触控板的系统手势 */
+    if (UI_INPUT_EVENT_TOOL_TYPE_MOUSE == toolType ||
+        UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD == toolType) {
+        return;
+    }
+#endif
+    /* GESTURE_EVENT_ACTION_END = 0x04
+     * GESTURE_EVENT_ACTION_ACCEPT = 0x01
+     * GESTURE_EVENT_ACTION_UPDATE = 0x02
+     * GESTURE_EVENT_ACTION_CANCEL = 0x08
+     */
+    ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);
+
+    float angle = OH_ArkUI_RotationGesture_GetAngle(event);
+
+    /* 获取UI输入事件发生的时间 */
+    int64_t timestamp = OH_ArkUI_UIInputEvent_GetEventTime(inputEvent);
+
+    /* 获取产生UI输入事件的来源类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(inputEvent);
+
+    /* 从带有指向性的输入事件中获取相对于当前屏幕左上角的坐标 */
+    float gx = OH_ArkUI_PointerEvent_GetDisplayX(inputEvent);
+    float gy = OH_ArkUI_PointerEvent_GetDisplayY(inputEvent);
+    int32_t displayId = OH_ArkUI_UIInputEvent_GetTargetDisplayId(inputEvent);
+    /* 获取特定接触点相对于当前应用窗口左上角的坐标 */
+    float lx = OH_ArkUI_PointerEvent_GetWindowX(inputEvent);
+    float ly = OH_ArkUI_PointerEvent_GetWindowY(inputEvent);
+
+    auto gestureType = [](int actionType) {
+        switch (actionType) {
+        case GESTURE_EVENT_ACTION_END:
+            return Qt::EndNativeGesture;
+        case GESTURE_EVENT_ACTION_ACCEPT:
+            return Qt::BeginNativeGesture;
+        default:
+            break;
+        }
+        return Qt::RotateNativeGesture;
+    };
+
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+        QSharedPointer<QtOh::GestureEvent> e(new QtOh::GestureEvent());
+        e->value = angle;
+        e->timestamp = timestamp;
+        e->local = QPointF(lx, ly);
+        e->global = fix_global_point(QPointF(gx, gy), displayId);
+        e->sourceType = sourceType;
+        e->gestureType = gestureType(actionType);
+        e->window = m_window;
+        dispatcher->appendOhEvent(e);
+    }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openharmony/qohwindownodeeventhandler.h b/src/plugins/platforms/openharmony/qohwindownodeeventhandler.h
new file mode 100644
index 00000000000..3a3281895e8
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohwindownodeeventhandler.h
@@ -0,0 +1,75 @@
+#ifndef QOHWINDOWNODEEVENTHANDLER_H
+#define QOHWINDOWNODEEVENTHANDLER_H
+
+#include <arkui/native_node.h>
+#include <arkui/native_interface.h>
+#include <arkui/native_gesture.h>
+#include <QtCore/QList>
+#include <QtCore/QEvent>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QHash>
+#include <arkui/native_gesture.h>
+#include "qohwindownode.h"
+#include <qpa/qwindowsysteminterface.h>
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(draganddrop)
+class QOhDropTarget;
+#endif
+class QOhNativeNodeAPI;
+class QOhWindowNodeEventHandler
+{
+public:
+    QOhWindowNodeEventHandler(QOhWindowNode *node);
+    ~QOhWindowNodeEventHandler();
+    void registerEvents(const std::vector<ArkUI_NodeEventType> &events);
+    void unregisterEvents();
+    void setTargetWindow(QWindow *window);
+private:
+    static void nodeEvent(ArkUI_NodeEvent *event);
+    void focusEvent(bool focusIn);
+    void hoverEvent(bool hover);
+#if OHOS_SDK_VERSION > 14
+    void touchEvent(ArkUI_UIInputEvent *inputEvent);
+#endif
+    void mouseEvent(ArkUI_UIInputEvent *event);
+#if OHOS_SDK_VERSION >= 17
+    void keyEvent(ArkUI_UIInputEvent *keyEvent);
+    void wheelEvent(ArkUI_UIInputEvent *event);
+#endif
+private:
+    void handleExternalNodeMouseEvent(const QPointF &global, QEvent::Type type,
+                                      Qt::MouseButton button, Qt::KeyboardModifiers mod);
+#if OHOS_SDK_VERSION > 14
+    void translateMouseEvent(ArkUI_UIInputEvent *inputEvent);
+    void translatePenEvent(ArkUI_UIInputEvent *inputEvent);
+    QHash<int32_t, int> m_pointerIdToTouchId;
+    QHash<int, QWindowSystemInterface::TouchPoint> m_lastTouchPoints;
+#endif
+    static bool isValidGestureEvent(ArkUI_GestureEvent *event, QOhWindowNodeEventHandler *handler);
+    void createGestureRecognizerForNode(ArkUI_NodeHandle node);
+    static void handlePanGestureEvent(ArkUI_GestureEvent *event, void *extraParam);
+    void panGesture(ArkUI_GestureEvent *event);
+    static void handleLongPressGesture(ArkUI_GestureEvent *event, void *extraParam);
+    void longPressGesture(ArkUI_GestureEvent *event);
+    static void handlePinchGestureEvent(ArkUI_GestureEvent *event, void *extraParam);
+    void pinchGestureEvent(ArkUI_GestureEvent *event);
+    static void handleSwipeGestureEvent(ArkUI_GestureEvent *event, void *extraParam);
+    void swipeGestureEvent(ArkUI_GestureEvent *event);
+    static void handleRotationGestureEvent(ArkUI_GestureEvent *event, void *extraParam);
+    void rotationGestureEvent(ArkUI_GestureEvent *event);
+private:
+    QOhWindowNode *m_node;
+    std::vector<ArkUI_NodeEventType> m_events;
+#if QT_CONFIG(draganddrop)
+    QOhDropTarget *m_dropTarget = nullptr;
+#endif
+    QPointer<QWindow> m_window;
+    std::atomic<bool> m_inHanding;
+    QSharedPointer<QOhNativeNodeAPI> m_nodeApi;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOHWINDOWNODEEVENTHANDLER_H
diff --git a/src/plugins/platforms/openharmony/qohxcomponent.cpp b/src/plugins/platforms/openharmony/qohxcomponent.cpp
new file mode 100644
index 00000000000..7dcd31323b2
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohxcomponent.cpp
@@ -0,0 +1,556 @@
+#include <QtMath>
+#include <QThread>
+#include <qopenharmonydefines.h>
+
+#include "qohkeys.h"
+#include "qohmain.h"
+#include "qohevent.h"
+#include "qohauxiliary.h"
+#include "qohxcomponent.h"
+#include "qohwindownode.h"
+#include "qohwindowcontext.h"
+#include "qohplatformscreen.h"
+#include "qohplatformwindow.h"
+#include "qohdisplaymanager.h"
+#include "qoheventdispatcher.h"
+#include "qohplatforminputcontext.h"
+
+OH_NativeXComponent_Callback QOhXComponent::m_componentCallback = []() {
+    OH_NativeXComponent_Callback cb{};
+    cb.OnSurfaceCreated = &QOhXComponent::onSurfaceCreated;
+    cb.OnSurfaceChanged = &QOhXComponent::onSurfaceChanged;
+    cb.OnSurfaceDestroyed = &QOhXComponent::onSurfaceDestroyed;
+    if (OHOS_SDK_VERSION < 15 || QtOh::isOpenHarmonyDevice()) {
+        cb.DispatchTouchEvent = &QOhXComponent::dispatchTouchEvent;
+    } else {
+        cb.DispatchTouchEvent = nullptr;
+    }
+    return cb;
+}();
+
+OH_NativeXComponent_MouseEvent_Callback QOhXComponent::m_mouseEventCallback = {
+    &QOhXComponent::dispatchMouseEvent,
+    nullptr
+};
+
+QMutex QOhXComponent::m_compoentMutex;
+
+QOhXComponent::QOhXComponent(QOhWindowNode *node, OH_NativeXComponent *component)
+    : m_nativeComponent(component)
+    , m_node(node)
+{
+    {
+        QMutexLocker locker(&m_compoentMutex);
+        Q_UNUSED(locker)
+        m_allXCompoents << this;
+    }
+    initXComponent(component);
+}
+
+QOhXComponent::~QOhXComponent()
+{
+    QMutexLocker locker(&m_compoentMutex);
+    Q_UNUSED(locker)
+    m_allXCompoents.removeOne(this);
+}
+
+QString QOhXComponent::name() const
+{
+    return getName(m_nativeComponent);
+}
+
+QOhXComponent *QOhXComponent::find(OH_NativeXComponent *component)
+{
+    QMutexLocker locker(&m_compoentMutex);
+    auto it = std::find_if(m_allXCompoents.constBegin(), m_allXCompoents.constEnd(), [component](QOhXComponent *xc){
+        return (xc->nativeComponent() == component);
+    });
+    if (it == m_allXCompoents.constEnd())
+        return nullptr;
+    return *it;
+}
+
+void QOhXComponent::onSurfaceCreated(OH_NativeXComponent *component, void *window)
+{
+    LOGI("%{public}s %{public}s", Q_FUNC_INFO, qPrintable(getName(component)));
+    auto xc = find(component);
+    if (xc != nullptr)
+        xc->setNativeWindow(window);
+}
+
+void QOhXComponent::onSurfaceChanged(OH_NativeXComponent *component, void *window)
+{
+    uint64_t width;
+    uint64_t height;
+
+    int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
+    if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+        LOGE("Get surface size failed");
+    }
+
+    QtOh::runOnQtMainThread([component, width, height] {
+        auto xc = find(component);
+        if (xc == nullptr)
+            return;
+        xc->handleSurfaceChanged(QSize(width, height));
+    });
+}
+
+void QOhXComponent::onSurfaceDestroyed(OH_NativeXComponent *component, void *window)
+{
+    Q_UNUSED(component);
+    Q_UNUSED(window);
+    QtOh::runOnQtMainThread([component]{
+        auto xc = find(component);
+        if (xc != nullptr)
+            xc->setNativeWindow(nullptr);
+    });
+}
+
+void QOhXComponent::handleWindowStatusEvent(QtOh::WindowStatusType event)
+{
+    if (m_node != nullptr && m_node->platformWindow() != nullptr){
+        QtOh::runOnQtMainThread([event, this]{
+            if (QOhWindowNode::nodeDestroyed(m_node))
+                return ;
+            if (QOhPlatformWindow *window = m_node->platformWindow()) {
+                window->handleWindowStatusEvent(event);
+            }
+        });
+    }
+}
+
+void QOhXComponent::onSurfaceHided(OH_NativeXComponent *component, void *window)
+{
+    Q_UNUSED(window);
+    LOGW("onSurfaceHided: %{public}s", qPrintable(getName(component)));
+    QOhXComponent *xc = find(component);
+    if (xc == nullptr)
+        return;
+
+    xc->handleWindowStatusEvent(QtOh::WindowStatusType::MINIMIZE);
+}
+
+void QOhXComponent::onSurfaceShow(OH_NativeXComponent *component, void *window)
+{
+    Q_UNUSED(window);
+    LOGW("onSurfaceShow: %{public}s", qPrintable(getName(component)));
+    QOhXComponent *xc = find(component);
+    if (xc == nullptr)
+        return;
+    xc->handleWindowStatusEvent(QtOh::WindowStatusType::SURFACE_SHOW);
+}
+
+bool QOhXComponent::dispatchKeyEvent(OH_NativeXComponent *component, void *window)
+{
+    Q_UNUSED(window);
+    QOhPlatformInputContext *context = QOhPlatformInputContext::ohInputContext();
+    if (Q_NULLPTR == component || Q_NULLPTR == context)
+        return true;
+
+    OH_NativeXComponent_KeyEvent *keyEvent = Q_NULLPTR;
+    /* 获取由XComponent触发的按键事件 */
+    if (OH_NativeXComponent_GetKeyEvent(component, &keyEvent) >= 0) {
+        OH_NativeXComponent_KeyAction action;
+        OH_NativeXComponent_GetKeyEventAction(keyEvent, &action); /* 获取按键事件的动作 */
+
+        OH_NativeXComponent_KeyCode code;
+        OH_NativeXComponent_GetKeyEventCode(keyEvent, &code); /*  获取按键事件的键码值 */
+
+        OH_NativeXComponent_EventSourceType sourceType;
+        OH_NativeXComponent_GetKeyEventSourceType(keyEvent, &sourceType); /* 获取按键事件的输入源类型 */
+
+        int64_t deviceId;
+        OH_NativeXComponent_GetKeyEventDeviceId(keyEvent, &deviceId); /* 获取按键事件的设备ID */
+
+        int64_t timeStamp;
+        OH_NativeXComponent_GetKeyEventTimestamp(keyEvent, &timeStamp); /* 获取按键事件的时间戳 */
+
+        QtOh::runOnQtMainThread([qWindow = QPointer<QWindow>(windowFromXComponent(component)), code, action, sourceType, deviceId, timeStamp]{
+            if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+                QSharedPointer<QtOh::KeyEvent> e(new QtOh::KeyEvent());
+                e->window = qWindow;
+                e->code = code;
+                e->action = action;
+                e->stype = sourceType;
+                e->deviceId = deviceId;
+                e->timeStamp = timeStamp;
+                e->keyboardModifiers = QOhKeys::keyboardModifiers();
+                dispatcher->appendOhEvent(e);
+            }
+        });
+    } else {
+        LOGW("Get Key Event Error");
+    }
+
+    return true;
+}
+
+void QOhXComponent::dispatchTouchEvent(OH_NativeXComponent *component, void *window)
+{
+    if (nullptr == component || nullptr == window)
+        return;
+
+    /* NOTE 触摸板会触发touch事件和mouse事件,导致2次鼠标事件 */
+    OH_NativeXComponent_TouchEvent touchEvent;
+    int32_t ret = OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent);
+    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != ret) {
+        LOGE("get touch event failed, error code: [%{public}d]", ret);
+        return;
+    }
+
+    OH_NativeXComponent_EventSourceType sourceType(OH_NATIVEXCOMPONENT_SOURCE_TYPE_UNKNOWN);
+    ret = OH_NativeXComponent_GetTouchEventSourceType(component, touchEvent.id, &sourceType);
+    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != ret) {
+        LOGE("get touch source type failed, code: [%{public}d]", ret);
+        return;
+    }
+
+    /* FIXME 不处理鼠标触发的touch */
+    if (OH_NATIVEXCOMPONENT_SOURCE_TYPE_MOUSE == sourceType ||
+        OH_NATIVEXCOMPONENT_SOURCE_TYPE_UNKNOWN == sourceType) {
+        //LOGW("input source type not process, type: [%{public}d]", sourceType);
+        return;
+    }
+
+    QList<QWindowSystemInterface::TouchPoint> touchPoints;
+    auto qw = windowFromXComponent(component);
+    QPlatformScreen *screen = qw->screen()->handle();
+    QRect rc = screen->geometry();
+    for (int i = 0; i < int(touchEvent.numPoints); i++) {
+        OH_NativeXComponent_TouchPoint &point = touchEvent.touchPoints[i];
+        QWindowSystemInterface::TouchPoint touchPoint;
+        touchPoint.id = point.id;
+        touchPoint.pressure = point.force;
+        touchPoint.rotation = 0;
+        touchPoint.area.setSize(QSize(100, 100));
+        float globalX, globalY;
+        OH_NativeXComponent_GetTouchPointDisplayX(component, point.id, &globalX);
+        OH_NativeXComponent_GetTouchPointDisplayY(component, point.id, &globalY);
+        touchPoint.area.moveCenter(QPointF(globalX, globalY));
+        touchPoint.rawPositions = QVector<QPointF> { QPointF(globalX, globalY).toPoint()
+                                                     , QPointF(globalX, globalY) };
+		/* Qt 6 only modify */
+        touchPoint.normalPosition = QPointF(globalX / rc.width(), globalY / rc.height());
+        touchPoint.state = QEventPoint::State::Updated;
+        if (OH_NATIVEXCOMPONENT_DOWN == point.type)
+            touchPoint.state = QEventPoint::State::Pressed;
+
+        if (OH_NATIVEXCOMPONENT_UP == point.type ||
+            OH_NATIVEXCOMPONENT_CANCEL == point.type)
+            touchPoint.state = QEventPoint::State::Released;
+
+        if (OH_NATIVEXCOMPONENT_MOVE == point.type) {
+            touchPoint.state = QEventPoint::State::Updated;
+        }
+
+        touchPoints.push_back(touchPoint);
+    }
+	/* Qt 6 only modify */
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+        QSharedPointer<QtOh::TouchEvent> e(new QtOh::TouchEvent());
+        e->id = touchEvent.id;
+        e->pointerType = QPointingDevice::PointerType::Unknown;
+        e->deviceType = sourceType ==  OH_NATIVEXCOMPONENT_SOURCE_TYPE_MOUSE ? QPointingDevice::DeviceType::Mouse :
+                QPointingDevice::DeviceType::TouchScreen;
+        switch (sourceType) {
+        case OH_NATIVEXCOMPONENT_SOURCE_TYPE_TOUCHSCREEN:
+        case OH_NATIVEXCOMPONENT_SOURCE_TYPE_TOUCHPAD:
+            e->pointerType = QPointingDevice::PointerType::Finger;
+            break;
+        case OH_NATIVEXCOMPONENT_SOURCE_TYPE_JOYSTICK:
+        case OH_NATIVEXCOMPONENT_SOURCE_TYPE_MOUSE:
+        case OH_NATIVEXCOMPONENT_SOURCE_TYPE_KEYBOARD:
+            e->pointerType = QPointingDevice::PointerType::Generic;
+            break;
+        default:
+            break;
+        }
+        e->touchPoints = touchPoints;
+        e->window = qw;
+        e->actionType = touchEvent.type;
+        e->timestamp = touchEvent.timeStamp;
+        dispatcher->appendOhEvent(e);
+    }
+
+}
+
+void QOhXComponent::dispatchMouseEvent(OH_NativeXComponent *component, void *window)
+{
+    if (QOhPlatformInputContext::ohInputContext() == nullptr)
+        return;
+
+    OH_NativeXComponent_MouseEvent mouseEvent;
+    int32_t ret = OH_NativeXComponent_GetMouseEvent(component, window, &mouseEvent);
+    if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS)
+        return;
+
+    OH_NativeXComponent_MouseEventAction action = mouseEvent.action;
+    OH_NativeXComponent_MouseEventButton button = mouseEvent.button;
+    Qt::MouseButton qbtn = Qt::NoButton;
+    switch (button) {
+    case OH_NATIVEXCOMPONENT_LEFT_BUTTON:
+        qbtn = Qt::LeftButton;
+        break;
+    case OH_NATIVEXCOMPONENT_RIGHT_BUTTON:
+        qbtn = Qt::RightButton;
+        break;
+    case OH_NATIVEXCOMPONENT_MIDDLE_BUTTON:
+        qbtn = Qt::MiddleButton;
+        break;
+    case OH_NATIVEXCOMPONENT_BACK_BUTTON:
+        qbtn = Qt::BackButton;
+        break;
+    case OH_NATIVEXCOMPONENT_FORWARD_BUTTON:
+        qbtn = Qt::ForwardButton;
+        break;
+    default:
+        break;
+    }
+
+           // LOGW("xid %{public}s, mouse event %{public}d, button is %{public}d screen point (%{public}f, %{public}f) xc point (%{public}f, %{public}f)", qPrintable(getName(component)), action, qbtn,
+           //    mouseEvent.screenX, mouseEvent.screenY,mouseEvent.x, mouseEvent.y);
+
+    QSharedPointer<QtOh::MouseEvent> event(new QtOh::MouseEvent());
+    event->mouseButton = qbtn;
+    event->window = windowFromXComponent(component);
+    event->xcPos = QPointF(mouseEvent.x, mouseEvent.y);
+    event->scPos = QPointF(mouseEvent.screenX, mouseEvent.screenY);
+
+    switch (action) {
+    case OH_NATIVEXCOMPONENT_MOUSE_RELEASE:
+        event->mouseEventType = QEvent::MouseButtonRelease;
+        break;
+    case OH_NATIVEXCOMPONENT_MOUSE_PRESS:
+        event->mouseEventType = QEvent::MouseButtonPress;
+        break;
+    case OH_NATIVEXCOMPONENT_MOUSE_MOVE:
+        event->mouseEventType = QEvent::MouseMove;
+        break;
+    default:
+        event->mouseEventType = QEvent::None;
+        break;
+    }
+
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance())
+        dispatcher->appendOhEvent(event);
+}
+
+void QOhXComponent::dispatchHoverEvent(OH_NativeXComponent *component, bool isHover)
+{
+    /* NOTE 已经使用NODE_ON_HOVER注册hover进入离开事件 */
+    Q_UNUSED(component);
+    Q_UNUSED(isHover);
+}
+
+QString QOhXComponent::getName(OH_NativeXComponent *component)
+{
+    char id[OH_XCOMPONENT_ID_LEN_MAX + 1] = { };
+    uint64_t id_length = OH_XCOMPONENT_ID_LEN_MAX + 1;
+
+    int32_t ret = OH_NativeXComponent_GetXComponentId(component, id, &id_length);
+    if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+        return QString();
+    }
+
+    return QString::fromLatin1(id);
+}
+
+QWindow *QOhXComponent::windowFromXComponent(OH_NativeXComponent *component)
+{
+    if (component == nullptr)
+        return nullptr;
+    QPlatformWindow *window = QOhWindowContext::get(QOhXComponent::getName(component));
+    return window == nullptr ? nullptr : window->window();
+}
+
+#if QT_CONFIG(wheelevent)
+void QOhXComponent::dispatchArkUIInputEvent(OH_NativeXComponent *component, ArkUI_UIInputEvent *event,
+                                            ArkUI_UIInputEvent_Type type)
+{
+    Q_UNUSED(type);
+    if (nullptr == event)
+        return;
+
+
+    /* 从带有指向性的输入事件中获取相对于当前屏幕左上角的坐标 */
+    float gx = OH_ArkUI_PointerEvent_GetDisplayX(event);
+    float gy = OH_ArkUI_PointerEvent_GetDisplayY(event);
+
+    /* 获取特定接触点相对于当前应用窗口左上角的坐标 */
+    float lx = OH_ArkUI_PointerEvent_GetX(event);
+    float ly = OH_ArkUI_PointerEvent_GetY(event);
+
+/* FIXME wanghao 多屏时获取当前输入回调的屏幕id错误 */
+#if 0
+    auto displayId= OH_ArkUI_UIInputEvent_GetTargetDisplayId(event);
+    auto platformScreen = QOhDisplayManager::instance()->platformScreenOrNull(displayId);
+    if (platformScreen) {
+        gx += platformScreen->geometry().left();
+        gy += platformScreen->geometry().top();
+    }
+#endif
+
+    float scale = OH_ArkUI_AxisEvent_GetPinchAxisScaleValue(event);
+
+    /* 获取产生UI输入事件的工具类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_TOOL_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENT_TOOL_TYPE_FINGER = 1,
+     * UI_INPUT_EVENT_TOOL_TYPE_PEN = 2,
+     * UI_INPUT_EVENT_TOOL_TYPE_MOUSE = 3,
+     * UI_INPUT_EVENT_TOOL_TYPE_TOUCHPAD = 4,
+     * UI_INPUT_EVENT_TOOL_TYPE_JOYSTICK = 5
+     */
+    int32_t toolType = OH_ArkUI_UIInputEvent_GetToolType(event);
+
+#if OHOS_SDK_VERSION >= 15
+    int32_t axisAction = 0;
+    if(QtOh::apiVersion() >= 15){
+        /* 获取当前轴事件的操作类型的值
+         * UI_AXIS_EVENT_ACTION_NONE = 0,   // The axis event is abnormal.
+         * UI_AXIS_EVENT_ACTION_BEGIN = 1,  // The axis event begins.
+         * UI_AXIS_EVENT_ACTION_UPDATE = 2, // The axis event is updated.
+         * UI_AXIS_EVENT_ACTION_END = 3,    // The axis event ends.
+         * UI_AXIS_EVENT_ACTION_CANCEL = 4, // The axis event is canceled.
+         */
+        axisAction = OH_ArkUI_AxisEvent_GetAxisAction(event);
+
+        /* NOTE 鼠标滚轮只处理UPDATE? */
+        if (UI_INPUT_EVENT_TOOL_TYPE_MOUSE == toolType &&
+            UI_AXIS_EVENT_ACTION_UPDATE != axisAction) {
+            return;
+        }
+    }
+#endif    
+
+#if OHOS_SDK_VERSION >= 17
+    int32_t scrollStep = qMax(1, OH_ArkUI_AxisEvent_GetScrollStep(event));
+#endif
+
+    /* 获取UI输入事件发生的时间 */
+    int64_t timestamp = OH_ArkUI_UIInputEvent_GetEventTime(event);
+
+    /* 获取产生UI输入事件的来源类型,鸿蒙端定义如下:
+     * UI_INPUT_EVENT_SOURCE_TYPE_UNKNOWN = 0,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_MOUSE = 1,
+     * UI_INPUT_EVENTT_SOURCE_TYPE_TOUCH_SCREEN = 2
+     */
+    int32_t sourceType = OH_ArkUI_UIInputEvent_GetSourceType(event);
+    double verticalValue = OH_ArkUI_AxisEvent_GetVerticalAxisValue(event);
+    double horizontalValue = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(event);
+
+    if (QOhEventDispatcher *dispatcher = QOhEventDispatcher::instance()) {
+        QSharedPointer<QtOh::WheelEvent> e(new QtOh::WheelEvent());
+        e->pinchScale = scale;
+        e->toolType = toolType;
+        e->timestamp = timestamp;
+
+#if OHOS_SDK_VERSION >= 15
+        e->axisAction = axisAction;
+#endif
+
+#if OHOS_SDK_VERSION >= 17
+        e->scrollStep = scrollStep;
+#endif
+        e->sourceType = sourceType;
+        e->local = QPointF(lx, ly);
+        /* FIXME wanghao 多屏坐标错误的临时处理 */
+        e->window = windowFromXComponent(component);
+        e->global = e->window->handle()->mapToGlobal(e->local.toPoint());
+
+        e->verticalValue = verticalValue;
+        e->horizontalValue = horizontalValue;
+        dispatcher->appendOhEvent(e);
+    }
+}
+#endif
+
+void QOhXComponent::initXComponent(OH_NativeXComponent *component)
+{
+    if (m_nativeComponent != nullptr) {
+        /* 注册界面渲染事件回调 */
+        int32_t ret = OH_NativeXComponent_RegisterCallback(component, &m_componentCallback);
+        if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+            LOGE("set surface touch callback failed");
+        }
+
+        /* 注册获焦-失焦回调 */
+        ret = OH_NativeXComponent_RegisterFocusEventCallback(component, &QOhXComponent::onFocusInEvent);
+        if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+            LOGI("register focus in callback failed.");
+        }
+
+        ret = OH_NativeXComponent_RegisterBlurEventCallback(component, &QOhXComponent::onFocusOutEvent);
+        if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+            LOGI("register focus in callback failed.");
+        }
+#if QT_CONFIG(wheelevent)
+#if OHOS_SDK_VERSION < 17 // API17 使用node的回调
+        /* 注册UI输入事件回调,轴事件 */
+        ret = OH_NativeXComponent_RegisterUIInputEventCallback(component, &QOhXComponent::dispatchArkUIInputEvent,
+                                                               ARKUI_UIINPUTEVENT_TYPE_AXIS);
+
+        if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+            LOGE("set axis event callback failed");
+        }
+#endif
+#endif
+       // 如果API>=15,则使用多模鼠标事件
+       // 代码见QOhNormalWindow::windowMouseEventFilter
+        if (OHOS_SDK_VERSION < 15 || QtOh::isOpenHarmonyDevice()) {
+            /* 注册界鼠标事件回调 */
+            ret = OH_NativeXComponent_RegisterMouseEventCallback(component, &m_mouseEventCallback);
+            if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+                LOGE("set surface mouse callback failed");
+            }
+        }
+
+#if OHOS_SDK_VERSION < 17 // API17 使用node的回调
+        /* 注册键盘事件回调 */
+        /*dispatchKeyEvent返回true时,该事件将不会继续分发(阻止tab键触发xc走焦)*/
+        ret = OH_NativeXComponent_RegisterKeyEventCallbackWithResult(component, &QOhXComponent::dispatchKeyEvent);
+        if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS)
+            LOGE("set surface keybord callback failed");
+#endif
+        ret = OH_NativeXComponent_RegisterSurfaceShowCallback(component, &QOhXComponent::onSurfaceShow);
+        if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS)
+            LOGE("set surface show callback failed");
+    }
+}
+
+OH_NativeXComponent *QOhXComponent::nativeComponent() const
+{
+    return m_nativeComponent;
+}
+
+void QOhXComponent::setNativeXComponent(OH_NativeXComponent *component)
+{
+    m_nativeComponent = component;
+    initXComponent(component);
+}
+
+void QOhXComponent::onFocusInEvent(OH_NativeXComponent *component, void *window)
+{
+    Q_UNUSED(component);
+    Q_UNUSED(window);
+}
+
+void QOhXComponent::onFocusOutEvent(OH_NativeXComponent *component, void *window)
+{
+    Q_UNUSED(component);
+    Q_UNUSED(window);
+}
+
+void QOhXComponent::setNativeWindow(void *nativeWindow)
+{
+    if (m_node == nullptr)
+        return;
+    m_node->setNativeWindow(nativeWindow);
+}
+
+void QOhXComponent::handleSurfaceChanged(const QSize &size)
+{    
+    if (m_node == nullptr)
+        return;
+    m_node->handleSurfaceChanged(size);
+}
diff --git a/src/plugins/platforms/openharmony/qohxcomponent.h b/src/plugins/platforms/openharmony/qohxcomponent.h
new file mode 100644
index 00000000000..d88d1eb4483
--- /dev/null
+++ b/src/plugins/platforms/openharmony/qohxcomponent.h
@@ -0,0 +1,70 @@
+#ifndef QOHXCOMPONENT_H
+#define QOHXCOMPONENT_H
+
+#include <QString>
+#include <QSize>
+#include <QMutex>
+#include <QtGui/qtguiglobal.h>
+#include <native_window/external_window.h>
+#include <ace/xcomponent/native_interface_xcomponent.h>
+#if QT_CONFIG(wheelevent)
+#include <arkui/ui_input_event.h>
+#endif
+
+class QOhWindowNode;
+class QWindow;
+struct OH_NativeXComponent;
+
+class QOhXComponent
+{
+public:
+    QOhXComponent(QOhWindowNode *node, OH_NativeXComponent *component = nullptr);
+    virtual ~QOhXComponent();
+
+    QString name() const;
+    OH_NativeXComponent *nativeComponent() const;
+
+    void setNativeWindow(void *nativeWindow);
+
+    void handleSurfaceChanged(const QSize &size);
+private:
+    void setNativeXComponent(OH_NativeXComponent *component);
+
+    static void onFocusInEvent(OH_NativeXComponent *component, void *window);
+    static void onFocusOutEvent(OH_NativeXComponent *component, void *window);
+    static void onSurfaceCreated(OH_NativeXComponent* component, void* window);
+
+    static void onSurfaceChanged(OH_NativeXComponent* component, void* window);
+
+    static void onSurfaceDestroyed(OH_NativeXComponent* component, void* window);
+
+    static void onSurfaceHided(OH_NativeXComponent *component, void *window);
+    static void onSurfaceShow(OH_NativeXComponent *component, void *window);
+
+    static bool dispatchKeyEvent(OH_NativeXComponent *component, void *window);
+
+    static void dispatchTouchEvent(OH_NativeXComponent* component, void* window);
+
+    static void dispatchMouseEvent(OH_NativeXComponent* component, void* window);
+    static void dispatchHoverEvent(OH_NativeXComponent *component, bool isHover);
+
+#if QT_CONFIG(wheelevent)
+    static void dispatchArkUIInputEvent(OH_NativeXComponent* component, ArkUI_UIInputEvent* event,
+                                        ArkUI_UIInputEvent_Type type);
+#endif
+
+private:
+    static QOhXComponent *find(OH_NativeXComponent *component);
+    static QString getName(OH_NativeXComponent *component);
+    static QWindow *windowFromXComponent(OH_NativeXComponent *component);
+    void initXComponent(OH_NativeXComponent *component);
+    void handleWindowStatusEvent(QtOh::WindowStatusType event);
+private:
+    static OH_NativeXComponent_Callback m_componentCallback;
+    static OH_NativeXComponent_MouseEvent_Callback m_mouseEventCallback;
+    static inline QList<QOhXComponent *> m_allXCompoents = {};
+    static QMutex m_compoentMutex;
+    OH_NativeXComponent *m_nativeComponent = nullptr;
+    QOhWindowNode *m_node;
+};
+#endif // QOHXCOMPONENT_H
diff --git a/src/plugins/printsupport/CMakeLists.txt b/src/plugins/printsupport/CMakeLists.txt
index 77366847622..75074c3ac70 100644
--- a/src/plugins/printsupport/CMakeLists.txt
+++ b/src/plugins/printsupport/CMakeLists.txt
@@ -1,6 +1,9 @@
 # Copyright (C) 2022 The Qt Company Ltd.
 # SPDX-License-Identifier: BSD-3-Clause
 
+if(OHOS)
+    add_subdirectory(openharmony)
+endif()
 if(QT_FEATURE_cups AND UNIX AND NOT APPLE)
     add_subdirectory(cups)
 endif()
diff --git a/src/plugins/printsupport/openharmony/CMakeLists.txt b/src/plugins/printsupport/openharmony/CMakeLists.txt
new file mode 100644
index 00000000000..531244621cd
--- /dev/null
+++ b/src/plugins/printsupport/openharmony/CMakeLists.txt
@@ -0,0 +1,24 @@
+qt_find_package(Cups PROVIDED_TARGETS Cups::Cups)
+#####################################################################
+## QOpenHarmonyPrinterSupportPlugin Plugin:
+#####################################################################
+
+qt_internal_add_plugin(QOpenHarmonyPrinterSupportPlugin
+    OUTPUT_NAME openharmonyprintersupport
+    PLUGIN_TYPE printsupport
+    SOURCES
+		main.cpp
+		qopenharmonyprintdevice.cpp qopenharmonyprintdevice.h
+		qopenharmonyprintersupport.cpp qopenharmonyprintersupport_p.h
+		qopenharmonyprintengine.cpp qopenharmonyprintengine_p.h
+    INCLUDE_DIRECTORIES
+        ../../../printsupport/kernel
+    LIBRARIES
+        Qt::Core
+        Qt::CorePrivate
+        Qt::Gui
+        Qt::GuiPrivate
+        Qt::PrintSupport
+        Qt::PrintSupportPrivate
+		ohprint ace_napi.z ohfileuri ace_ndk.z rawfile.z
+)
diff --git a/src/plugins/printsupport/openharmony/main.cpp b/src/plugins/printsupport/openharmony/main.cpp
new file mode 100644
index 00000000000..1d0597b7314
--- /dev/null
+++ b/src/plugins/printsupport/openharmony/main.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qopenharmonyprintersupport_p.h"
+
+#include <qpa/qplatformprintplugin.h>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class QOhPrinterSupportPlugin : public QPlatformPrinterSupportPlugin
+{
+    Q_OBJECT
+    Q_PLUGIN_METADATA(IID QPlatformPrinterSupportFactoryInterface_iid FILE "openharmonyprint.json")
+
+public:
+    QStringList keys() const;
+    QPlatformPrinterSupport *create(const QString &) override;
+};
+
+QStringList QOhPrinterSupportPlugin::keys() const
+{
+    return QStringList(QStringLiteral("openharmonyprintersupport"));
+}
+
+QPlatformPrinterSupport *QOhPrinterSupportPlugin::create(const QString &key)
+{
+    if (key.compare(key, QLatin1String("openharmonyprintersupport"), Qt::CaseInsensitive) == 0)
+        return new QOpenHarmonyPrinterSupport;
+    return 0;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/printsupport/openharmony/openharmonyprint.json b/src/plugins/printsupport/openharmony/openharmonyprint.json
new file mode 100644
index 00000000000..f9a1786cf7d
--- /dev/null
+++ b/src/plugins/printsupport/openharmony/openharmonyprint.json
@@ -0,0 +1,3 @@
+{
+    "Keys": [ "openharmonyprintersupport" ]
+}
diff --git a/src/plugins/printsupport/openharmony/qopenharmonyprintdevice.cpp b/src/plugins/printsupport/openharmony/qopenharmonyprintdevice.cpp
new file mode 100644
index 00000000000..5fe97d148ff
--- /dev/null
+++ b/src/plugins/printsupport/openharmony/qopenharmonyprintdevice.cpp
@@ -0,0 +1,541 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopenharmonyprintdevice.h"
+
+#include "qopenharmonyprintersupport_p.h"
+
+#include <QDebug>
+
+#if QT_CONFIG(mimetype)
+#include <QtCore/QMimeDatabase>
+#endif
+
+QT_BEGIN_NAMESPACE
+#define PDPK_OHOSPrinterId QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 100)
+QOpenHarmonyPrintDevice::QOpenHarmonyPrintDevice(const QString &id)
+    : QPlatformPrintDevice(id),
+      m_printerInfo(new Print_PrinterInfo),
+      m_ppd(0)
+{
+    if (!id.isEmpty()) {
+        m_PrinterId = id.toUtf8();
+        // Get the print instance and PPD file
+        //鸿蒙native接口中没有ppd相关接口。
+        int ret = OH_Print_QueryPrinterInfo(m_PrinterId.constData(), &m_printerInfo);
+        if(PRINT_ERROR_NONE == ret){
+//            m_id = m_printerInfo->printerId;
+            m_id = m_printerInfo->printerName;
+            m_name = m_printerInfo->printerName;
+            m_location = m_printerInfo->location;
+            m_makeAndModel = m_printerInfo->makeAndModel;
+            //鸿蒙native接口中没有下面几个信息,暂定为false。
+            m_isRemote = false;
+            m_supportsMultipleCopies = false;
+            m_supportsCollateCopies = false;
+            m_supportsCustomPageSizes = false;
+        }
+        else{
+            qWarning() << "QOpenHarmonyPrintDevice:query printer info fail,errCode:" << ret;
+            m_printerInfo = nullptr;
+        }
+    }else{
+        m_printerInfo = nullptr;
+        qWarning() << "QOpenHarmonyPrintDevice:device id is empty";
+    }
+}
+
+QOpenHarmonyPrintDevice::~QOpenHarmonyPrintDevice()
+{
+    if (m_ppd)
+        //鸿蒙native接口中没有ppd相关接口。
+        //ppdClose(m_ppd);
+    if (m_printerInfo)
+        OH_Print_ReleasePrinterInfo(m_printerInfo);
+    m_printerInfo = 0;
+    m_ppd = 0;
+}
+
+bool QOpenHarmonyPrintDevice::isValid() const
+{
+    return m_printerInfo;
+}
+
+bool QOpenHarmonyPrintDevice::isDefault() const
+{
+    return m_printerInfo->isDefaultPrinter;
+}
+
+QPrint::DeviceState QOpenHarmonyPrintDevice::state() const
+{
+    Print_PrinterState state = m_printerInfo ? m_printerInfo->printerState : PRINTER_UNAVAILABLE;
+    if (PRINTER_IDLE == state)
+        return QPrint::Idle;
+    else if (PRINTER_BUSY == state)
+        /* TODO 待确定PRINTER_BUSY对应Active还是Aborted */
+        return QPrint::Active;
+    else if (PRINTER_UNAVAILABLE == state)
+        return QPrint::Error;
+    else
+        return QPrint::Error;
+}
+
+extern qreal qt_pointMultiplier(QPageLayout::Unit unit);
+void QOpenHarmonyPrintDevice::loadPageSizes() const
+{
+    if(!m_printerInfo)
+        return;
+
+    m_pageSizes.clear();
+    m_printableMargins.clear();
+
+    Print_PrinterCapability printerCapability = m_printerInfo->capability;
+    Print_Margin defaultMargin = m_printerInfo->defaultValue.defaultMargin;
+    uint32_t pageSizesCount = printerCapability.supportedPageSizesCount;
+    Print_PageSize *pageSize = printerCapability.supportedPageSizes;
+    static auto converToPoint = [](uint32_t value)->int {
+        const double factor = 25.4 * qt_pointMultiplier(QPageLayout::Millimeter) / 1000.0;
+        return qRound(value * factor);
+    };
+    static auto converToMillimeter = [](uint32_t value) {
+        return value / 1000.0;
+    };
+
+    for(uint32_t i = 0; i < pageSizesCount; ++i){
+        QString key = pageSize[i].id;
+        QSize size = QSize(converToPoint(pageSize[i].width), converToPoint(pageSize[i].height));
+        QString name = QString::fromLocal8Bit(pageSize[i].name);
+        if (!size.isEmpty()) {
+            QPageSize ps = createPageSize(key, size, name);
+            qWarning() << "create page size:" << ps << "original size:" << QSize(pageSize[i].width, pageSize[i].height);
+            if (ps.isValid()) {
+                m_pageSizes.append(ps);
+                m_printableMargins.insert(key, QMarginsF(converToMillimeter(defaultMargin.leftMargin),
+                                                         converToMillimeter(defaultMargin.topMargin),
+                                                         converToMillimeter(defaultMargin.rightMargin),
+                                                         converToMillimeter(defaultMargin.bottomMargin)) );
+            }
+        }
+    }
+
+    m_havePageSizes = true;
+}
+
+QPageSize QOpenHarmonyPrintDevice::defaultPageSize() const
+{
+    if(!m_printerInfo)
+        return QPageSize();
+
+    Print_DefaultValue defaultVal = m_printerInfo->defaultValue;
+    QString key = QString::fromLocal8Bit(defaultVal.defaultPageSizeId);
+    auto it = std::find_if(m_pageSizes.constBegin(), m_pageSizes.constEnd(),[&key](const QPageSize &page){
+        return key == page.key();
+    });
+
+    return it == m_pageSizes.constEnd() ? QPageSize() : *it;
+}
+
+QMarginsF QOpenHarmonyPrintDevice::printableMargins(const QPageSize &pageSize,
+                                            QPageLayout::Orientation orientation,
+                                            int resolution) const
+{
+    Q_UNUSED(orientation)
+    Q_UNUSED(resolution)
+    if (!m_havePageSizes)
+        loadPageSizes();
+    // TODO Orientation?
+    if (m_printableMargins.contains(pageSize.key()))
+        return m_printableMargins.value(pageSize.key());
+    return m_customMargins;
+}
+
+void QOpenHarmonyPrintDevice::loadResolutions() const
+{
+    if(!m_printerInfo)
+        return;
+
+    m_resolutions.clear();
+
+    Print_Resolution *resolution = m_printerInfo->capability.supportedResolutions;
+    uint resolutionCount = m_printerInfo->capability.supportedResolutionsCount;
+
+    //Try load printer supportedResolutions
+    if(resolutionCount > 0){
+        for (int i = 0; i < resolutionCount; ++i) {
+            /* FIXME 暂定水平和垂直分辨率相同 */
+            if((resolution[i].horizontalDpi > 0) &&
+                (!m_resolutions.contains(resolution[i].horizontalDpi))){
+                m_resolutions.append(resolution[i].horizontalDpi);
+            }
+        }
+    }
+
+    // If no result, try just the default
+    if (m_resolutions.size() == 0) {
+        Print_Resolution defaultResolution = m_printerInfo->defaultValue.defaultResolution;
+        if((defaultResolution.horizontalDpi > 0) &&
+            (!m_resolutions.contains(defaultResolution.horizontalDpi))){
+            m_resolutions.append(defaultResolution.horizontalDpi);
+        }
+    }
+
+    m_haveResolutions = true;
+}
+
+int QOpenHarmonyPrintDevice::defaultResolution() const
+{
+    if(!m_printerInfo)
+        return 72;
+
+    Print_Resolution defaultResolution = m_printerInfo->defaultValue.defaultResolution;
+    int res = defaultResolution.horizontalDpi;
+    if(res > 0){
+        return res;
+    }
+    // Otherwise return a sensible default.
+    // TODO What is sensible? 150? 300?
+    return 72;
+}
+
+//todo:鸿蒙native接口中没有InputSlots信息
+void QOpenHarmonyPrintDevice::loadInputSlots() const
+{
+    // // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+    // // TODO Deal with concatenated names like Tray1Manual or Tray1_Man,
+    // //      will currently show as CustomInputSlot
+    // // TODO Deal with separate ManualFeed key
+    // // Try load standard PPD options first
+    // m_inputSlots.clear();
+    // if (m_ppd) {
+    //     ppd_option_t *inputSlots = ppdFindOption(m_ppd, "InputSlot");
+    //     if (inputSlots) {
+    //         m_inputSlots.reserve(inputSlots->num_choices);
+    //         for (int i = 0; i < inputSlots->num_choices; ++i)
+    //             m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[i]));
+    //     }
+    //     // If no result, try just the default
+    //     if (m_inputSlots.size() == 0) {
+    //         inputSlots = ppdFindOption(m_ppd, "DefaultInputSlot");
+    //         if (inputSlots)
+    //             m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[0]));
+    //     }
+    // }
+    // // If still no result, just use Auto
+    // if (m_inputSlots.size() == 0)
+    //     m_inputSlots.append(QPlatformPrintDevice::defaultInputSlot());
+    // m_haveInputSlots = true;
+}
+
+QPrint::InputSlot QOpenHarmonyPrintDevice::defaultInputSlot() const
+{
+    //todo:鸿蒙native接口中没有InputSlots信息
+    // // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+    // // Try load standard PPD option first
+    // if (m_ppd) {
+    //     ppd_option_t *inputSlot = ppdFindOption(m_ppd, "DefaultInputSlot");
+    //     if (inputSlot)
+    //         return QPrintUtils::ppdChoiceToInputSlot(inputSlot->choices[0]);
+    //     // If no result, then try a marked option
+    //     ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "InputSlot");
+    //     if (defaultChoice)
+    //         return QPrintUtils::ppdChoiceToInputSlot(*defaultChoice);
+    // }
+    // Otherwise return Auto
+    return QPlatformPrintDevice::defaultInputSlot();
+}
+//todo:鸿蒙native接口中没有OutputBins信息
+void QOpenHarmonyPrintDevice::loadOutputBins() const
+{
+    // // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+    // m_outputBins.clear();
+    // if (m_ppd) {
+    //     ppd_option_t *outputBins = ppdFindOption(m_ppd, "OutputBin");
+    //     if (outputBins) {
+    //         m_outputBins.reserve(outputBins->num_choices);
+    //         for (int i = 0; i < outputBins->num_choices; ++i)
+    //             m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[i]));
+    //     }
+    //     // If no result, try just the default
+    //     if (m_outputBins.size() == 0) {
+    //         outputBins = ppdFindOption(m_ppd, "DefaultOutputBin");
+    //         if (outputBins)
+    //             m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[0]));
+    //     }
+    // }
+    // // If still no result, just use Auto
+    // if (m_outputBins.size() == 0)
+    //     m_outputBins.append(QPlatformPrintDevice::defaultOutputBin());
+    // m_haveOutputBins = true;
+}
+
+QPrint::OutputBin QOpenHarmonyPrintDevice::defaultOutputBin() const
+{
+    //todo:鸿蒙native接口中没有OutputBins信息
+    // // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+    // // Try load standard PPD option first
+    // if (m_ppd) {
+    //     ppd_option_t *outputBin = ppdFindOption(m_ppd, "DefaultOutputBin");
+    //     if (outputBin)
+    //         return QPrintUtils::ppdChoiceToOutputBin(outputBin->choices[0]);
+    //     // If no result, then try a marked option
+    //     ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "OutputBin");
+    //     if (defaultChoice)
+    //         return QPrintUtils::ppdChoiceToOutputBin(*defaultChoice);
+    // }
+    // Otherwise return AutoBin
+    return QPlatformPrintDevice::defaultOutputBin();
+}
+
+void QOpenHarmonyPrintDevice::loadDuplexModes() const
+{
+    if(!m_printerInfo)
+        return;
+
+    // Try load standard PPD options first
+    m_duplexModes.clear();
+    Print_DuplexMode *duplexModes = m_printerInfo->capability.supportedDuplexModes;
+    uint duplexModesCount = m_printerInfo->capability.supportedDuplexModesCount;
+    QPrint::DuplexMode qtDuplexMode;
+
+    if(duplexModes){
+        m_duplexModes.reserve(duplexModesCount);
+        for (int i = 0; i < duplexModesCount; ++i) {
+            switch(*(duplexModes+i)){
+            case DUPLEX_MODE_ONE_SIDED:
+                qtDuplexMode = QPrint::DuplexNone;
+                break;
+            case DUPLEX_MODE_TWO_SIDED_LONG_EDGE:
+                qtDuplexMode = QPrint::DuplexLongSide;
+                break;
+            case DUPLEX_MODE_TWO_SIDED_SHORT_EDGE:
+                qtDuplexMode = QPrint::DuplexShortSide;
+                break;
+            default:
+                qtDuplexMode = QPrint::DuplexNone;
+                break;
+            }
+            if(!m_duplexModes.contains(qtDuplexMode)){
+                m_duplexModes.append(qtDuplexMode);
+            }
+        }
+    }
+
+    if (m_duplexModes.size() == 0) {
+        Print_DuplexMode defaultDuplexMode = m_printerInfo->defaultValue.defaultDuplexMode;
+        switch(defaultDuplexMode){
+        case DUPLEX_MODE_ONE_SIDED:
+            qtDuplexMode = QPrint::DuplexNone;
+            break;
+        case DUPLEX_MODE_TWO_SIDED_LONG_EDGE:
+            qtDuplexMode = QPrint::DuplexLongSide;
+            break;
+        case DUPLEX_MODE_TWO_SIDED_SHORT_EDGE:
+            qtDuplexMode = QPrint::DuplexShortSide;
+            break;
+        default:
+            qtDuplexMode = QPrint::DuplexNone;
+            break;
+        }
+        if(!m_duplexModes.contains(qtDuplexMode)){
+            m_duplexModes.append(qtDuplexMode);
+        }
+    }
+
+    // If still no result, or not added in PPD, then add None
+    if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone))
+        m_duplexModes.append(QPrint::DuplexNone);
+    // If have both modes, then can support DuplexAuto
+    if (m_duplexModes.contains(QPrint::DuplexLongSide) && m_duplexModes.contains(QPrint::DuplexShortSide))
+        m_duplexModes.append(QPrint::DuplexAuto);
+
+    m_haveDuplexModes = true;
+}
+
+QPrint::DuplexMode QOpenHarmonyPrintDevice::defaultDuplexMode() const
+{
+    QPrint::DuplexMode qtDuplexMode;
+    Print_DuplexMode defaultDuplexMode = m_printerInfo ? m_printerInfo->defaultValue.defaultDuplexMode : DUPLEX_MODE_ONE_SIDED;
+    switch(defaultDuplexMode){
+    case DUPLEX_MODE_ONE_SIDED:
+        qtDuplexMode = QPrint::DuplexNone;
+        break;
+    case DUPLEX_MODE_TWO_SIDED_LONG_EDGE:
+        qtDuplexMode = QPrint::DuplexLongSide;
+        break;
+    case DUPLEX_MODE_TWO_SIDED_SHORT_EDGE:
+        qtDuplexMode = QPrint::DuplexShortSide;
+        break;
+    default:
+        qtDuplexMode = QPrint::DuplexNone;
+        break;
+    }
+    return qtDuplexMode;
+}
+
+void QOpenHarmonyPrintDevice::loadColorModes() const
+{
+    if(!m_printerInfo)
+        return;
+
+    m_colorModes.clear();
+
+    Print_ColorMode *colorModes = m_printerInfo->capability.supportedColorModes;
+    uint colorModesCount = m_printerInfo->capability.supportedColorModesCount;
+    QPrint::ColorMode qtColorMode;
+
+    for (int i = 0; i < colorModesCount; ++i) {
+        switch(*(colorModes+i)){
+        case COLOR_MODE_MONOCHROME:
+            qtColorMode = QPrint::GrayScale;
+            break;
+        case COLOR_MODE_COLOR:
+            qtColorMode = QPrint::Color;
+            break;
+        case COLOR_MODE_AUTO:
+            qtColorMode = QPrint::Color;
+            break;
+        default:
+            qtColorMode = QPrint::GrayScale;
+            break;
+        }
+        if(!m_colorModes.contains(qtColorMode)){
+            m_colorModes.append(qtColorMode);
+        }
+    }
+
+    m_haveColorModes = true;
+}
+
+QPrint::ColorMode QOpenHarmonyPrintDevice::defaultColorMode() const
+{
+    // Not a proper option, usually only know if supports color or not, but some
+    // users known to abuse ColorModel to always force GrayScale.
+    if (supportedColorModes().contains(QPrint::Color)) {
+        QPrint::ColorMode qtColorMode = QPrint::GrayScale;
+
+        if(m_printerInfo && m_printerInfo->printerId != nullptr){
+            Print_ColorMode defaultColorMode = m_printerInfo->defaultValue.defaultColorMode;
+            switch(defaultColorMode){
+            case COLOR_MODE_MONOCHROME:
+                qtColorMode = QPrint::GrayScale;
+                break;
+            case COLOR_MODE_COLOR:
+                qtColorMode = QPrint::Color;
+                break;
+            case COLOR_MODE_AUTO:
+                qtColorMode = QPrint::Color;
+                break;
+            default:
+                qtColorMode = QPrint::GrayScale;
+                break;
+            }
+        }
+
+        if(QPrint::Color == qtColorMode)
+        {
+            return qtColorMode;
+        }
+    }
+
+    return QPrint::GrayScale;
+}
+
+QVariant QOpenHarmonyPrintDevice::property(QPrintDevice::PrintDevicePropertyKey key) const
+{
+    //todo:鸿蒙native没有这些接口
+    // if (key == PDPK_PpdFile)
+    //     return QVariant::fromValue<ppd_file_t *>(m_ppd);
+    // else if (key == PDPK_CupsJobPriority)
+    //     return printerOption(QStringLiteral("job-priority"));
+    // else if (key == PDPK_CupsJobSheets)
+    //     return printerOption(QStringLiteral("job-sheets"));
+    // else if (key == PDPK_CupsJobBilling)
+    //     return printerOption(QStringLiteral("job-billing"));
+    // else if (key == PDPK_CupsJobHoldUntil)
+    //     return printerOption(QStringLiteral("job-hold-until"));
+    if (key == PDPK_OHOSPrinterId) {
+        return m_PrinterId;
+    }
+
+    return QPlatformPrintDevice::property(key);
+}
+
+bool QOpenHarmonyPrintDevice::setProperty(QPrintDevice::PrintDevicePropertyKey key, const QVariant &value)
+{
+    //todo:鸿蒙native没有该接口
+    // if (key == PDPK_PpdOption) {
+    //     const QStringList values = value.toStringList();
+    //     if (values.count() == 2) {
+    //         ppdMarkOption(m_ppd, values[0].toLatin1(), values[1].toLatin1());
+    //         return true;
+    //     }
+    // }
+
+    return QPlatformPrintDevice::setProperty(key, value);
+}
+
+bool QOpenHarmonyPrintDevice::isFeatureAvailable(QPrintDevice::PrintDevicePropertyKey key, const QVariant &params) const
+{
+    //todo:鸿蒙native没有该接口
+    // if (key == PDPK_PpdChoiceIsInstallableConflict) {
+    //     const QStringList values = params.toStringList();
+    //     if (values.count() == 2)
+    //         return ppdInstallableConflict(m_ppd, values[0].toLatin1(), values[1].toLatin1());
+    // }
+
+    return QPlatformPrintDevice::isFeatureAvailable(key, params);
+}
+
+#if QT_CONFIG(mimetype)
+void QOpenHarmonyPrintDevice::loadMimeTypes() const
+{
+    QMimeDatabase db;
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("application/pdf")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("application/postscript")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/gif")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/png")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/jpeg")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/tiff")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("text/html")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("text/plain")));
+    m_haveMimeTypes = true;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/plugins/printsupport/openharmony/qopenharmonyprintdevice.h b/src/plugins/printsupport/openharmony/qopenharmonyprintdevice.h
new file mode 100644
index 00000000000..fb8758f1600
--- /dev/null
+++ b/src/plugins/printsupport/openharmony/qopenharmonyprintdevice.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOpenHarmonyPrintDevice_H
+#define QOpenHarmonyPrintDevice_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for the convenience
+// of internal files.  This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtPrintSupport/qprintengine.h"
+#include <qpa/qplatformprintdevice.h>
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qmargins.h>
+#include <BasicServicesKit/ohprint.h>
+
+QT_BEGIN_NAMESPACE
+
+struct oh_ppd_file_t;       //todo:仅占位,鸿蒙native接口没有该结构体。
+
+class QOpenHarmonyPrintDevice : public QPlatformPrintDevice
+{
+public:
+    explicit QOpenHarmonyPrintDevice(const QString &id);
+    virtual ~QOpenHarmonyPrintDevice();
+
+    bool isValid() const override;
+    bool isDefault() const override;
+
+    QPrint::DeviceState state() const override;
+
+    QPageSize defaultPageSize() const override;
+
+    QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation,
+                               int resolution) const override;
+
+    int defaultResolution() const override;
+
+    QPrint::InputSlot defaultInputSlot() const override;
+
+    QPrint::OutputBin defaultOutputBin() const override;
+
+    QPrint::DuplexMode defaultDuplexMode() const override;
+
+    QPrint::ColorMode defaultColorMode() const override;
+
+    QVariant property(QPrintDevice::PrintDevicePropertyKey key) const override;
+    bool setProperty(QPrintDevice::PrintDevicePropertyKey key, const QVariant &value) override;
+    bool isFeatureAvailable(QPrintDevice::PrintDevicePropertyKey key, const QVariant &params) const override;
+
+protected:
+    void loadPageSizes() const override;
+    void loadResolutions() const override;
+    void loadInputSlots() const override;
+    void loadOutputBins() const override;
+    void loadDuplexModes() const override;
+    void loadColorModes() const override;
+#if QT_CONFIG(mimetype)
+    void loadMimeTypes() const override;
+#endif
+
+private:
+    Print_PrinterInfo *m_printerInfo;
+    oh_ppd_file_t *m_ppd;
+    QByteArray m_PrinterId;
+    QMarginsF m_customMargins;
+    mutable QHash<QString, QMarginsF> m_printableMargins;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOpenHarmonyPrintDevice_H
diff --git a/src/plugins/printsupport/openharmony/qopenharmonyprintengine.cpp b/src/plugins/printsupport/openharmony/qopenharmonyprintengine.cpp
new file mode 100644
index 00000000000..6f25395ad57
--- /dev/null
+++ b/src/plugins/printsupport/openharmony/qopenharmonyprintengine.cpp
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <qfile.h>
+#include <qdebug.h>
+#include <qbuffer.h>
+#include <QFileInfo>
+#include <qiodevice.h>
+#include <QPrintDialog>
+#include <QStandardPaths>
+#include <QtGui/qpagelayout.h>
+
+#include <qpa/qplatformprintplugin.h>
+#include <BasicServicesKit/ohprint.h>
+#include <qpa/qplatformprintersupport.h>
+
+#include "private/qcore_unix_p.h" // overrides QT_OPEN
+#include "qopenharmonyprintengine_p.h"
+
+QT_BEGIN_NAMESPACE
+#define PDPK_OHOSPrinterId QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 100)
+extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits);
+
+QOpenHarmonyPrintEngine::QOpenHarmonyPrintEngine(QPrinter::PrinterMode m, const QString &deviceId)
+    : QPdfPrintEngine(*new QOpenHarmonyPrintEnginePrivate(m))
+{
+    Q_D(QOpenHarmonyPrintEngine);
+    d->changePrinter(deviceId);
+    state = QPrinter::Idle;
+}
+
+QOpenHarmonyPrintEngine::~QOpenHarmonyPrintEngine()
+{
+}
+
+void QOpenHarmonyPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value)
+{
+    Q_D(QOpenHarmonyPrintEngine);
+
+    switch (int(key)) {
+    case PPK_PageSize:
+        d->setPageSize(QPageSize(QPageSize::PageSizeId(value.toInt())));
+        break;
+    case PPK_WindowsPageSize:
+        d->setPageSize(QPageSize(QPageSize::id(value.toInt())));
+        break;
+    case PPK_CustomPaperSize:
+        d->setPageSize(QPageSize(value.toSizeF(), QPageSize::Point));
+        break;
+    case PPK_PaperName:
+        // Get the named page size from the printer if supported
+        d->setPageSize(d->m_printDevice.supportedPageSize(value.toString()));
+        break;
+    case PPK_Duplex: {
+        QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt());
+        if (d->m_printDevice.supportedDuplexModes().contains(mode)) {
+            d->duplex = mode;
+            d->duplexRequestedExplicitly = true;
+        }
+        break;
+    }
+    case PPK_Orientation: {
+        d->m_pageLayout.setOrientation(QPageLayout::Orientation(value.toInt()));
+        qWarning() << "set ppk orientation:" << d->m_pageLayout;
+    }
+    break;
+    case PPK_PrinterName:
+        d->changePrinter(value.toString());
+        break;
+    case PPK_OhPrintOptions:
+        d->ohOptions = value.toStringList();
+        break;
+    case PPK_QPageSize:
+        d->setPageSize(qvariant_cast<QPageSize>(value));
+        break;
+    case PPK_QPageLayout: {
+        QPageLayout pageLayout = qvariant_cast<QPageLayout>(value);
+        d->m_pageLayout = pageLayout;
+        qWarning() << "set ppk page layout:" << d->m_pageLayout;
+#if 0
+        if (pageLayout.isValid() && (d->m_printDevice.isValidPageLayout(pageLayout, d->resolution)
+                                     || d->m_printDevice.supportsCustomPageSizes()
+                                     || d->m_printDevice.supportedPageSizes().isEmpty())) {
+            // supportedPageSizes().isEmpty() because QPageSetupWidget::initPageSizes says
+            // "If no available printer page sizes, populate with all page sizes"
+            d->m_pageLayout = pageLayout;
+            d->setPageSize(pageLayout.pageSize());
+        }
+#endif
+        break;
+    }
+    default:
+        QPdfPrintEngine::setProperty(key, value);
+        break;
+    }
+}
+
+QVariant QOpenHarmonyPrintEngine::property(PrintEnginePropertyKey key) const
+{
+    Q_D(const QOpenHarmonyPrintEngine);
+
+    QVariant ret;
+    switch (int(key)) {
+    case PPK_SupportsMultipleCopies:
+        //不确定是否支持该属性,暂时认为不支持。
+        ret = false;
+        break;
+    case PPK_NumberOfCopies:
+        ret = 1;
+        break;
+    case PPK_OhPrintOptions:
+        ret = d->ohOptions;
+        break;
+    case PPK_Duplex:
+        ret = d->duplex;
+        break;
+    default:
+        ret = QPdfPrintEngine::property(key);
+        break;
+    }
+    return ret;
+}
+
+
+QOpenHarmonyPrintEnginePrivate::QOpenHarmonyPrintEnginePrivate(QPrinter::PrinterMode m)
+    : QPdfPrintEnginePrivate(m)
+    , duplex(QPrint::DuplexNone)
+    , printMode(m)
+{
+    outputFileName.clear();
+    ownsDevice = true; /* FIXME 是否让PDF基类控制文件内容落盘 */
+}
+
+QOpenHarmonyPrintEnginePrivate::~QOpenHarmonyPrintEnginePrivate()
+{
+}
+
+bool QOpenHarmonyPrintEnginePrivate::openPrintDevice()
+{
+    if (this->outDevice)
+        return false;
+
+    if (!outputFileName.isEmpty()) {
+        QFile *file = new QFile(outputFileName);
+        if (!file->open(QFile::WriteOnly|QFile::Truncate)) {
+            delete file;
+            return false;
+        }
+        this->outDevice = file;
+    } else {
+        QUuid uuid = QUuid::createUuid();
+        const QString &tempDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
+        ohTempFile = QString("%1/%2.pdf").arg(tempDir, uuid.toString(QUuid::Id128));
+        fd = open(ohTempFile.toLocal8Bit().constData(), O_CREAT | O_SYNC | O_WRONLY,
+                  S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP);
+        QFile *f = new QFile();
+        // if (!f->open(QIODevice::WriteOnly)) {
+        //     f->close();
+        //     qWarning() << "create print temp file failed:" << f->errorString();
+        //     return false;
+        // }
+        this->outDevice = f;
+        static_cast<QFile *>(outDevice)->open(fd, QIODevice::WriteOnly);
+        //this->fd = f->handle();
+        qWarning() << "open tmp file:" << ohTempFile <<  "fd:" << fd << outDevice;
+    }
+
+    return true;
+}
+
+void QOpenHarmonyPrintEnginePrivate::closePrintDevice()
+{
+    Q_Q(QOpenHarmonyPrintEngine);
+    if (!ohTempFile.isEmpty()) {
+        QString tempFile = ohTempFile;
+        ohTempFile.clear();
+
+        // Should never have got here without a printer, but check anyway
+        if (printerName.isEmpty()) {
+            qWarning("Could not determine printer to print to");
+            QFile::remove(tempFile);
+            return;
+        }
+
+        // Set up print options.
+        QList<QPair<QByteArray, QByteArray> > options;
+        QVector<Print_Property> ohPrintOptStruct;
+
+
+        options.append(QPair<QByteArray, QByteArray>("media", m_pageLayout.pageSize().key().toLocal8Bit()));
+
+        if (copies > 1)
+            options.append(QPair<QByteArray, QByteArray>("copies", QString::number(copies).toLocal8Bit()));
+
+        if (copies > 1 && collate)
+            options.append(QPair<QByteArray, QByteArray>("Collate", "True"));
+
+        switch (duplex) {
+        case QPrint::DuplexNone:
+            options.append(QPair<QByteArray, QByteArray>("sides", "one-sided"));
+            break;
+        case QPrint::DuplexAuto:
+            if (m_pageLayout.orientation() == QPageLayout::Portrait)
+                options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-long-edge"));
+            else
+                options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-short-edge"));
+            break;
+        case QPrint::DuplexLongSide:
+            options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-long-edge"));
+            break;
+        case QPrint::DuplexShortSide:
+            options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-short-edge"));
+            break;
+        }
+
+        if (m_pageLayout.orientation() == QPageLayout::Landscape)
+            options.append(QPair<QByteArray, QByteArray>("landscape", ""));
+
+        QStringList::const_iterator it = ohOptions.constBegin();
+        while (it != ohOptions.constEnd()) {
+            options.append(QPair<QByteArray, QByteArray>((*it).toLocal8Bit(), (*(it+1)).toLocal8Bit()));
+            it += 2;
+        }
+
+        const int numOptions = options.size();
+        ohPrintOptStruct.reserve(numOptions);
+        for (int c = 0; c < numOptions; ++c) {
+            Print_Property prop;
+            prop.key = options[c].first.data();
+            prop.value = options[c].second.data();
+            ohPrintOptStruct.append(prop);
+        }
+
+        Print_PrintJob printJob;
+        fd = open(tempFile.toLocal8Bit().constData(), O_RDONLY);
+
+        QString jobName = title.isEmpty() ? QUuid::createUuid().toString(QUuid::Id128) : title;
+        QByteArray jobNameArray = jobName.toUtf8();
+        printJob.jobName = jobNameArray.data();
+        uint32_t fds[1] = { static_cast<uint32_t>(fd) };
+        printJob.fdList = fds;
+        printJob.fdList[0] = fd;
+        printJob.fdListCount = 1;
+
+        QByteArray printerId = printerName.toUtf8();
+        printJob.printerId = printerId.data();
+        printJob.copyNumber = copies;
+        // printJob.paperSource = q->property(PPK_PaperSources);
+        std::string paperSource = "auto";
+        printJob.paperSource = paperSource.data();
+        std::string mediaType = "stationery";
+        printJob.mediaType = mediaType.data();
+        QString key = m_pageLayout.pageSize().key();
+        QByteArray keyArray = key.toUtf8();
+        printJob.pageSizeId = keyArray.data();
+        //printJob.pageSizeId = "ISO_A4";
+        //Print_ColorMode
+        Print_ColorMode ohColorMode;
+        QPrinter::ColorMode qtColorMode = (QPrinter::ColorMode)q->property(QPrintEngine::PPK_ColorMode).toInt();
+        switch(qtColorMode){
+        case QPrinter::GrayScale:
+            ohColorMode = COLOR_MODE_MONOCHROME;
+            break;
+        case QPrinter::Color:
+            ohColorMode = COLOR_MODE_COLOR;
+            break;
+        default:
+            ohColorMode = COLOR_MODE_MONOCHROME;
+            break;
+        }
+        printJob.colorMode = ohColorMode;
+
+
+        //Print_DuplexMode
+        Print_DuplexMode ohDuplexMode;
+        QPrint::DuplexMode qtDuplexMode = (QPrint::DuplexMode)q->property(QPrintEngine::PPK_Duplex).toInt();
+        switch(qtDuplexMode){
+        case QPrint::DuplexNone:
+            ohDuplexMode = DUPLEX_MODE_ONE_SIDED;
+            break;
+        case QPrint::DuplexAuto:
+            //自动模式暂时设置为One sided。
+            ohDuplexMode = DUPLEX_MODE_ONE_SIDED;
+            break;
+        case QPrint::DuplexLongSide:
+            ohDuplexMode = DUPLEX_MODE_TWO_SIDED_LONG_EDGE;
+            break;
+        case QPrint::DuplexShortSide:
+            ohDuplexMode = DUPLEX_MODE_TWO_SIDED_SHORT_EDGE;
+            break;
+        default:
+            ohDuplexMode = DUPLEX_MODE_ONE_SIDED;
+            break;
+        }
+        printJob.duplexMode = ohDuplexMode;
+
+        //Print_Resolution
+        int resolution = 600/*q->property(QPrintEngine::PPK_Resolution).toInt()*/;
+        printJob.resolution.horizontalDpi = resolution;
+        printJob.resolution.verticalDpi = resolution;
+
+        //Print_Margin
+        Print_Margin ohPrintMargin;
+        QPair<QMarginsF, QPageLayout::Unit> pair = qvariant_cast<QPair<QMarginsF, QPageLayout::Unit> >(q->property(QPrintEngine::PPK_QPageMargins));
+        ohPrintMargin.leftMargin = static_cast<uint>(pair.first.left());
+        ohPrintMargin.topMargin = static_cast<uint>(pair.first.top());
+        ohPrintMargin.rightMargin = static_cast<uint>(pair.first.right());
+        ohPrintMargin.bottomMargin = static_cast<uint>(pair.first.bottom());
+        printJob.printMargin = ohPrintMargin;
+        /* 默认无border */
+        printJob.borderless = false;
+
+        //Print_OrientationMode
+        Print_OrientationMode ohOrientationMode;
+        // int ohOrientationMode;
+        QPageLayout::Orientation qtOrientation = m_pageLayout.orientation();
+        switch(qtOrientation){
+        case QPageLayout::Portrait:
+            ohOrientationMode = ORIENTATION_MODE_PORTRAIT;
+            break;
+        case QPageLayout::Landscape:
+            ohOrientationMode = ORIENTATION_MODE_LANDSCAPE;
+            break;
+        default:
+            ohOrientationMode = ORIENTATION_MODE_PORTRAIT;
+            break;
+        }
+        printJob.orientationMode = ohOrientationMode;
+
+        //Print_Quality
+        Print_Quality ohQuality;
+        switch(printMode){
+        case QPrinter::ScreenResolution:
+            ohQuality = PRINT_QUALITY_DRAFT;
+            break;
+        case QPrinter::PrinterResolution:
+            ohQuality = PRINT_QUALITY_NORMAL;
+            break;
+        case QPrinter::HighResolution:
+            ohQuality = PRINT_QUALITY_HIGH;
+            break;
+        default:
+            ohQuality = PRINT_QUALITY_HIGH;
+            break;
+        }
+        printJob.printQuality = ohQuality;
+
+
+        //Print_DocumentFormat
+        Print_DocumentFormat ohDocumentFormat;
+        QFileInfo fi(outputFileName);
+        if (!fi.suffix().compare(QLatin1String("pdf"), Qt::CaseInsensitive))
+            ohDocumentFormat = DOCUMENT_FORMAT_PDF;
+        else if (!fi.suffix().compare(QLatin1String("jpeg"), Qt::CaseInsensitive) ||
+                 !fi.suffix().compare(QLatin1String("jpg"), Qt::CaseInsensitive))
+            ohDocumentFormat = DOCUMENT_FORMAT_JPEG;
+        else if (!fi.suffix().compare(QLatin1String("ps"), Qt::CaseInsensitive))
+            ohDocumentFormat = DOCUMENT_FORMAT_POSTSCRIPT;
+        else if (!fi.suffix().compare(QLatin1String("txt"), Qt::CaseInsensitive))
+            ohDocumentFormat = DOCUMENT_FORMAT_TEXT;
+        else{
+            ohDocumentFormat = DOCUMENT_FORMAT_AUTO;
+        }
+        /* FIXME 暂时支持PDF格式 */
+        printJob.documentFormat = DOCUMENT_FORMAT_PDF;
+        printJob.advancedOptions = nullptr;
+
+        qWarning() << "start print job page layout" << this->m_pageLayout;
+        /* 启动打印任务 */
+        int ret = OH_Print_StartPrintJob(&printJob);        
+        if(PRINT_ERROR_NONE != ret){
+            qWarning() << "print job execute fail,errCode:" << ret;
+        }
+
+        //QPdfPrintEnginePrivate::closePrintDevice();
+    }
+}
+
+void QOpenHarmonyPrintEnginePrivate::changePrinter(const QString &newPrinter)
+{
+    // Don't waste time if same printer name
+    if (newPrinter == printerName)
+        return;
+
+    // Should never have reached here if no plugin available, but check just in case
+    QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
+    if (!ps)
+        return;
+
+    // Try create the printer, only use it if it returns valid
+    QPrintDevice printDevice = ps->createPrintDevice(newPrinter);
+    if (!printDevice.isValid())
+        return;
+    m_printDevice.swap(printDevice);
+    printerName = m_printDevice.property(PDPK_OHOSPrinterId).toString();
+
+    // in case a duplex value was explicitly set, check if new printer supports current value,
+    // otherwise use device default
+    if (!duplexRequestedExplicitly || !m_printDevice.supportedDuplexModes().contains(duplex)) {
+        duplex = m_printDevice.defaultDuplexMode();
+        duplexRequestedExplicitly = false;
+    }
+    QPrint::ColorMode colorMode = grayscale ? QPrint::GrayScale : QPrint::Color;
+    if (!m_printDevice.supportedColorModes().contains(colorMode))
+        grayscale = m_printDevice.defaultColorMode() == QPrint::GrayScale;
+
+    // Get the equivalent page size for this printer as supported names may be different
+    if (m_printDevice.supportedPageSize(m_pageLayout.pageSize()).isValid()) {
+        setPageSize(m_pageLayout.pageSize());
+    }
+    else {
+        setPageSize(QPageSize(m_pageLayout.pageSize().size(QPageSize::Point), QPageSize::Point));
+    }
+}
+
+void QOpenHarmonyPrintEnginePrivate::setPageSize(const QPageSize &pageSize)
+{
+    if (pageSize.isValid()) {
+        // Find if the requested page size has a matching printer page size, if so use its defined name instead
+        QPageSize printerPageSize = m_printDevice.supportedPageSize(pageSize);
+        QPageSize usePageSize = printerPageSize.isValid() ? printerPageSize : pageSize;
+        QMarginsF printable = m_printDevice.printableMargins(usePageSize, m_pageLayout.orientation(), resolution);
+        m_pageLayout.setPageSize(usePageSize, qt_convertMargins(printable, QPageLayout::Point, m_pageLayout.units()));
+    }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/printsupport/openharmony/qopenharmonyprintengine_p.h b/src/plugins/printsupport/openharmony/qopenharmonyprintengine_p.h
new file mode 100644
index 00000000000..7fb7894975f
--- /dev/null
+++ b/src/plugins/printsupport/openharmony/qopenharmonyprintengine_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENHARMONYPRINTENGINE_P_H
+#define QOPENHARMONYPRINTENGINE_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtPrintSupport/qprintengine.h"
+
+#include <QtCore/qstring.h>
+#include <QtGui/qpaintengine.h>
+
+#include <private/qpaintengine_p.h>
+#include <private/qprintdevice_p.h>
+#include <private/qprintengine_pdf_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#define PPK_OhPrintOptions QPrintEngine::PrintEnginePropertyKey(0xef55)
+
+class QOpenHarmonyPrintEnginePrivate;
+
+class QOpenHarmonyPrintEngine : public QPdfPrintEngine
+{
+    Q_DECLARE_PRIVATE(QOpenHarmonyPrintEngine)
+public:
+    QOpenHarmonyPrintEngine(QPrinter::PrinterMode m, const QString &deviceId);
+    virtual ~QOpenHarmonyPrintEngine();
+
+    // reimplementations QPdfPrintEngine
+    void setProperty(PrintEnginePropertyKey key, const QVariant &value) override;
+    QVariant property(PrintEnginePropertyKey key) const override;
+    // end reimplementations QPdfPrintEngine
+
+private:
+    Q_DISABLE_COPY_MOVE(QOpenHarmonyPrintEngine)
+};
+
+class QOpenHarmonyPrintEnginePrivate : public QPdfPrintEnginePrivate
+{
+    Q_DECLARE_PUBLIC(QOpenHarmonyPrintEngine)
+public:
+    QOpenHarmonyPrintEnginePrivate(QPrinter::PrinterMode m);
+    ~QOpenHarmonyPrintEnginePrivate();
+
+    bool openPrintDevice() override;
+    void closePrintDevice() override;
+
+private:
+    Q_DISABLE_COPY_MOVE(QOpenHarmonyPrintEnginePrivate)
+
+    void changePrinter(const QString &newPrinter);
+    void setPageSize(const QPageSize &pageSize);
+
+    QPrintDevice m_printDevice;
+    QStringList ohOptions;
+    QString ohTempFile;
+    QPrint::DuplexMode duplex;
+    bool duplexRequestedExplicitly = false;
+    QPrinter::PrinterMode printMode;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOPENHARMONYPRINTENGINE_P_H
diff --git a/src/plugins/printsupport/openharmony/qopenharmonyprintersupport.cpp b/src/plugins/printsupport/openharmony/qopenharmonyprintersupport.cpp
new file mode 100644
index 00000000000..62ff7ac26eb
--- /dev/null
+++ b/src/plugins/printsupport/openharmony/qopenharmonyprintersupport.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopenharmonyprintersupport_p.h"
+
+#include "qopenharmonyprintengine_p.h"
+#include "qopenharmonyprintdevice.h"
+#include <private/qprinterinfo_p.h>
+#include <private/qprintdevice_p.h>
+#include <QtPrintSupport/QPrinterInfo>
+
+#if QT_CONFIG(dialogbuttonbox)
+#include <QGuiApplication>
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QFormLayout>
+#include <QLabel>
+#include <QLineEdit>
+#endif // QT_CONFIG(dialogbuttonbox)
+
+QT_BEGIN_NAMESPACE
+#if 0
+#if QT_CONFIG(dialogbuttonbox)
+static const char *getPasswordCB(const char */*prompt*/, http_t *http, const char */*method*/, const char *resource, void */*user_data*/)
+{
+    // cups doesn't free the const char * we return so keep around
+    // the last password so we don't leak memory if called multiple times.
+    static QByteArray password;
+
+    // prompt is always "Password for %s on %s? " but we can't use it since we allow the user to change the user.
+    // That is fine because cups always calls cupsUser after calling this callback.
+    // We build our own prompt with the hostname (if not localhost) and the resource that is being used
+
+    char hostname[HTTP_MAX_HOST];
+    httpGetHostname(http, hostname, HTTP_MAX_HOST);
+
+    const QString username = QString::fromLocal8Bit(cupsUser());
+
+    QDialog dialog;
+    dialog.setWindowTitle(QCoreApplication::translate("QOpenHarmonyPrinterSupport", "Authentication Needed"));
+
+    QFormLayout *layout = new QFormLayout(&dialog);
+    layout->setSizeConstraint(QLayout::SetFixedSize);
+
+    QLineEdit *usernameLE = new QLineEdit();
+    usernameLE->setText(username);
+
+    QLineEdit *passwordLE = new QLineEdit();
+    passwordLE->setEchoMode(QLineEdit::Password);
+
+    QString resourceString = QString::fromLocal8Bit(resource);
+    if (resourceString.startsWith(QStringLiteral("/printers/")))
+        resourceString = resourceString.mid(QStringLiteral("/printers/").length());
+
+    QLabel *label = new QLabel();
+    if (hostname == QStringLiteral("localhost")) {
+        label->setText(QCoreApplication::translate("QOpenHarmonyPrinterSupport", "Authentication needed to use %1.").arg(resourceString));
+    } else {
+        label->setText(QCoreApplication::translate("QOpenHarmonyPrinterSupport", "Authentication needed to use %1 on %2.").arg(resourceString).arg(hostname));
+        label->setWordWrap(true);
+    }
+
+    layout->addRow(label);
+    layout->addRow(new QLabel(QCoreApplication::translate("QOpenHarmonyPrinterSupport", "Username:")), usernameLE);
+    layout->addRow(new QLabel(QCoreApplication::translate("QOpenHarmonyPrinterSupport", "Password:")), passwordLE);
+
+    QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+    layout->addRow(buttonBox);
+
+    QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
+    QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
+
+    passwordLE->setFocus();
+
+    if (dialog.exec() != QDialog::Accepted)
+        return nullptr;
+
+    if (usernameLE->text() != username)
+        cupsSetUser(usernameLE->text().toLocal8Bit().constData());
+
+    password = passwordLE->text().toLocal8Bit();
+
+    return password.constData();
+}
+#endif // QT_CONFIG(dialogbuttonbox)
+#endif
+
+static QOpenHarmonyPrinterSupport *ps = nullptr;
+
+QOpenHarmonyPrinterSupport::QOpenHarmonyPrinterSupport()
+    : QPlatformPrinterSupport()
+{
+    ps = this;
+    Print_ErrorCode ret = Print_ErrorCode::PRINT_ERROR_NONE;
+
+    ret = OH_Print_Init();
+    if(PRINT_ERROR_NONE != ret){
+        qWarning() << "QOpenHarmonyPrinterSupport:init Env failed,errCode:" << ret;
+        return;
+    }
+    qInfo() << "QOpenHarmonyPrinterSupport:init Env ok";
+
+    ret = OH_Print_RegisterPrinterChangeListener(Print_PrinterChange);
+    if(PRINT_ERROR_NONE != ret){
+        qWarning() << "QOpenHarmonyPrinterSupport:register printer change failed,errCode:" << ret;
+        return;
+    }
+    qInfo() << "QOpenHarmonyPrinterSupport:register printer change ok";
+
+    ret = OH_Print_StartPrinterDiscovery(Print_PrinterDiscovery);
+    if (PRINT_ERROR_NONE != ret)
+    {
+        qWarning() << "QOpenHarmonyPrinterSupport:StartPrinterDiscovery failed,errCode:" << ret;
+        OH_Print_UnregisterPrinterChangeListener();
+        OH_Print_Release();
+        return;
+    }
+    qInfo() << "QOpenHarmonyPrinterSupport:StartPrinterDiscovery ok";
+
+    detectOHPrinter();
+}
+
+QOpenHarmonyPrinterSupport::~QOpenHarmonyPrinterSupport()
+{
+    OH_Print_StopPrinterDiscovery();
+    OH_Print_UnregisterPrinterChangeListener();
+    OH_Print_Release();
+    ps = nullptr;
+}
+
+QPrintEngine *QOpenHarmonyPrinterSupport::createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId)
+{
+    return new QOpenHarmonyPrintEngine(printerMode, (deviceId.isEmpty() ? defaultPrintDeviceId() : deviceId));
+}
+
+QPaintEngine *QOpenHarmonyPrinterSupport::createPaintEngine(QPrintEngine *engine, QPrinter::PrinterMode printerMode)
+{
+    Q_UNUSED(printerMode)
+    return static_cast<QOpenHarmonyPrintEngine *>(engine);
+}
+
+QPrintDevice QOpenHarmonyPrinterSupport::createPrintDevice(const QString &id)
+{
+    return QPlatformPrinterSupport::createPrintDevice(new QOpenHarmonyPrintDevice(idFromName(id)));
+}
+
+void QOpenHarmonyPrinterSupport::Print_PrinterChange(Print_PrinterEvent event, const Print_PrinterInfo *printerInfo)
+{
+    qInfo() << "Print_PrinterChange id:" << printerInfo->printerId << " name: " <<  printerInfo->printerName;
+
+#if 0
+    QString id = QString::fromLocal8Bit(printerInfo->printerId);
+    if (!ps)
+        return;
+    OHPrinter p;
+    p.id = id;
+    p.name = QString::fromLocal8Bit(printerInfo->printerName);
+    p.isDefault = printerInfo->isDefaultPrinter;
+
+    if(PRINTER_ADDED == event){
+        ps->add(p);
+    }else if(PRINTER_DELETED == event){
+        ps->deletePrinter(p);
+    }
+#endif
+}
+
+void QOpenHarmonyPrinterSupport::Print_PrinterDiscovery(Print_DiscoveryEvent event, const Print_PrinterInfo *printerInfo)
+{
+    qInfo() << "PrinterDiscovery id:" << printerInfo->printerId << " name: " <<  printerInfo->printerName;
+    QString id = QString::fromUtf8(printerInfo->printerId);
+    if (event == PRINTER_DISCOVERED) {
+        if (!ps || ps->contains(id))
+            return;
+        OHPrinter p;
+        p.id = id;
+        p.name = QString::fromUtf8(printerInfo->printerName);
+        p.isDefault = printerInfo->isDefaultPrinter;
+        ps->add(p);
+    } else if (event == PRINTER_LOST) {
+        if (ps != nullptr)
+            ps->remove(id);
+    }
+}
+
+void QOpenHarmonyPrinterSupport::detectOHPrinter()
+{
+    Print_StringList printerIdList;
+    int ret = OH_Print_QueryPrinterList(&printerIdList);
+
+    if (PRINT_ERROR_NONE != ret) {
+        qWarning() << "QOpenHarmonyPrinterSupport:detectOHPrinter OH_Print_QueryPrinterList failed,errCode:" << ret;
+        return;
+    }
+    for (int i = 0; i < printerIdList.count; ++i) {
+        char *id = printerIdList.list[i];
+        QString idString = QString::fromUtf8(id);
+        if (contains(idString)) {
+            continue;
+        }
+        Print_PrinterInfo *info = nullptr;
+        ret = OH_Print_QueryPrinterInfo(id, &info);
+        if (PRINT_ERROR_NONE != ret || info == nullptr) {
+            qWarning() << "QOpenHarmonyPrinterSupport:detectOHPrinter OH_Print_QueryPrinterInfo failed,errCode:" << ret;
+            continue;
+        }
+        OHPrinter p;
+        p.id = idString;
+        p.name = QString::fromUtf8(info->printerName);
+        p.isDefault = info->isDefaultPrinter;
+        OH_Print_ReleasePrinterInfo(info);
+        m_printers << p;
+    }
+    OH_Print_ReleasePrinterList(&printerIdList);
+}
+
+bool QOpenHarmonyPrinterSupport::contains(const QString &id)
+{
+    for (int i = 0; i < m_printers.count(); ++i) {
+        if (m_printers.at(i).id == id)
+            return true;
+    }
+    return false;
+}
+
+QStringList QOpenHarmonyPrinterSupport::availablePrintDeviceIds() const
+{
+    QStringList result;
+    for (int i = 0; i < m_printers.count(); ++i) {
+        result << m_printers.at(i).name;
+    }
+    return result;
+}
+
+QString QOpenHarmonyPrinterSupport::defaultPrintDeviceId() const
+{
+    for (int i = 0; i < m_printers.count(); ++i) {
+        if (m_printers.at(i).isDefault)
+            return m_printers.at(i).name;
+    }
+    return QString();
+}
+
+void QOpenHarmonyPrinterSupport::add(const OHPrinter &p)
+{
+    m_printers << p;
+}
+
+void QOpenHarmonyPrinterSupport::remove(const QString &id)
+{
+    for (int i = 0; i < m_printers.count(); ++i) {
+        if (m_printers.at(i).id == id) {
+            m_printers.removeAt(i);
+            break;
+        }
+    }
+}
+
+void QOpenHarmonyPrinterSupport::deletePrinter(const OHPrinter &p)
+{
+    auto erased = std::remove_if(m_printers.begin(), m_printers.end(), [p](const OHPrinter& printer){
+        return printer.id == p.id;
+    });
+
+    m_printers.erase(erased, m_printers.end());
+}
+
+QString QOpenHarmonyPrinterSupport::defaultPrinterId() const
+{
+    for (int i = 0; i < m_printers.count(); ++i) {
+        if (m_printers.at(i).isDefault)
+            return m_printers.at(i).id;
+    }
+    return QString();
+}
+
+QString QOpenHarmonyPrinterSupport::idFromName(const QString &name)
+{
+    for (int i = 0; i < m_printers.count(); ++i) {
+        if (m_printers.at(i).name == name)
+            return m_printers.at(i).id;
+    }
+    return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/printsupport/openharmony/qopenharmonyprintersupport_p.h b/src/plugins/printsupport/openharmony/qopenharmonyprintersupport_p.h
new file mode 100644
index 00000000000..f94541ce1ca
--- /dev/null
+++ b/src/plugins/printsupport/openharmony/qopenharmonyprintersupport_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENHARMONYSPRINTERSUPPORT_H
+#define QOPENHARMONYSPRINTERSUPPORT_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qpa/qplatformprintersupport.h>
+
+#include <QtCore/qstringlist.h>
+#include <BasicServicesKit/ohprint.h>
+
+QT_BEGIN_NAMESPACE
+
+struct OHPrinter
+{
+    QString name;
+    QString id;
+    bool isDefault;
+};
+
+class QOpenHarmonyPrinterSupport : public QPlatformPrinterSupport
+{
+public:
+    QOpenHarmonyPrinterSupport();
+    ~QOpenHarmonyPrinterSupport();
+
+    QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) override;
+    QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode) override;
+
+    QPrintDevice createPrintDevice(const QString &id) override;
+    QStringList availablePrintDeviceIds() const override;
+    QString defaultPrintDeviceId() const override;
+    void add(const OHPrinter &p);
+    void remove(const QString &id);
+    void deletePrinter(const OHPrinter &p);
+private:
+    QString defaultPrinterId() const;
+    QString idFromName(const QString &name);
+    void detectOHPrinter();
+    bool contains(const QString &id);
+    QString cupsOption(int i, const QString &key) const;
+
+    static void Print_PrinterChange(Print_PrinterEvent event, const Print_PrinterInfo *printerInfo);
+    static void Print_PrinterDiscovery(Print_DiscoveryEvent event, const Print_PrinterInfo *printerInfo);
+    QList<OHPrinter> m_printers;
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QOPENHARMONYSPRINTERSUPPORT_H
diff --git a/src/printsupport/CMakeLists.txt b/src/printsupport/CMakeLists.txt
index 1ff5fd552f9..c3793e4af37 100644
--- a/src/printsupport/CMakeLists.txt
+++ b/src/printsupport/CMakeLists.txt
@@ -77,6 +77,20 @@ qt_internal_extend_target(PrintSupport CONDITION WIN32
         platform/windows/qwindowsprintersupport.cpp
 )
 
+qt_internal_extend_target(PrintSupport CONDITION OHOS
+    SOURCES
+        platform/openharmony/main.cpp 
+        platform/openharmony/qopenharmonyprintdevice.cpp  platform/openharmony/qopenharmonyprintdevice.h 
+        platform/openharmony/qopenharmonyprintengine.cpp platform/openharmony/qopenharmonyprintengine_p.h 
+        platform/openharmony/qopenharmonyprintersupport.cpp platform/openharmony/qopenharmonyprintersupport_p.h
+    LIBRARIES
+        ohprint
+        ohfileuri 
+        ace_ndk.z
+        rawfile.z
+        ace_napi.z
+)
+
 qt_internal_extend_target(PrintSupport CONDITION QT_FEATURE_printpreviewwidget
     SOURCES
         kernel/qpaintengine_preview.cpp kernel/qpaintengine_preview_p.h
diff --git a/src/printsupport/kernel/qprintengine_pdf_p.h b/src/printsupport/kernel/qprintengine_pdf_p.h
index ccef8215e19..69e0c20f0a3 100644
--- a/src/printsupport/kernel/qprintengine_pdf_p.h
+++ b/src/printsupport/kernel/qprintengine_pdf_p.h
@@ -87,6 +87,10 @@ private:
 
     friend class QCupsPrintEngine;
     friend class QCupsPrintEnginePrivate;
+#ifdef Q_OS_OPENHARMONY
+    friend class QOpenHarmonyPrintEngine;
+    friend class QOpenHarmonyPrintEnginePrivate;
+#endif
 
     QString printerName;
     QString printProgram;
diff --git a/src/printsupport/platform/openharmony/main.cpp b/src/printsupport/platform/openharmony/main.cpp
new file mode 100644
index 00000000000..1d0597b7314
--- /dev/null
+++ b/src/printsupport/platform/openharmony/main.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qopenharmonyprintersupport_p.h"
+
+#include <qpa/qplatformprintplugin.h>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class QOhPrinterSupportPlugin : public QPlatformPrinterSupportPlugin
+{
+    Q_OBJECT
+    Q_PLUGIN_METADATA(IID QPlatformPrinterSupportFactoryInterface_iid FILE "openharmonyprint.json")
+
+public:
+    QStringList keys() const;
+    QPlatformPrinterSupport *create(const QString &) override;
+};
+
+QStringList QOhPrinterSupportPlugin::keys() const
+{
+    return QStringList(QStringLiteral("openharmonyprintersupport"));
+}
+
+QPlatformPrinterSupport *QOhPrinterSupportPlugin::create(const QString &key)
+{
+    if (key.compare(key, QLatin1String("openharmonyprintersupport"), Qt::CaseInsensitive) == 0)
+        return new QOpenHarmonyPrinterSupport;
+    return 0;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/printsupport/platform/openharmony/openharmony.pro b/src/printsupport/platform/openharmony/openharmony.pro
new file mode 100644
index 00000000000..bc12956139c
--- /dev/null
+++ b/src/printsupport/platform/openharmony/openharmony.pro
@@ -0,0 +1,22 @@
+TARGET = openharmonyprintersupport
+MODULE = openharmonyprintersupport
+
+QT += core-private gui-private printsupport printsupport-private
+LIBS += -lohprint -lace_napi.z -lohfileuri -lace_ndk.z -lrawfile.z
+
+INCLUDEPATH += ../../../printsupport/kernel
+
+SOURCES += main.cpp \
+    qopenharmonyprintdevice.cpp \
+    qopenharmonyprintersupport.cpp \
+    qopenharmonyprintengine.cpp
+
+HEADERS += qopenharmonyprintersupport_p.h \
+    qopenharmonyprintdevice.h \
+    qopenharmonyprintengine_p.h
+
+OTHER_FILES += openharmonyprint.json
+
+PLUGIN_TYPE = printsupport
+PLUGIN_CLASS_NAME = QOpenHarmonyPrinterSupportPlugin
+load(qt_plugin)
diff --git a/src/printsupport/platform/openharmony/openharmonyprint.json b/src/printsupport/platform/openharmony/openharmonyprint.json
new file mode 100644
index 00000000000..f9a1786cf7d
--- /dev/null
+++ b/src/printsupport/platform/openharmony/openharmonyprint.json
@@ -0,0 +1,3 @@
+{
+    "Keys": [ "openharmonyprintersupport" ]
+}
diff --git a/src/printsupport/platform/openharmony/qopenharmonyprintdevice.cpp b/src/printsupport/platform/openharmony/qopenharmonyprintdevice.cpp
new file mode 100644
index 00000000000..01e318936ff
--- /dev/null
+++ b/src/printsupport/platform/openharmony/qopenharmonyprintdevice.cpp
@@ -0,0 +1,535 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopenharmonyprintdevice.h"
+
+#include "qopenharmonyprintersupport_p.h"
+
+#include <QDebug>
+
+#if QT_CONFIG(mimetype)
+#include <QtCore/QMimeDatabase>
+#endif
+
+QT_BEGIN_NAMESPACE
+#define PDPK_OHOSPrinterId QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 100)
+QOpenHarmonyPrintDevice::QOpenHarmonyPrintDevice(const QString &id)
+    : QPlatformPrintDevice(id),
+      m_printerInfo(new Print_PrinterInfo),
+      m_ppd(0)
+{
+    if (!id.isEmpty()) {
+        m_PrinterId = id.toUtf8();
+        // Get the print instance and PPD file
+        //鸿蒙native接口中没有ppd相关接口。
+        int ret = OH_Print_QueryPrinterInfo(m_PrinterId.constData(), &m_printerInfo);
+        if(PRINT_ERROR_NONE == ret){
+//            m_id = m_printerInfo->printerId;
+            m_id = m_printerInfo->printerName;
+            m_name = m_printerInfo->printerName;
+            m_location = m_printerInfo->location;
+            m_makeAndModel = m_printerInfo->makeAndModel;
+            //鸿蒙native接口中没有下面几个信息,暂定为false。
+            m_isRemote = false;
+            m_supportsMultipleCopies = false;
+            m_supportsCollateCopies = false;
+            m_supportsCustomPageSizes = false;
+        }
+        else{
+            qWarning() << "QOpenHarmonyPrintDevice:query printer info fail,errCode:" << ret;
+            m_printerInfo = nullptr;
+        }
+    }else{
+        m_printerInfo = nullptr;
+        qWarning() << "QOpenHarmonyPrintDevice:device id is empty";
+    }
+}
+
+QOpenHarmonyPrintDevice::~QOpenHarmonyPrintDevice()
+{
+    if (m_ppd)
+        //鸿蒙native接口中没有ppd相关接口。
+        //ppdClose(m_ppd);
+    if (m_printerInfo)
+        OH_Print_ReleasePrinterInfo(m_printerInfo);
+    m_printerInfo = 0;
+    m_ppd = 0;
+}
+
+bool QOpenHarmonyPrintDevice::isValid() const
+{
+    return m_printerInfo;
+}
+
+bool QOpenHarmonyPrintDevice::isDefault() const
+{
+    return m_printerInfo->isDefaultPrinter;
+}
+
+QPrint::DeviceState QOpenHarmonyPrintDevice::state() const
+{
+    Print_PrinterState state = m_printerInfo ? m_printerInfo->printerState : PRINTER_UNAVAILABLE;
+    if (PRINTER_IDLE == state)
+        return QPrint::Idle;
+    else if (PRINTER_BUSY == state)
+        /* TODO 待确定PRINTER_BUSY对应Active还是Aborted */
+        return QPrint::Active;
+    else if (PRINTER_UNAVAILABLE == state)
+        return QPrint::Error;
+    else
+        return QPrint::Error;
+}
+
+extern qreal qt_pointMultiplier(QPageLayout::Unit unit);
+void QOpenHarmonyPrintDevice::loadPageSizes() const
+{
+    if(!m_printerInfo)
+        return;
+
+    m_pageSizes.clear();
+    m_printableMargins.clear();
+
+    Print_PrinterCapability printerCapability = m_printerInfo->capability;
+    Print_Margin defaultMargin = m_printerInfo->defaultValue.defaultMargin;
+    uint32_t pageSizesCount = printerCapability.supportedPageSizesCount;
+    Print_PageSize *pageSize = printerCapability.supportedPageSizes;
+    static auto conver = [](uint32_t value)->int {
+        const double factor = 25.4 * qt_pointMultiplier(QPageLayout::Millimeter) / 1000.0;
+        return qRound(value * factor);
+    };
+    for(uint32_t i = 0; i < pageSizesCount; ++i){
+        QString key = pageSize[i].id;
+        QSize size = QSize(conver(pageSize[i].width), conver(pageSize[i].height));
+        QString name = QString::fromLocal8Bit(pageSize[i].name);
+        if (!size.isEmpty()) {
+            QPageSize ps = createPageSize(key, size, name);
+            qWarning() << "create page size:" << ps << "original size:" << QSize(pageSize[i].width, pageSize[i].height);
+            if (ps.isValid()) {
+                m_pageSizes.append(ps);
+                m_printableMargins.insert(key, QMarginsF(defaultMargin.leftMargin, defaultMargin.topMargin,
+                                                         defaultMargin.rightMargin, defaultMargin.bottomMargin));
+            }
+        }
+    }
+
+    m_havePageSizes = true;
+}
+
+QPageSize QOpenHarmonyPrintDevice::defaultPageSize() const
+{
+    if(!m_printerInfo)
+        return QPageSize();
+
+    Print_DefaultValue defaultVal = m_printerInfo->defaultValue;
+    QString key = QString::fromLocal8Bit(defaultVal.defaultPageSizeId);
+    auto it = std::find_if(m_pageSizes.constBegin(), m_pageSizes.constEnd(),[&key](const QPageSize &page){
+        return key == page.key();
+    });
+
+    return it == m_pageSizes.constEnd() ? QPageSize() : *it;
+}
+
+QMarginsF QOpenHarmonyPrintDevice::printableMargins(const QPageSize &pageSize,
+                                            QPageLayout::Orientation orientation,
+                                            int resolution) const
+{
+    Q_UNUSED(orientation)
+    Q_UNUSED(resolution)
+    if (!m_havePageSizes)
+        loadPageSizes();
+    // TODO Orientation?
+    if (m_printableMargins.contains(pageSize.key()))
+        return m_printableMargins.value(pageSize.key());
+    return m_customMargins;
+}
+
+void QOpenHarmonyPrintDevice::loadResolutions() const
+{
+    if(!m_printerInfo)
+        return;
+
+    m_resolutions.clear();
+
+    Print_Resolution *resolution = m_printerInfo->capability.supportedResolutions;
+    uint resolutionCount = m_printerInfo->capability.supportedResolutionsCount;
+
+    //Try load printer supportedResolutions
+    if(resolutionCount > 0){
+        for (int i = 0; i < resolutionCount; ++i) {
+            /* FIXME 暂定水平和垂直分辨率相同 */
+            if((resolution[i].horizontalDpi > 0) &&
+                (!m_resolutions.contains(resolution[i].horizontalDpi))){
+                m_resolutions.append(resolution[i].horizontalDpi);
+            }
+        }
+    }
+
+    // If no result, try just the default
+    if (m_resolutions.size() == 0) {
+        Print_Resolution defaultResolution = m_printerInfo->defaultValue.defaultResolution;
+        if((defaultResolution.horizontalDpi > 0) &&
+            (!m_resolutions.contains(defaultResolution.horizontalDpi))){
+            m_resolutions.append(defaultResolution.horizontalDpi);
+        }
+    }
+
+    m_haveResolutions = true;
+}
+
+int QOpenHarmonyPrintDevice::defaultResolution() const
+{
+    if(!m_printerInfo)
+        return 72;
+
+    Print_Resolution defaultResolution = m_printerInfo->defaultValue.defaultResolution;
+    int res = defaultResolution.horizontalDpi;
+    if(res > 0){
+        return res;
+    }
+    // Otherwise return a sensible default.
+    // TODO What is sensible? 150? 300?
+    return 72;
+}
+
+//todo:鸿蒙native接口中没有InputSlots信息
+void QOpenHarmonyPrintDevice::loadInputSlots() const
+{
+    // // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+    // // TODO Deal with concatenated names like Tray1Manual or Tray1_Man,
+    // //      will currently show as CustomInputSlot
+    // // TODO Deal with separate ManualFeed key
+    // // Try load standard PPD options first
+    // m_inputSlots.clear();
+    // if (m_ppd) {
+    //     ppd_option_t *inputSlots = ppdFindOption(m_ppd, "InputSlot");
+    //     if (inputSlots) {
+    //         m_inputSlots.reserve(inputSlots->num_choices);
+    //         for (int i = 0; i < inputSlots->num_choices; ++i)
+    //             m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[i]));
+    //     }
+    //     // If no result, try just the default
+    //     if (m_inputSlots.size() == 0) {
+    //         inputSlots = ppdFindOption(m_ppd, "DefaultInputSlot");
+    //         if (inputSlots)
+    //             m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[0]));
+    //     }
+    // }
+    // // If still no result, just use Auto
+    // if (m_inputSlots.size() == 0)
+    //     m_inputSlots.append(QPlatformPrintDevice::defaultInputSlot());
+    // m_haveInputSlots = true;
+}
+
+QPrint::InputSlot QOpenHarmonyPrintDevice::defaultInputSlot() const
+{
+    //todo:鸿蒙native接口中没有InputSlots信息
+    // // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+    // // Try load standard PPD option first
+    // if (m_ppd) {
+    //     ppd_option_t *inputSlot = ppdFindOption(m_ppd, "DefaultInputSlot");
+    //     if (inputSlot)
+    //         return QPrintUtils::ppdChoiceToInputSlot(inputSlot->choices[0]);
+    //     // If no result, then try a marked option
+    //     ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "InputSlot");
+    //     if (defaultChoice)
+    //         return QPrintUtils::ppdChoiceToInputSlot(*defaultChoice);
+    // }
+    // Otherwise return Auto
+    return QPlatformPrintDevice::defaultInputSlot();
+}
+//todo:鸿蒙native接口中没有OutputBins信息
+void QOpenHarmonyPrintDevice::loadOutputBins() const
+{
+    // // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+    // m_outputBins.clear();
+    // if (m_ppd) {
+    //     ppd_option_t *outputBins = ppdFindOption(m_ppd, "OutputBin");
+    //     if (outputBins) {
+    //         m_outputBins.reserve(outputBins->num_choices);
+    //         for (int i = 0; i < outputBins->num_choices; ++i)
+    //             m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[i]));
+    //     }
+    //     // If no result, try just the default
+    //     if (m_outputBins.size() == 0) {
+    //         outputBins = ppdFindOption(m_ppd, "DefaultOutputBin");
+    //         if (outputBins)
+    //             m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[0]));
+    //     }
+    // }
+    // // If still no result, just use Auto
+    // if (m_outputBins.size() == 0)
+    //     m_outputBins.append(QPlatformPrintDevice::defaultOutputBin());
+    // m_haveOutputBins = true;
+}
+
+QPrint::OutputBin QOpenHarmonyPrintDevice::defaultOutputBin() const
+{
+    //todo:鸿蒙native接口中没有OutputBins信息
+    // // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+    // // Try load standard PPD option first
+    // if (m_ppd) {
+    //     ppd_option_t *outputBin = ppdFindOption(m_ppd, "DefaultOutputBin");
+    //     if (outputBin)
+    //         return QPrintUtils::ppdChoiceToOutputBin(outputBin->choices[0]);
+    //     // If no result, then try a marked option
+    //     ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "OutputBin");
+    //     if (defaultChoice)
+    //         return QPrintUtils::ppdChoiceToOutputBin(*defaultChoice);
+    // }
+    // Otherwise return AutoBin
+    return QPlatformPrintDevice::defaultOutputBin();
+}
+
+void QOpenHarmonyPrintDevice::loadDuplexModes() const
+{
+    if(!m_printerInfo)
+        return;
+
+    // Try load standard PPD options first
+    m_duplexModes.clear();
+    Print_DuplexMode *duplexModes = m_printerInfo->capability.supportedDuplexModes;
+    uint duplexModesCount = m_printerInfo->capability.supportedDuplexModesCount;
+    QPrint::DuplexMode qtDuplexMode;
+
+    if(duplexModes){
+        m_duplexModes.reserve(duplexModesCount);
+        for (int i = 0; i < duplexModesCount; ++i) {
+            switch(*(duplexModes+i)){
+            case DUPLEX_MODE_ONE_SIDED:
+                qtDuplexMode = QPrint::DuplexNone;
+                break;
+            case DUPLEX_MODE_TWO_SIDED_LONG_EDGE:
+                qtDuplexMode = QPrint::DuplexLongSide;
+                break;
+            case DUPLEX_MODE_TWO_SIDED_SHORT_EDGE:
+                qtDuplexMode = QPrint::DuplexShortSide;
+                break;
+            default:
+                qtDuplexMode = QPrint::DuplexNone;
+                break;
+            }
+            if(!m_duplexModes.contains(qtDuplexMode)){
+                m_duplexModes.append(qtDuplexMode);
+            }
+        }
+    }
+
+    if (m_duplexModes.size() == 0) {
+        Print_DuplexMode defaultDuplexMode = m_printerInfo->defaultValue.defaultDuplexMode;
+        switch(defaultDuplexMode){
+        case DUPLEX_MODE_ONE_SIDED:
+            qtDuplexMode = QPrint::DuplexNone;
+            break;
+        case DUPLEX_MODE_TWO_SIDED_LONG_EDGE:
+            qtDuplexMode = QPrint::DuplexLongSide;
+            break;
+        case DUPLEX_MODE_TWO_SIDED_SHORT_EDGE:
+            qtDuplexMode = QPrint::DuplexShortSide;
+            break;
+        default:
+            qtDuplexMode = QPrint::DuplexNone;
+            break;
+        }
+        if(!m_duplexModes.contains(qtDuplexMode)){
+            m_duplexModes.append(qtDuplexMode);
+        }
+    }
+
+    // If still no result, or not added in PPD, then add None
+    if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone))
+        m_duplexModes.append(QPrint::DuplexNone);
+    // If have both modes, then can support DuplexAuto
+    if (m_duplexModes.contains(QPrint::DuplexLongSide) && m_duplexModes.contains(QPrint::DuplexShortSide))
+        m_duplexModes.append(QPrint::DuplexAuto);
+
+    m_haveDuplexModes = true;
+}
+
+QPrint::DuplexMode QOpenHarmonyPrintDevice::defaultDuplexMode() const
+{
+    QPrint::DuplexMode qtDuplexMode;
+    Print_DuplexMode defaultDuplexMode = m_printerInfo ? m_printerInfo->defaultValue.defaultDuplexMode : DUPLEX_MODE_ONE_SIDED;
+    switch(defaultDuplexMode){
+    case DUPLEX_MODE_ONE_SIDED:
+        qtDuplexMode = QPrint::DuplexNone;
+        break;
+    case DUPLEX_MODE_TWO_SIDED_LONG_EDGE:
+        qtDuplexMode = QPrint::DuplexLongSide;
+        break;
+    case DUPLEX_MODE_TWO_SIDED_SHORT_EDGE:
+        qtDuplexMode = QPrint::DuplexShortSide;
+        break;
+    default:
+        qtDuplexMode = QPrint::DuplexNone;
+        break;
+    }
+    return qtDuplexMode;
+}
+
+void QOpenHarmonyPrintDevice::loadColorModes() const
+{
+    if(!m_printerInfo)
+        return;
+
+    m_colorModes.clear();
+
+    Print_ColorMode *colorModes = m_printerInfo->capability.supportedColorModes;
+    uint colorModesCount = m_printerInfo->capability.supportedColorModesCount;
+    QPrint::ColorMode qtColorMode;
+
+    for (int i = 0; i < colorModesCount; ++i) {
+        switch(*(colorModes+i)){
+        case COLOR_MODE_MONOCHROME:
+            qtColorMode = QPrint::GrayScale;
+            break;
+        case COLOR_MODE_COLOR:
+            qtColorMode = QPrint::Color;
+            break;
+        case COLOR_MODE_AUTO:
+            qtColorMode = QPrint::Color;
+            break;
+        default:
+            qtColorMode = QPrint::GrayScale;
+            break;
+        }
+        if(!m_colorModes.contains(qtColorMode)){
+            m_colorModes.append(qtColorMode);
+        }
+    }
+
+    m_haveColorModes = true;
+}
+
+QPrint::ColorMode QOpenHarmonyPrintDevice::defaultColorMode() const
+{
+    // Not a proper option, usually only know if supports color or not, but some
+    // users known to abuse ColorModel to always force GrayScale.
+    if (supportedColorModes().contains(QPrint::Color)) {
+        QPrint::ColorMode qtColorMode = QPrint::GrayScale;
+
+        if(m_printerInfo && m_printerInfo->printerId != nullptr){
+            Print_ColorMode defaultColorMode = m_printerInfo->defaultValue.defaultColorMode;
+            switch(defaultColorMode){
+            case COLOR_MODE_MONOCHROME:
+                qtColorMode = QPrint::GrayScale;
+                break;
+            case COLOR_MODE_COLOR:
+                qtColorMode = QPrint::Color;
+                break;
+            case COLOR_MODE_AUTO:
+                qtColorMode = QPrint::Color;
+                break;
+            default:
+                qtColorMode = QPrint::GrayScale;
+                break;
+            }
+        }
+
+        if(QPrint::Color == qtColorMode)
+        {
+            return qtColorMode;
+        }
+    }
+
+    return QPrint::GrayScale;
+}
+
+QVariant QOpenHarmonyPrintDevice::property(QPrintDevice::PrintDevicePropertyKey key) const
+{
+    //todo:鸿蒙native没有这些接口
+    // if (key == PDPK_PpdFile)
+    //     return QVariant::fromValue<ppd_file_t *>(m_ppd);
+    // else if (key == PDPK_CupsJobPriority)
+    //     return printerOption(QStringLiteral("job-priority"));
+    // else if (key == PDPK_CupsJobSheets)
+    //     return printerOption(QStringLiteral("job-sheets"));
+    // else if (key == PDPK_CupsJobBilling)
+    //     return printerOption(QStringLiteral("job-billing"));
+    // else if (key == PDPK_CupsJobHoldUntil)
+    //     return printerOption(QStringLiteral("job-hold-until"));
+    if (key == PDPK_OHOSPrinterId) {
+        return m_PrinterId;
+    }
+
+    return QPlatformPrintDevice::property(key);
+}
+
+bool QOpenHarmonyPrintDevice::setProperty(QPrintDevice::PrintDevicePropertyKey key, const QVariant &value)
+{
+    //todo:鸿蒙native没有该接口
+    // if (key == PDPK_PpdOption) {
+    //     const QStringList values = value.toStringList();
+    //     if (values.count() == 2) {
+    //         ppdMarkOption(m_ppd, values[0].toLatin1(), values[1].toLatin1());
+    //         return true;
+    //     }
+    // }
+
+    return QPlatformPrintDevice::setProperty(key, value);
+}
+
+bool QOpenHarmonyPrintDevice::isFeatureAvailable(QPrintDevice::PrintDevicePropertyKey key, const QVariant &params) const
+{
+    //todo:鸿蒙native没有该接口
+    // if (key == PDPK_PpdChoiceIsInstallableConflict) {
+    //     const QStringList values = params.toStringList();
+    //     if (values.count() == 2)
+    //         return ppdInstallableConflict(m_ppd, values[0].toLatin1(), values[1].toLatin1());
+    // }
+
+    return QPlatformPrintDevice::isFeatureAvailable(key, params);
+}
+
+#if QT_CONFIG(mimetype)
+void QOpenHarmonyPrintDevice::loadMimeTypes() const
+{
+    QMimeDatabase db;
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("application/pdf")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("application/postscript")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/gif")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/png")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/jpeg")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/tiff")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("text/html")));
+    m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("text/plain")));
+    m_haveMimeTypes = true;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/printsupport/platform/openharmony/qopenharmonyprintdevice.h b/src/printsupport/platform/openharmony/qopenharmonyprintdevice.h
new file mode 100644
index 00000000000..fb8758f1600
--- /dev/null
+++ b/src/printsupport/platform/openharmony/qopenharmonyprintdevice.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOpenHarmonyPrintDevice_H
+#define QOpenHarmonyPrintDevice_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for the convenience
+// of internal files.  This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtPrintSupport/qprintengine.h"
+#include <qpa/qplatformprintdevice.h>
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qmargins.h>
+#include <BasicServicesKit/ohprint.h>
+
+QT_BEGIN_NAMESPACE
+
+struct oh_ppd_file_t;       //todo:仅占位,鸿蒙native接口没有该结构体。
+
+class QOpenHarmonyPrintDevice : public QPlatformPrintDevice
+{
+public:
+    explicit QOpenHarmonyPrintDevice(const QString &id);
+    virtual ~QOpenHarmonyPrintDevice();
+
+    bool isValid() const override;
+    bool isDefault() const override;
+
+    QPrint::DeviceState state() const override;
+
+    QPageSize defaultPageSize() const override;
+
+    QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation,
+                               int resolution) const override;
+
+    int defaultResolution() const override;
+
+    QPrint::InputSlot defaultInputSlot() const override;
+
+    QPrint::OutputBin defaultOutputBin() const override;
+
+    QPrint::DuplexMode defaultDuplexMode() const override;
+
+    QPrint::ColorMode defaultColorMode() const override;
+
+    QVariant property(QPrintDevice::PrintDevicePropertyKey key) const override;
+    bool setProperty(QPrintDevice::PrintDevicePropertyKey key, const QVariant &value) override;
+    bool isFeatureAvailable(QPrintDevice::PrintDevicePropertyKey key, const QVariant &params) const override;
+
+protected:
+    void loadPageSizes() const override;
+    void loadResolutions() const override;
+    void loadInputSlots() const override;
+    void loadOutputBins() const override;
+    void loadDuplexModes() const override;
+    void loadColorModes() const override;
+#if QT_CONFIG(mimetype)
+    void loadMimeTypes() const override;
+#endif
+
+private:
+    Print_PrinterInfo *m_printerInfo;
+    oh_ppd_file_t *m_ppd;
+    QByteArray m_PrinterId;
+    QMarginsF m_customMargins;
+    mutable QHash<QString, QMarginsF> m_printableMargins;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOpenHarmonyPrintDevice_H
diff --git a/src/printsupport/platform/openharmony/qopenharmonyprintengine.cpp b/src/printsupport/platform/openharmony/qopenharmonyprintengine.cpp
new file mode 100644
index 00000000000..642d9658cac
--- /dev/null
+++ b/src/printsupport/platform/openharmony/qopenharmonyprintengine.cpp
@@ -0,0 +1,515 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <qfile.h>
+#include <qdebug.h>
+#include <qbuffer.h>
+#include <QFileInfo>
+#include <qiodevice.h>
+#include <QPrintDialog>
+#include <QStandardPaths>
+#include <QtGui/qpagelayout.h>
+
+#include <qpa/qplatformprintplugin.h>
+#include <BasicServicesKit/ohprint.h>
+#include <qpa/qplatformprintersupport.h>
+
+#include "private/qcore_unix_p.h" // overrides QT_OPEN
+#include "qopenharmonyprintengine_p.h"
+
+QT_BEGIN_NAMESPACE
+#define PDPK_OHOSPrinterId QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 100)
+extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits);
+
+QOpenHarmonyPrintEngine::QOpenHarmonyPrintEngine(QPrinter::PrinterMode m, const QString &deviceId)
+    : QPdfPrintEngine(*new QOpenHarmonyPrintEnginePrivate(m))
+{
+    Q_D(QOpenHarmonyPrintEngine);
+    d->changePrinter(deviceId);
+    state = QPrinter::Idle;
+}
+
+QOpenHarmonyPrintEngine::~QOpenHarmonyPrintEngine()
+{
+}
+
+void QOpenHarmonyPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value)
+{
+    Q_D(QOpenHarmonyPrintEngine);
+
+    switch (int(key)) {
+    case PPK_PageSize:
+        d->setPageSize(QPageSize(QPageSize::PageSizeId(value.toInt())));
+        break;
+    case PPK_WindowsPageSize:
+        d->setPageSize(QPageSize(QPageSize::id(value.toInt())));
+        break;
+    case PPK_CustomPaperSize:
+        d->setPageSize(QPageSize(value.toSizeF(), QPageSize::Point));
+        break;
+    case PPK_PaperName:
+        // Get the named page size from the printer if supported
+        d->setPageSize(d->m_printDevice.supportedPageSize(value.toString()));
+        break;
+    case PPK_Duplex: {
+        QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt());
+        if (d->m_printDevice.supportedDuplexModes().contains(mode)) {
+            d->duplex = mode;
+            d->duplexRequestedExplicitly = true;
+        }
+        break;
+    }
+    case PPK_Orientation: {
+        d->m_pageLayout.setOrientation(QPageLayout::Orientation(value.toInt()));
+        qWarning() << "set ppk orientation:" << d->m_pageLayout;
+    }
+    break;
+    case PPK_PrinterName:
+        d->changePrinter(value.toString());
+        break;
+    case PPK_OhPrintOptions:
+        d->ohOptions = value.toStringList();
+        break;
+    case PPK_QPageSize:
+        d->setPageSize(qvariant_cast<QPageSize>(value));
+        break;
+    case PPK_QPageLayout: {
+        QPageLayout pageLayout = qvariant_cast<QPageLayout>(value);
+        d->m_pageLayout = pageLayout;
+        qWarning() << "set ppk page layout:" << d->m_pageLayout;
+#if 0
+        if (pageLayout.isValid() && (d->m_printDevice.isValidPageLayout(pageLayout, d->resolution)
+                                     || d->m_printDevice.supportsCustomPageSizes()
+                                     || d->m_printDevice.supportedPageSizes().isEmpty())) {
+            // supportedPageSizes().isEmpty() because QPageSetupWidget::initPageSizes says
+            // "If no available printer page sizes, populate with all page sizes"
+            d->m_pageLayout = pageLayout;
+            d->setPageSize(pageLayout.pageSize());
+        }
+#endif
+        break;
+    }
+    default:
+        QPdfPrintEngine::setProperty(key, value);
+        break;
+    }
+}
+
+QVariant QOpenHarmonyPrintEngine::property(PrintEnginePropertyKey key) const
+{
+    Q_D(const QOpenHarmonyPrintEngine);
+
+    QVariant ret;
+    switch (int(key)) {
+    case PPK_SupportsMultipleCopies:
+        //不确定是否支持该属性,暂时认为不支持。
+        ret = false;
+        break;
+    case PPK_NumberOfCopies:
+        ret = 1;
+        break;
+    case PPK_OhPrintOptions:
+        ret = d->ohOptions;
+        break;
+    case PPK_Duplex:
+        ret = d->duplex;
+        break;
+    default:
+        ret = QPdfPrintEngine::property(key);
+        break;
+    }
+    return ret;
+}
+
+
+QOpenHarmonyPrintEnginePrivate::QOpenHarmonyPrintEnginePrivate(QPrinter::PrinterMode m)
+    : QPdfPrintEnginePrivate(m)
+    , duplex(QPrint::DuplexNone)
+    , printMode(m)
+{
+    outputFileName.clear();
+    ownsDevice = true; /* FIXME 是否让PDF基类控制文件内容落盘 */
+}
+
+QOpenHarmonyPrintEnginePrivate::~QOpenHarmonyPrintEnginePrivate()
+{
+}
+
+bool QOpenHarmonyPrintEnginePrivate::openPrintDevice()
+{
+    if (this->outDevice)
+        return false;
+
+    if (!outputFileName.isEmpty()) {
+        QFile *file = new QFile(outputFileName);
+        if (!file->open(QFile::WriteOnly|QFile::Truncate)) {
+            delete file;
+            return false;
+        }
+        this->outDevice = file;
+    } else {
+        QUuid uuid = QUuid::createUuid();
+        const QString &tempDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
+        ohTempFile = QString("%1/%2.pdf").arg(tempDir, uuid.toString(QUuid::Id128));
+        fd = open(ohTempFile.toLocal8Bit().constData(), O_CREAT | O_SYNC | O_WRONLY,
+                  S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP);
+        QFile *f = new QFile();
+        // if (!f->open(QIODevice::WriteOnly)) {
+        //     f->close();
+        //     qWarning() << "create print temp file failed:" << f->errorString();
+        //     return false;
+        // }
+        this->outDevice = f;
+        static_cast<QFile *>(outDevice)->open(fd, QIODevice::WriteOnly);
+        //this->fd = f->handle();
+        qWarning() << "open tmp file:" << ohTempFile <<  "fd:" << fd << outDevice;
+    }
+
+    return true;
+}
+
+void QOpenHarmonyPrintEnginePrivate::closePrintDevice()
+{
+    Q_Q(QOpenHarmonyPrintEngine);
+    if (!ohTempFile.isEmpty()) {
+        QString tempFile = ohTempFile;
+        ohTempFile.clear();
+
+        // Should never have got here without a printer, but check anyway
+        if (printerName.isEmpty()) {
+            qWarning("Could not determine printer to print to");
+            QFile::remove(tempFile);
+            return;
+        }
+
+#if 0
+        Print_ErrorCode errCode = OH_Print_ConnectPrinter(printerName.toLocal8Bit().constData());
+        if (Print_ErrorCode::PRINT_ERROR_NONE != errCode)
+        {
+            qWarning() << "OnPrint OH_Print_ConnectPrinter error:" << errCode;
+            OH_Print_StopPrinterDiscovery();
+            OH_Print_UnregisterPrinterChangeListener();
+            OH_Print_Release();
+            return;
+        }
+#endif
+        // Set up print options.
+        QList<QPair<QByteArray, QByteArray> > options;
+        QVector<Print_Property> ohPrintOptStruct;
+
+
+        options.append(QPair<QByteArray, QByteArray>("media", m_pageLayout.pageSize().key().toLocal8Bit()));
+
+        if (copies > 1)
+            options.append(QPair<QByteArray, QByteArray>("copies", QString::number(copies).toLocal8Bit()));
+
+        if (copies > 1 && collate)
+            options.append(QPair<QByteArray, QByteArray>("Collate", "True"));
+
+        switch (duplex) {
+        case QPrint::DuplexNone:
+            options.append(QPair<QByteArray, QByteArray>("sides", "one-sided"));
+            break;
+        case QPrint::DuplexAuto:
+            if (m_pageLayout.orientation() == QPageLayout::Portrait)
+                options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-long-edge"));
+            else
+                options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-short-edge"));
+            break;
+        case QPrint::DuplexLongSide:
+            options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-long-edge"));
+            break;
+        case QPrint::DuplexShortSide:
+            options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-short-edge"));
+            break;
+        }
+
+        if (m_pageLayout.orientation() == QPageLayout::Landscape)
+            options.append(QPair<QByteArray, QByteArray>("landscape", ""));
+
+        QStringList::const_iterator it = ohOptions.constBegin();
+        while (it != ohOptions.constEnd()) {
+            options.append(QPair<QByteArray, QByteArray>((*it).toLocal8Bit(), (*(it+1)).toLocal8Bit()));
+            it += 2;
+        }
+
+        const int numOptions = options.size();
+        ohPrintOptStruct.reserve(numOptions);
+        for (int c = 0; c < numOptions; ++c) {
+            Print_Property prop;
+            prop.key = options[c].first.data();
+            prop.value = options[c].second.data();
+            ohPrintOptStruct.append(prop);
+        }
+#if 0
+        int thisFd = -1;
+        QFile file(tempFile);
+        if (!file.open(QFile::ReadOnly)) {
+            qWarning() << "get file:" << tempFile << "failed:" << file.errorString();
+            file.close();
+            return;
+        }
+        thisFd = file.handle();
+        file.close();
+#endif
+
+        Print_PrintJob printJob;
+#if 0
+        /* 公共目录下文件无法打印,拷贝到临时目录下 */
+        //QFile sourceFile("/storage/Users/currentUser/DowLoad/123.pdf");
+        QFile sourceFile(tempFile);
+        QTemporaryDir temporaryDir;
+        QString temporaryDirPath = temporaryDir.path();
+        QString destinationFilePath = QDir(temporaryDirPath).filePath(sourceFile.fileName());
+        qDebug() << "destinationFilePath:" << destinationFilePath;
+        if (!sourceFile.copy(destinationFilePath)) {
+            qDebug() << "copy failed";
+        }
+#endif
+
+        //QFile::copy("/storage/Users/currentUser/Desktop/wanghao_test222.pdf", "/data/storage/el2/base/temp/test.pdf");
+        //fd = open("/data/storage/el2/base/temp/test.pdf", O_RDONLY);
+        /* FIXME 何时close文件? */
+        fd = open(tempFile.toLocal8Bit().constData(), O_RDONLY);
+        // QFile ff(tempFile);
+        // ff.open(QIODevice::ReadOnly);
+        // fd = ff.handle();
+
+        // struct stat st;
+        // fstat(fd, &st);
+
+        // qWarning() << st.st_size << fd
+        //            << tempFile << m_pageLayout;
+
+        QString jobName = title.isEmpty() ? QUuid::createUuid().toString(QUuid::Id128) : title;
+        QByteArray jobNameArray = jobName.toUtf8();
+        std::unique_ptr<char[]> cjobName(new char[jobNameArray.length() + 1]);
+        memset(cjobName.get(), 0, jobNameArray.length() + 1);
+        memcpy(cjobName.get(), jobNameArray.constData(), jobNameArray.length());
+        printJob.jobName = cjobName.get();
+        printJob.fdList = new uint32_t[1]{0};
+        printJob.fdList[0] = fd;
+        printJob.fdListCount = 1;
+
+        /* FIXME OH_Print_StartPrintJob接口负责删除? 不这样会有内存访问问题 */
+        char *id = new char[printerName.length() + 1]{0};
+        memcpy(id, printerName.toLocal8Bit().data(), printerName.length());
+        printJob.printerId = id;
+        printJob.copyNumber = copies;
+        // printJob.paperSource = q->property(PPK_PaperSources);
+        printJob.paperSource = "auto";
+        printJob.mediaType = "stationery";
+        QString key = m_pageLayout.pageSize().key();
+        std::unique_ptr<char[]> ckey(new char[key.length() + 1]);
+        memset(ckey.get(), 0, key.length() + 1);
+        memcpy(ckey.get(), key.toLocal8Bit().data(), key.length());
+        printJob.pageSizeId = ckey.get();
+        //printJob.pageSizeId = "ISO_A4";
+        //Print_ColorMode
+        Print_ColorMode ohColorMode;
+        QPrinter::ColorMode qtColorMode = (QPrinter::ColorMode)q->property(QPrintEngine::PPK_ColorMode).toInt();
+        switch(qtColorMode){
+        case QPrinter::GrayScale:
+            ohColorMode = COLOR_MODE_MONOCHROME;
+            break;
+        case QPrinter::Color:
+            ohColorMode = COLOR_MODE_COLOR;
+            break;
+        default:
+            ohColorMode = COLOR_MODE_MONOCHROME;
+            break;
+        }
+        printJob.colorMode = ohColorMode;
+
+
+        //Print_DuplexMode
+        Print_DuplexMode ohDuplexMode;
+        QPrint::DuplexMode qtDuplexMode = (QPrint::DuplexMode)q->property(QPrintEngine::PPK_Duplex).toInt();
+        switch(qtDuplexMode){
+        case QPrinter::DuplexNone:
+            ohDuplexMode = DUPLEX_MODE_ONE_SIDED;
+            break;
+        case QPrinter::DuplexAuto:
+            //自动模式暂时设置为One sided。
+            ohDuplexMode = DUPLEX_MODE_ONE_SIDED;
+            break;
+        case QPrinter::DuplexLongSide:
+            ohDuplexMode = DUPLEX_MODE_TWO_SIDED_LONG_EDGE;
+            break;
+        case QPrinter::DuplexShortSide:
+            ohDuplexMode = DUPLEX_MODE_TWO_SIDED_SHORT_EDGE;
+            break;
+        default:
+            ohDuplexMode = DUPLEX_MODE_ONE_SIDED;
+            break;
+        }
+        printJob.duplexMode = ohDuplexMode;
+
+        //Print_Resolution
+        int resolution = 600/*q->property(QPrintEngine::PPK_Resolution).toInt()*/;
+        printJob.resolution.horizontalDpi = resolution;
+        printJob.resolution.verticalDpi = resolution;
+
+        //Print_Margin
+        Print_Margin ohPrintMargin;
+        QPair<QMarginsF, QPageLayout::Unit> pair = qvariant_cast<QPair<QMarginsF, QPageLayout::Unit> >(q->property(QPrintEngine::PPK_QPageMargins));
+        ohPrintMargin.leftMargin = static_cast<uint>(pair.first.left());
+        ohPrintMargin.topMargin = static_cast<uint>(pair.first.top());
+        ohPrintMargin.rightMargin = static_cast<uint>(pair.first.right());
+        ohPrintMargin.bottomMargin = static_cast<uint>(pair.first.bottom());
+        printJob.printMargin = ohPrintMargin;
+        /* 默认无border */
+        printJob.borderless = false;
+
+        //Print_OrientationMode
+        Print_OrientationMode ohOrientationMode;
+        // int ohOrientationMode;
+        QPageLayout::Orientation qtOrientation = m_pageLayout.orientation();
+        switch(qtOrientation){
+        case QPageLayout::Portrait:
+            ohOrientationMode = ORIENTATION_MODE_PORTRAIT;
+            break;
+        case QPageLayout::Landscape:
+            ohOrientationMode = ORIENTATION_MODE_LANDSCAPE;
+            break;
+        default:
+            ohOrientationMode = ORIENTATION_MODE_PORTRAIT;
+            break;
+        }
+        printJob.orientationMode = ohOrientationMode;
+
+        //Print_Quality
+        Print_Quality ohQuality;
+        switch(printMode){
+        case QPrinter::ScreenResolution:
+            ohQuality = PRINT_QUALITY_DRAFT;
+            break;
+        case QPrinter::PrinterResolution:
+            ohQuality = PRINT_QUALITY_NORMAL;
+            break;
+        case QPrinter::HighResolution:
+            ohQuality = PRINT_QUALITY_HIGH;
+            break;
+        default:
+            ohQuality = PRINT_QUALITY_HIGH;
+            break;
+        }
+        printJob.printQuality = ohQuality;
+
+
+        //Print_DocumentFormat
+        Print_DocumentFormat ohDocumentFormat;
+        QFileInfo fi(outputFileName);
+        if (!fi.suffix().compare(QLatin1String("pdf"), Qt::CaseInsensitive))
+            ohDocumentFormat = DOCUMENT_FORMAT_PDF;
+        else if (!fi.suffix().compare(QLatin1String("jpeg"), Qt::CaseInsensitive) ||
+                 !fi.suffix().compare(QLatin1String("jpg"), Qt::CaseInsensitive))
+            ohDocumentFormat = DOCUMENT_FORMAT_JPEG;
+        else if (!fi.suffix().compare(QLatin1String("ps"), Qt::CaseInsensitive))
+            ohDocumentFormat = DOCUMENT_FORMAT_POSTSCRIPT;
+        else if (!fi.suffix().compare(QLatin1String("txt"), Qt::CaseInsensitive))
+            ohDocumentFormat = DOCUMENT_FORMAT_TEXT;
+        else{
+            ohDocumentFormat = DOCUMENT_FORMAT_AUTO;
+        }
+        /* FIXME 暂时支持PDF格式 */
+        printJob.documentFormat = DOCUMENT_FORMAT_PDF;
+        printJob.advancedOptions = nullptr;
+
+        qWarning() << "start print job page layout" << this->m_pageLayout;
+        /* 启动打印任务 */
+        int ret = OH_Print_StartPrintJob(&printJob);        
+        if(PRINT_ERROR_NONE != ret){
+            qWarning() << "print job execute fail,errCode:" << ret;
+        }
+
+        //QPdfPrintEnginePrivate::closePrintDevice();
+    }
+}
+
+void QOpenHarmonyPrintEnginePrivate::changePrinter(const QString &newPrinter)
+{
+    // Don't waste time if same printer name
+    if (newPrinter == printerName)
+        return;
+
+    // Should never have reached here if no plugin available, but check just in case
+    QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
+    if (!ps)
+        return;
+
+    // Try create the printer, only use it if it returns valid
+    QPrintDevice printDevice = ps->createPrintDevice(newPrinter);
+    if (!printDevice.isValid())
+        return;
+    m_printDevice.swap(printDevice);
+    printerName = m_printDevice.property(PDPK_OHOSPrinterId).toString();
+
+    // in case a duplex value was explicitly set, check if new printer supports current value,
+    // otherwise use device default
+    if (!duplexRequestedExplicitly || !m_printDevice.supportedDuplexModes().contains(duplex)) {
+        duplex = m_printDevice.defaultDuplexMode();
+        duplexRequestedExplicitly = false;
+    }
+    QPrint::ColorMode colorMode = grayscale ? QPrint::GrayScale : QPrint::Color;
+    if (!m_printDevice.supportedColorModes().contains(colorMode))
+        grayscale = m_printDevice.defaultColorMode() == QPrint::GrayScale;
+
+    // Get the equivalent page size for this printer as supported names may be different
+    if (m_printDevice.supportedPageSize(m_pageLayout.pageSize()).isValid())
+        setPageSize(m_pageLayout.pageSize());
+    else
+        setPageSize(QPageSize(m_pageLayout.pageSize().size(QPageSize::Point), QPageSize::Point));
+}
+
+void QOpenHarmonyPrintEnginePrivate::setPageSize(const QPageSize &pageSize)
+{
+    if (pageSize.isValid()) {
+        // Find if the requested page size has a matching printer page size, if so use its defined name instead
+        QPageSize printerPageSize = m_printDevice.supportedPageSize(pageSize);
+        QPageSize usePageSize = printerPageSize.isValid() ? printerPageSize : pageSize;
+        QMarginsF printable = m_printDevice.printableMargins(usePageSize, m_pageLayout.orientation(), resolution);
+        m_pageLayout.setPageSize(usePageSize, qt_convertMargins(printable, QPageLayout::Point, m_pageLayout.units()));
+    }
+}
+
+QT_END_NAMESPACE
diff --git a/src/printsupport/platform/openharmony/qopenharmonyprintengine_p.h b/src/printsupport/platform/openharmony/qopenharmonyprintengine_p.h
new file mode 100644
index 00000000000..7fb7894975f
--- /dev/null
+++ b/src/printsupport/platform/openharmony/qopenharmonyprintengine_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENHARMONYPRINTENGINE_P_H
+#define QOPENHARMONYPRINTENGINE_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtPrintSupport/qprintengine.h"
+
+#include <QtCore/qstring.h>
+#include <QtGui/qpaintengine.h>
+
+#include <private/qpaintengine_p.h>
+#include <private/qprintdevice_p.h>
+#include <private/qprintengine_pdf_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#define PPK_OhPrintOptions QPrintEngine::PrintEnginePropertyKey(0xef55)
+
+class QOpenHarmonyPrintEnginePrivate;
+
+class QOpenHarmonyPrintEngine : public QPdfPrintEngine
+{
+    Q_DECLARE_PRIVATE(QOpenHarmonyPrintEngine)
+public:
+    QOpenHarmonyPrintEngine(QPrinter::PrinterMode m, const QString &deviceId);
+    virtual ~QOpenHarmonyPrintEngine();
+
+    // reimplementations QPdfPrintEngine
+    void setProperty(PrintEnginePropertyKey key, const QVariant &value) override;
+    QVariant property(PrintEnginePropertyKey key) const override;
+    // end reimplementations QPdfPrintEngine
+
+private:
+    Q_DISABLE_COPY_MOVE(QOpenHarmonyPrintEngine)
+};
+
+class QOpenHarmonyPrintEnginePrivate : public QPdfPrintEnginePrivate
+{
+    Q_DECLARE_PUBLIC(QOpenHarmonyPrintEngine)
+public:
+    QOpenHarmonyPrintEnginePrivate(QPrinter::PrinterMode m);
+    ~QOpenHarmonyPrintEnginePrivate();
+
+    bool openPrintDevice() override;
+    void closePrintDevice() override;
+
+private:
+    Q_DISABLE_COPY_MOVE(QOpenHarmonyPrintEnginePrivate)
+
+    void changePrinter(const QString &newPrinter);
+    void setPageSize(const QPageSize &pageSize);
+
+    QPrintDevice m_printDevice;
+    QStringList ohOptions;
+    QString ohTempFile;
+    QPrint::DuplexMode duplex;
+    bool duplexRequestedExplicitly = false;
+    QPrinter::PrinterMode printMode;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOPENHARMONYPRINTENGINE_P_H
diff --git a/src/printsupport/platform/openharmony/qopenharmonyprintersupport.cpp b/src/printsupport/platform/openharmony/qopenharmonyprintersupport.cpp
new file mode 100644
index 00000000000..b87e1e165c9
--- /dev/null
+++ b/src/printsupport/platform/openharmony/qopenharmonyprintersupport.cpp
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopenharmonyprintersupport_p.h"
+
+#include "qopenharmonyprintengine_p.h"
+#include "qopenharmonyprintdevice.h"
+#include <private/qprinterinfo_p.h>
+#include <private/qprintdevice_p.h>
+#include <QtPrintSupport/QPrinterInfo>
+
+#if QT_CONFIG(dialogbuttonbox)
+#include <QGuiApplication>
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QFormLayout>
+#include <QLabel>
+#include <QLineEdit>
+#endif // QT_CONFIG(dialogbuttonbox)
+
+QT_BEGIN_NAMESPACE
+#if 0
+#if QT_CONFIG(dialogbuttonbox)
+static const char *getPasswordCB(const char */*prompt*/, http_t *http, const char */*method*/, const char *resource, void */*user_data*/)
+{
+    // cups doesn't free the const char * we return so keep around
+    // the last password so we don't leak memory if called multiple times.
+    static QByteArray password;
+
+    // prompt is always "Password for %s on %s? " but we can't use it since we allow the user to change the user.
+    // That is fine because cups always calls cupsUser after calling this callback.
+    // We build our own prompt with the hostname (if not localhost) and the resource that is being used
+
+    char hostname[HTTP_MAX_HOST];
+    httpGetHostname(http, hostname, HTTP_MAX_HOST);
+
+    const QString username = QString::fromLocal8Bit(cupsUser());
+
+    QDialog dialog;
+    dialog.setWindowTitle(QCoreApplication::translate("QOpenHarmonyPrinterSupport", "Authentication Needed"));
+
+    QFormLayout *layout = new QFormLayout(&dialog);
+    layout->setSizeConstraint(QLayout::SetFixedSize);
+
+    QLineEdit *usernameLE = new QLineEdit();
+    usernameLE->setText(username);
+
+    QLineEdit *passwordLE = new QLineEdit();
+    passwordLE->setEchoMode(QLineEdit::Password);
+
+    QString resourceString = QString::fromLocal8Bit(resource);
+    if (resourceString.startsWith(QStringLiteral("/printers/")))
+        resourceString = resourceString.mid(QStringLiteral("/printers/").length());
+
+    QLabel *label = new QLabel();
+    if (hostname == QStringLiteral("localhost")) {
+        label->setText(QCoreApplication::translate("QOpenHarmonyPrinterSupport", "Authentication needed to use %1.").arg(resourceString));
+    } else {
+        label->setText(QCoreApplication::translate("QOpenHarmonyPrinterSupport", "Authentication needed to use %1 on %2.").arg(resourceString).arg(hostname));
+        label->setWordWrap(true);
+    }
+
+    layout->addRow(label);
+    layout->addRow(new QLabel(QCoreApplication::translate("QOpenHarmonyPrinterSupport", "Username:")), usernameLE);
+    layout->addRow(new QLabel(QCoreApplication::translate("QOpenHarmonyPrinterSupport", "Password:")), passwordLE);
+
+    QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+    layout->addRow(buttonBox);
+
+    QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
+    QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
+
+    passwordLE->setFocus();
+
+    if (dialog.exec() != QDialog::Accepted)
+        return nullptr;
+
+    if (usernameLE->text() != username)
+        cupsSetUser(usernameLE->text().toLocal8Bit().constData());
+
+    password = passwordLE->text().toLocal8Bit();
+
+    return password.constData();
+}
+#endif // QT_CONFIG(dialogbuttonbox)
+#endif
+
+static QOpenHarmonyPrinterSupport *ps = nullptr;
+
+QOpenHarmonyPrinterSupport::QOpenHarmonyPrinterSupport()
+    : QPlatformPrinterSupport()
+{
+    ps = this;
+    Print_ErrorCode ret = Print_ErrorCode::PRINT_ERROR_NONE;
+
+    ret = OH_Print_Init();
+    if(PRINT_ERROR_NONE != ret){
+        qWarning() << "QOpenHarmonyPrinterSupport:init Env failed,errCode:" << ret;
+        return;
+    }
+    qInfo() << "QOpenHarmonyPrinterSupport:init Env ok";
+
+    ret = OH_Print_RegisterPrinterChangeListener(Print_PrinterChange);
+    if(PRINT_ERROR_NONE != ret){
+        qWarning() << "QOpenHarmonyPrinterSupport:register printer change failed,errCode:" << ret;
+        return;
+    }
+    qInfo() << "QOpenHarmonyPrinterSupport:register printer change ok";
+
+    ret = OH_Print_StartPrinterDiscovery(Print_PrinterDiscovery);
+    if (PRINT_ERROR_NONE != ret)
+    {
+        qWarning() << "QOpenHarmonyPrinterSupport:StartPrinterDiscovery failed,errCode:" << ret;
+        OH_Print_UnregisterPrinterChangeListener();
+        OH_Print_Release();
+        return;
+    }
+    qInfo() << "QOpenHarmonyPrinterSupport:StartPrinterDiscovery ok";
+
+    detectOHPrinter();
+}
+
+QOpenHarmonyPrinterSupport::~QOpenHarmonyPrinterSupport()
+{
+    OH_Print_StopPrinterDiscovery();
+    OH_Print_UnregisterPrinterChangeListener();
+    OH_Print_Release();
+    ps = nullptr;
+}
+
+QPrintEngine *QOpenHarmonyPrinterSupport::createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId)
+{
+    return new QOpenHarmonyPrintEngine(printerMode, (deviceId.isEmpty() ? defaultPrintDeviceId() : deviceId));
+}
+
+QPaintEngine *QOpenHarmonyPrinterSupport::createPaintEngine(QPrintEngine *engine, QPrinter::PrinterMode printerMode)
+{
+    Q_UNUSED(printerMode)
+    return static_cast<QOpenHarmonyPrintEngine *>(engine);
+}
+
+QPrintDevice QOpenHarmonyPrinterSupport::createPrintDevice(const QString &id)
+{
+    return QPlatformPrinterSupport::createPrintDevice(new QOpenHarmonyPrintDevice(idFromName(id)));
+}
+
+void QOpenHarmonyPrinterSupport::Print_PrinterChange(Print_PrinterEvent event, const Print_PrinterInfo *printerInfo)
+{
+    qInfo() << "Print_PrinterChange id:" << printerInfo->printerId << " name: " <<  printerInfo->printerName;
+}
+
+void QOpenHarmonyPrinterSupport::Print_PrinterDiscovery(Print_DiscoveryEvent event, const Print_PrinterInfo *printerInfo)
+{
+    qInfo() << "PrinterDiscovery id:" << printerInfo->printerId << " name: " <<  printerInfo->printerName;
+    QString id = QString::fromUtf8(printerInfo->printerId);
+    if (event == PRINTER_DISCOVERED) {
+        if (!ps || ps->contains(id))
+            return;
+        OHPrinter p;
+        p.id = id;
+        p.name = QString::fromUtf8(printerInfo->printerName);;
+        p.isDefault = printerInfo->isDefaultPrinter;
+        ps->add(p);
+    } else if (event == PRINTER_LOST) {
+        if (ps != nullptr)
+            ps->remove(id);
+    }
+}
+
+void QOpenHarmonyPrinterSupport::detectOHPrinter()
+{
+    Print_StringList printerIdList;
+    int ret = OH_Print_QueryPrinterList(&printerIdList);
+
+    if (PRINT_ERROR_NONE != ret) {
+        qWarning() << "QOpenHarmonyPrinterSupport:detectOHPrinter OH_Print_QueryPrinterList failed,errCode:" << ret;
+        return;
+    }
+    for (int i = 0; i < printerIdList.count; ++i) {
+        char *id = printerIdList.list[i];
+        Print_PrinterInfo *info = nullptr;
+        ret = OH_Print_QueryPrinterInfo(id, &info);
+        if (PRINT_ERROR_NONE != ret || info == nullptr) {
+            qWarning() << "QOpenHarmonyPrinterSupport:detectOHPrinter OH_Print_QueryPrinterInfo failed,errCode:" << ret;
+            continue;
+        }
+        QString idString = QString::fromUtf8(id);
+        if (contains(idString)) {
+            OH_Print_ReleasePrinterInfo(info);
+            continue;
+        }
+        OHPrinter p;
+        p.id = idString;
+        p.name = QString::fromUtf8(info->printerName);
+        p.isDefault = info->isDefaultPrinter;
+        OH_Print_ReleasePrinterInfo(info);
+        m_printers << p;
+    }
+    OH_Print_ReleasePrinterList(&printerIdList);
+}
+
+bool QOpenHarmonyPrinterSupport::contains(const QString &id)
+{
+    for (int i = 0; i < m_printers.count(); ++i) {
+        if (m_printers.at(i).id == id)
+            return true;
+    }
+    return false;
+}
+
+QStringList QOpenHarmonyPrinterSupport::availablePrintDeviceIds() const
+{
+    QStringList result;
+    for (int i = 0; i < m_printers.count(); ++i) {
+        result << m_printers.at(i).name;
+    }
+    return result;
+}
+
+QString QOpenHarmonyPrinterSupport::defaultPrintDeviceId() const
+{
+    for (int i = 0; i < m_printers.count(); ++i) {
+        if (m_printers.at(i).isDefault)
+            return m_printers.at(i).name;
+    }
+    return QString();
+}
+
+void QOpenHarmonyPrinterSupport::add(const OHPrinter &p)
+{
+    m_printers << p;
+}
+
+void QOpenHarmonyPrinterSupport::remove(const QString &id)
+{
+    for (int i = 0; i < m_printers.count(); ++i) {
+        if (m_printers.at(i).id == id) {
+            m_printers.removeAt(i);
+            break;
+        }
+    }
+}
+
+QString QOpenHarmonyPrinterSupport::defaultPrinterId() const
+{
+    for (int i = 0; i < m_printers.count(); ++i) {
+        if (m_printers.at(i).isDefault)
+            return m_printers.at(i).id;
+    }
+    return QString();
+}
+
+QString QOpenHarmonyPrinterSupport::idFromName(const QString &name)
+{
+    for (int i = 0; i < m_printers.count(); ++i) {
+        if (m_printers.at(i).name == name)
+            return m_printers.at(i).id;
+    }
+    return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/src/printsupport/platform/openharmony/qopenharmonyprintersupport_p.h b/src/printsupport/platform/openharmony/qopenharmonyprintersupport_p.h
new file mode 100644
index 00000000000..c77b0872100
--- /dev/null
+++ b/src/printsupport/platform/openharmony/qopenharmonyprintersupport_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENHARMONYSPRINTERSUPPORT_H
+#define QOPENHARMONYSPRINTERSUPPORT_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qpa/qplatformprintersupport.h>
+
+#include <QtCore/qstringlist.h>
+#include <BasicServicesKit/ohprint.h>
+
+QT_BEGIN_NAMESPACE
+
+struct OHPrinter
+{
+    QString name;
+    QString id;
+    bool isDefault;
+};
+
+class QOpenHarmonyPrinterSupport : public QPlatformPrinterSupport
+{
+public:
+    QOpenHarmonyPrinterSupport();
+    ~QOpenHarmonyPrinterSupport();
+
+    QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) override;
+    QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode) override;
+
+    QPrintDevice createPrintDevice(const QString &id) override;
+    QStringList availablePrintDeviceIds() const override;
+    QString defaultPrintDeviceId() const override;
+    void add(const OHPrinter &p);
+    void remove(const QString &id);
+private:
+    QString defaultPrinterId() const;
+    QString idFromName(const QString &name);
+    void detectOHPrinter();
+    bool contains(const QString &id);
+    QString cupsOption(int i, const QString &key) const;
+
+    static void Print_PrinterChange(Print_PrinterEvent event, const Print_PrinterInfo *printerInfo);
+    static void Print_PrinterDiscovery(Print_DiscoveryEvent event, const Print_PrinterInfo *printerInfo);
+    QList<OHPrinter> m_printers;
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QOPENHARMONYSPRINTERSUPPORT_H
diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp
index 6284c210f25..9124be35f13 100644
--- a/src/testlib/qplaintestlogger.cpp
+++ b/src/testlib/qplaintestlogger.cpp
@@ -24,6 +24,9 @@
 #  include <android/log.h>
 #endif
 
+#ifdef Q_OS_OPENHARMONY
+#include <QDebug>
+#endif
 #ifdef Q_OS_WIN
 #  include <qt_windows.h>
 #endif
@@ -249,6 +252,9 @@ void QPlainTestLogger::outputMessage(const char *str)
     }
 #elif defined(Q_OS_ANDROID)
     __android_log_write(ANDROID_LOG_INFO, "QTestLib", str);
+#elif defined(Q_OS_OPENHARMONY)
+        /* wanghao TODO */
+        qInfo() << str;
 #endif
     outputString(str);
 }
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 4674b925a28..30462c333b0 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -115,6 +115,12 @@
 #include <CoreFoundation/CFPreferences.h>
 #endif
 
+#ifdef Q_OS_OPENHARMONY
+#include <QtCore/QLoggingCategory>
+Q_LOGGING_CATEGORY(openharmonyTestCase, "openharmony.testcase");
+#endif
+
+
 #include <vector>
 
 QT_BEGIN_NAMESPACE
@@ -1753,10 +1759,19 @@ void TestMethods::invokeTests(QObject *testObject) const
         QTestResult::finishedCurrentTestFunction();
 
         if (!QTestResult::skipCurrentTest() && !previousFailed) {
+#ifdef Q_OS_OPENHARMONY
+            const char *className = metaObject->className();
+            int size = m_methods.size();
+#endif
             for (int i = 0, count = int(m_methods.size()); i < count; ++i) {
                 const char *data = nullptr;
                 if (i < QTest::testTags.size() && !QTest::testTags.at(i).isEmpty())
                     data = qstrdup(QTest::testTags.at(i).toLatin1().constData());
+#ifdef Q_OS_OPENHARMONY
+                qCWarning(openharmonyTestCase) << "Now Test Class:" << className
+                                               << ", Now Test Func:" << m_methods[i].name().constData()
+                                               << ", The Func Progress:" << (i + 1) << "/" << size;
+#endif
                 const bool ok = invokeTest(i, QLatin1StringView(data), watchDog.data());
                 delete [] data;
                 if (!ok)
diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp
index 9fa165c11f9..a78b412a1d5 100644
--- a/src/testlib/qtestlog.cpp
+++ b/src/testlib/qtestlog.cpp
@@ -37,6 +37,12 @@
 
 #include <vector>
 #include <memory>
+#ifdef Q_OS_OPENHARMONY
+#include "qcoreapplication.h"
+#include <hilog/log.h>
+#define APP_LOG_DOMAIN 0xf000
+#define APP_LOG_TAG "QtForOpenHarmony"
+#endif
 
 QT_BEGIN_NAMESPACE
 
@@ -234,8 +240,24 @@ namespace QTest {
             }
         }
 
+#ifdef Q_OS_OPENHARMONY
+        QString formattedMessage = qFormatLogMessage(type, context, message);
+
+        LogLevel priority = LOG_INFO;
+        switch (type) {
+        //LOG_DEBUG unable to print, temporarily use LOG_ INFO replace.
+        case QtDebugMsg: priority = LOG_INFO; break;
+        case QtInfoMsg: priority = LOG_INFO; break;
+        case QtWarningMsg: priority = LOG_WARN; break;
+        case QtCriticalMsg: priority = LOG_ERROR; break;
+        case QtFatalMsg: priority = LOG_FATAL; break;
+        };
+
+        OH_LOG_Print(LOG_APP, priority, APP_LOG_DOMAIN, APP_LOG_TAG, "%{public}s %{public}s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(formattedMessage));
+#else
         FOREACH_TEST_LOGGER
             logger->addMessage(type, context, message);
+#endif
 
         if (type == QtFatalMsg) {
              /* Right now, we're inside the custom message handler and we're
diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt
index 3d1569d51f5..f1214a28a07 100644
--- a/src/widgets/CMakeLists.txt
+++ b/src/widgets/CMakeLists.txt
@@ -320,6 +320,11 @@ qt_internal_extend_target(Widgets CONDITION WIN32
         uxtheme
 )
 
+qt_internal_extend_target(Widgets CONDITION OHOS
+    LIBRARIES
+        hitrace_ndk.z
+)
+
 qt_internal_extend_target(Widgets CONDITION QT_FEATURE_graphicseffect
     SOURCES
         effects/qgraphicseffect.cpp effects/qgraphicseffect.h effects/qgraphicseffect_p.h
diff --git a/src/widgets/accessible/itemviews.cpp b/src/widgets/accessible/itemviews.cpp
index b960cd70e23..83e4270d62c 100644
--- a/src/widgets/accessible/itemviews.cpp
+++ b/src/widgets/accessible/itemviews.cpp
@@ -1075,7 +1075,7 @@ QStringList QAccessibleTableCell::actionNames() const
 void QAccessibleTableCell::doAction(const QString& actionName)
 {
     if (actionName == toggleAction()) {
-#if defined(Q_OS_ANDROID)
+#if defined(Q_OS_ANDROID) || defined(Q_OS_OPENHARMONY)
         QAccessibleInterface *parentInterface = parent();
         while (parentInterface){
             if (parentInterface->role() == QAccessible::ComboBox) {
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
index d04bf33eec1..343047da829 100644
--- a/src/widgets/dialogs/qcolordialog.cpp
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -44,6 +44,11 @@
 #include <private/qguiapplication_p.h>
 
 #include <algorithm>
+#ifdef Q_OS_OPENHARMONY
+#include "qjsmodule.h"
+#include <private/qjspromise_p.h>
+#include <private/qopenharmony_p.h>
+#endif
 
 QT_BEGIN_NAMESPACE
 
@@ -118,7 +123,9 @@ public:
     bool handleColorPickingMouseMove(QMouseEvent *e);
     bool handleColorPickingMouseButtonRelease(QMouseEvent *e);
     bool handleColorPickingKeyPress(QKeyEvent *e);
-
+#ifdef Q_OS_OPENHARMONY
+    void imageFeaturePicker(QColorDialog *window);
+#endif
     bool canBeNativeDialog() const override;
     void setVisible(bool visible) override;
 
@@ -1609,7 +1616,9 @@ void QColorDialogPrivate::_q_newStandard(int r, int c)
 void QColorDialogPrivate::_q_pickScreenColor()
 {
     Q_Q(QColorDialog);
-
+#ifdef Q_OS_OPENHARMONY
+    imageFeaturePicker(q);
+#else
     auto *platformServices = QGuiApplicationPrivate::platformIntegration()->services();
     if (platformServices->hasCapability(QPlatformServices::Capability::ColorPicking)) {
         if (auto *colorPicker = platformServices->colorPicker(q->windowHandle())) {
@@ -1657,6 +1666,7 @@ void QColorDialogPrivate::_q_pickScreenColor()
         q->setCurrentColor(grabScreenColor(globalPos));
         updateColorLabelText(globalPos);
     }
+#endif
 }
 
 void QColorDialogPrivate::updateColorLabelText(const QPoint &globalPos)
@@ -2294,6 +2304,56 @@ bool QColorDialogPrivate::handleColorPickingKeyPress(QKeyEvent *e)
     return true;
 }
 
+#ifdef Q_OS_OPENHARMONY
+void QColorDialogPrivate::imageFeaturePicker(QColorDialog *dialog)
+{
+    if (!dialog) {
+        return;
+    }
+    QPoint center;
+    QScreen *screen = dialog->screen();
+    if (screen) {
+        QRect screenGeometry = screen->geometry();
+        qreal dpr = screen->devicePixelRatio();
+
+        center = screenGeometry.center();
+        center = QPoint(center.x() * dpr, center.y() * dpr);
+    }
+    else
+    {
+        return;
+    }
+
+    auto pickeColor = QtOh::runOnJsUIThreadWithPromise<QColor>([center](auto p){
+        auto imageFeaturePicker = QJsModule(QString::fromUtf8("@hms.officeservice.imageFeaturePicker"));
+        Napi::Value result = imageFeaturePicker.call(QString::fromUtf8("pickForResult"),
+                                                     {   Napi::Number::New(imageFeaturePicker.env(),center.x()),
+                                                         Napi::Number::New(imageFeaturePicker.env(),center.y())});
+        if (!result.IsPromise()) {
+            p->set_value(Qt::white);
+            return;
+        }
+        QJsPromise promise(result.As<Napi::Promise>());
+        promise.onThen([p](const Napi::CallbackInfo& info){
+            if (info.Length() < 1) {
+                p->set_value(Qt::white);
+                return ;
+            }
+            Napi::Object PickedColorInfo = info[0].As<Napi::Object>();
+            Napi::Object color = PickedColorInfo.Get("color").As<Napi::Object>();
+            QColor pickeColor(color.Get("red").As<Napi::Number>().Int32Value(),
+                              color.Get("green").As<Napi::Number>().Int32Value(),
+                              color.Get("blue").As<Napi::Number>().Int32Value(),
+                              color.Get("alpha").As<Napi::Number>().Int32Value());
+
+            p->set_value(pickeColor);
+
+        }).onCatch([p](const Napi::CallbackInfo& info){ Q_UNUSED(info); p->set_value(Qt::white); });
+    });
+    dialog->setCurrentColor(pickeColor);
+}
+#endif
+
 /*!
   Closes the dialog and sets its result code to \a result. If this dialog
   is shown with exec(), done() causes the local event loop to finish,
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index 32396418ab2..09f80555f32 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -1222,6 +1222,16 @@ QList<QUrl> QFileDialogPrivate::userSelectedFiles() const
     return files;
 }
 
+#ifdef Q_OS_OPENHARMONY
+QList<QUrl> QFileDialogPrivate::userSelectedUris() const
+{
+    if (!usingWidgets())
+        return addDefaultSuffixToUrls(selectedUris_sys());
+
+    return QList<QUrl>();
+}
+#endif
+
 QStringList QFileDialogPrivate::addDefaultSuffixToFiles(const QStringList &filesToFix) const
 {
     QStringList files;
@@ -1316,6 +1326,18 @@ QList<QUrl> QFileDialog::selectedUrls() const
     }
 }
 
+#ifdef Q_OS_OPENHARMONY
+QList<QUrl> QFileDialog::selectedUris() const
+{
+    Q_D(const QFileDialog);
+    if (d->nativeDialogInUse) {
+        return d->userSelectedUris();
+    }
+
+    return QList<QUrl>();
+}
+#endif
+
 /*
     Makes a list of filters from ;;-separated text.
     Used by the mac and windows implementations
@@ -2144,6 +2166,35 @@ QUrl QFileDialog::getOpenFileUrl(QWidget *parent,
     return QUrl();
 }
 
+#ifdef Q_OS_OPENHARMONY
+QUrl QFileDialog::getOpenFileUri(QWidget *parent,
+                                 const QString &caption,
+                                 const QUrl &dir,
+                                 const QString &filter,
+                                 QString *selectedFilter,
+                                 Options options,
+                                 const QStringList &supportedSchemes)
+{
+    QFileDialogArgs args(dir);
+    args.parent = parent;
+    args.caption = caption;
+    args.filter = filter;
+    args.mode = ExistingFile;
+    args.options = options;
+
+    QFileDialog dialog(args);
+    dialog.setSupportedSchemes(supportedSchemes);
+    if (selectedFilter && !selectedFilter->isEmpty())
+        dialog.selectNameFilter(*selectedFilter);
+    if (dialog.exec() == QDialog::Accepted) {
+        if (selectedFilter)
+            *selectedFilter = dialog.selectedNameFilter();
+        return dialog.selectedUris().value(0);
+    }
+    return QUrl();
+}
+#endif
+
 /*!
     This is a convenience static function that will return one or more existing
     files selected by the user.
@@ -2914,8 +2965,9 @@ void QFileDialogPrivate::init(const QFileDialogArgs &args)
     if (!nativeDialogInUse)
         createWidgets();
     q->setFileMode(QFileDialog::AnyFile);
-    if (!args.filter.isEmpty())
+    if (!args.filter.isEmpty()){
         q->setNameFilter(args.filter);
+    }
     // QTBUG-70798, prevent the default blocking the restore logic.
     const bool dontStoreDir = !args.directory.isValid() && !lastVisitedDir()->isValid();
     q->setDirectoryUrl(args.directory);
diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h
index 970bddb3595..d95b175965d 100644
--- a/src/widgets/dialogs/qfiledialog.h
+++ b/src/widgets/dialogs/qfiledialog.h
@@ -77,6 +77,9 @@ public:
 
     void selectUrl(const QUrl &url);
     QList<QUrl> selectedUrls() const;
+#ifdef Q_OS_OPENHARMONY
+    QList<QUrl> selectedUris() const;
+#endif
 
     void setNameFilter(const QString &filter);
     void setNameFilters(const QStringList &filters);
@@ -171,6 +174,16 @@ public:
                                Options options = Options(),
                                const QStringList &supportedSchemes = QStringList());
 
+#ifdef Q_OS_OPENHARMONY
+    static QUrl getOpenFileUri(QWidget *parent = nullptr,
+                               const QString &caption = QString(),
+                               const QUrl &dir = QUrl(),
+                               const QString &filter = QString(),
+                               QString *selectedFilter = nullptr,
+                               Options options = Options(),
+                               const QStringList &supportedSchemes = QStringList());
+#endif
+
     static QString getSaveFileName(QWidget *parent = nullptr,
                                    const QString &caption = QString(),
                                    const QString &dir = QString(),
diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h
index 0067a900616..8e5cf9b2138 100644
--- a/src/widgets/dialogs/qfiledialog_p.h
+++ b/src/widgets/dialogs/qfiledialog_p.h
@@ -101,6 +101,9 @@ public:
     QString getEnvironmentVariable(const QString &string);
     QStringList typedFiles() const;
     QList<QUrl> userSelectedFiles() const;
+#ifdef Q_OS_OPENHARMONY
+    QList<QUrl> userSelectedUris() const;
+#endif
     QStringList addDefaultSuffixToFiles(const QStringList &filesToFix) const;
     QList<QUrl> addDefaultSuffixToUrls(const QList<QUrl> &urlsToFix) const;
     bool removeDirectory(const QString &path);
@@ -228,6 +231,9 @@ public:
     inline QUrl directory_sys() const;
     inline void selectFile_sys(const QUrl &filename);
     inline QList<QUrl> selectedFiles_sys() const;
+#ifdef Q_OS_OPENHARMONY
+    inline QList<QUrl> selectedUris_sys() const;
+#endif
     inline void setFilter_sys();
     inline void selectMimeTypeFilter_sys(const QString &filter);
     inline QString selectedMimeTypeFilter_sys() const;
@@ -372,6 +378,15 @@ QList<QUrl> QFileDialogPrivate::selectedFiles_sys() const
     return QList<QUrl>();
 }
 
+#ifdef Q_OS_OPENHARMONY
+QList<QUrl> QFileDialogPrivate::selectedUris_sys() const
+{
+    if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
+        return helper->selectedUris();
+    return QList<QUrl>();
+}
+#endif
+
 void QFileDialogPrivate::setFilter_sys()
 {
     if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp
index 76411adaf0f..c6711e14943 100644
--- a/src/widgets/kernel/qlayout.cpp
+++ b/src/widgets/kernel/qlayout.cpp
@@ -497,6 +497,9 @@ static bool removeWidgetRecursively(QLayoutItem *li, QObject *w)
 
 void QLayoutPrivate::doResize()
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QLayoutPrivate::doResize");
+#endif
     Q_Q(QLayout);
     QWidget *mw = q->parentWidget();
     QRect rect = mw->testAttribute(Qt::WA_LayoutOnEntireRect) ? mw->rect() : mw->contentsRect();
@@ -993,6 +996,9 @@ void QLayout::update()
 */
 bool QLayout::activate()
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QLayout::activate");
+#endif
     Q_D(QLayout);
     if (!d->enabled || !parent())
         return false;
diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp
index 4effc1a2d15..1a3cda13d4e 100644
--- a/src/widgets/kernel/qstandardgestures.cpp
+++ b/src/widgets/kernel/qstandardgestures.cpp
@@ -161,14 +161,26 @@ QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state,
             } else {
                 d->lastCenterPoint = d->centerPoint;
             }
+#ifdef Q_OS_OPENHARMONY
+            if (d->centerPoint != centerPoint) {
+                d->centerPoint = centerPoint;
+                d->changeFlags |= QPinchGesture::CenterPointChanged;
+            }
+#else
             d->centerPoint = centerPoint;
 
             d->changeFlags |= QPinchGesture::CenterPointChanged;
-
+#endif
             if (d->isNewSequence) {
                 d->scaleFactor = 1.0;
                 d->lastScaleFactor = 1.0;
             } else {
+#ifdef Q_OS_OPENHARMONY
+                if (!qFuzzyCompare(1.0 + d->lastScaleFactor, 1.0 + d->scaleFactor)) {
+                    d->totalScaleFactor = d->totalScaleFactor * d->scaleFactor;
+                    d->changeFlags |= QPinchGesture::ScaleFactorChanged;
+                }
+#endif
                 d->lastScaleFactor = d->scaleFactor;
                 QLineF line(p1.globalPosition(), p2.globalPosition());
                 QLineF lastLine(p1.globalLastPosition(),  p2.globalLastPosition());
@@ -177,9 +189,10 @@ QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state,
                     return QGestureRecognizer::Ignore;
                 d->scaleFactor = newScaleFactor;
             }
+#ifndef Q_OS_OPENHARMONY
             d->totalScaleFactor = d->totalScaleFactor * d->scaleFactor;
             d->changeFlags |= QPinchGesture::ScaleFactorChanged;
-
+#endif
             qreal angle = QLineF(p1.globalPosition(), p2.globalPosition()).angle();
             if (angle > 180)
                 angle -= 360;
@@ -190,11 +203,22 @@ QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state,
             if (d->isNewSequence)
                 d->lastRotationAngle = 0.0;
             else
+#ifdef Q_OS_OPENHARMONY
+            {
+                if (!qFuzzyCompare(1.0 + d->lastRotationAngle, 1.0 + d->rotationAngle)) {
+                    d->lastRotationAngle = d->rotationAngle;
+                    d->totalRotationAngle += d->rotationAngle - d->lastRotationAngle;
+                    d->changeFlags |= QPinchGesture::RotationAngleChanged;
+                }
+            }
+#else
                 d->lastRotationAngle = d->rotationAngle;
+#endif
             d->rotationAngle = rotationAngle;
+#ifndef Q_OS_OPENHARMONY
             d->totalRotationAngle += d->rotationAngle - d->lastRotationAngle;
             d->changeFlags |= QPinchGesture::RotationAngleChanged;
-
+#endif
             d->totalChangeFlags |= d->changeFlags;
             d->isNewSequence = false;
             result = QGestureRecognizer::TriggerGesture;
diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp
index ed91ed1d0a3..212ae4d5a29 100644
--- a/src/widgets/kernel/qtooltip.cpp
+++ b/src/widgets/kernel/qtooltip.cpp
@@ -372,7 +372,11 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
 
         p += offset;
 
+#ifdef Q_OS_OPENHARMONY
+        QRect screenRect = screen->availableGeometry();
+#else
         QRect screenRect = screen->geometry();
+#endif
         if (p.x() + this->width() > screenRect.x() + screenRect.width())
         p.rx() -= 4 + this->width();
         if (p.y() + this->height() > screenRect.y() + screenRect.height())
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 760fa7fa2f6..bb4c72bcdc3 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -1155,6 +1155,9 @@ bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outCo
 
 void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWidget::create");
+#endif
     Q_UNUSED(initializeWindow);
     Q_UNUSED(destroyOldWindow);
 
@@ -1754,6 +1757,9 @@ QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst
 
 void QWidgetPrivate::syncBackingStore()
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWidgetPrivate::syncBackingStore");
+#endif
     if (shouldPaintOnScreen()) {
         paintOnScreen(dirty);
         dirty = QRegion();
@@ -4786,6 +4792,9 @@ void QWidgetPrivate::resolveFont()
 */
 void QWidgetPrivate::updateFont(const QFont &font)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWidgetPrivate::updateFont");
+#endif
     Q_Q(QWidget);
 #ifndef QT_NO_STYLE_STYLESHEET
     const QStyleSheetStyle* cssStyle;
@@ -5455,6 +5464,9 @@ void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset
 void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
                                 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWidgetPrivate::drawWidget");
+#endif
     if (rgn.isEmpty())
         return;
 
@@ -5641,6 +5653,9 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
 
 void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("sendPaintEvent");
+#endif
     Q_Q(QWidget);
     QPaintEvent e(toBePainted);
     QCoreApplication::sendSpontaneousEvent(q, &e);
@@ -5725,6 +5740,9 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis
                                             const QPoint &offset, DrawWidgetFlags flags
                                             , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("paintSiblingsRecursive");
+#endif
     QWidget *w = nullptr;
     QRect boundingRect;
     bool dirtyBoundingRect = true;
@@ -8030,6 +8048,9 @@ void QWidgetPrivate::activateChildLayoutsRecursively()
 
 void QWidgetPrivate::show_helper()
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWidgetPrivate::show_helper");
+#endif
     Q_Q(QWidget);
     data.in_show = true; // qws optimization
     // make sure we receive pending move and resize events
@@ -8114,6 +8135,9 @@ void QWidgetPrivate::show_helper()
 
 void QWidgetPrivate::show_sys()
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWidgetPrivate::show_sys");
+#endif
     Q_Q(QWidget);
 
     auto window = qobject_cast<QWidgetWindow *>(windowHandle());
@@ -8322,6 +8346,9 @@ void QWidget::setVisible(bool visible)
 // the other hand keeps track of WA_WState_ExplicitShowHide in addition.
 void QWidgetPrivate::setVisible(bool visible)
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWidgetPrivate::setVisible");
+#endif
     Q_Q(QWidget);
     if (visible) { // show
         // Designer uses a trick to make grabWidget work without showing
@@ -8536,7 +8563,17 @@ bool QWidgetPrivate::handleClose(CloseMode mode)
         mode = CloseNoEvent;
 
     if (mode != CloseNoEvent) {
+#ifdef Q_OS_OPENHARMONY
+#if OHOS_SDK_VERSION >= 15
+        QVariant reason = that->property("_qohclosereason");
+        QCloseEvent e(reason.isValid() ? QCloseEvent::CloseReason(reason.toInt()) : QCloseEvent::InternalClose);
+#else
+        QCloseEvent e;
+#endif
+#else
         QCloseEvent e;
+#endif
+
         if (mode == CloseWithSpontaneousEvent)
             QApplication::sendSpontaneousEvent(q, &e);
         else
@@ -11101,6 +11138,9 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
 
 void QWidget::repaint()
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWidget::repaint");
+#endif
     repaint(rect());
 }
 
@@ -11179,6 +11219,9 @@ void QWidgetPrivate::repaint(T r)
 */
 void QWidget::update()
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWidget::update");
+#endif
     update(rect());
 }
 
diff --git a/src/widgets/kernel/qwidgetrepaintmanager.cpp b/src/widgets/kernel/qwidgetrepaintmanager.cpp
index 514667ed818..2135e756248 100644
--- a/src/widgets/kernel/qwidgetrepaintmanager.cpp
+++ b/src/widgets/kernel/qwidgetrepaintmanager.cpp
@@ -361,7 +361,12 @@ void QWidgetRepaintManager::sendUpdateRequest(QWidget *widget, UpdateTime update
         // normal backingstore sync machinery.
         if (!widget->d_func()->shouldPaintOnScreen())
             updateRequestSent = true;
+#ifdef Q_OS_OPENHARMONY
+        // most important on openharmony
+        QCoreApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::HighEventPriority + 1);
+#else
         QCoreApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
+#endif
         break;
     case UpdateNow: {
         QEvent event(QEvent::UpdateRequest);
@@ -703,6 +708,9 @@ static bool isDrawnInEffect(const QWidget *w)
 
 void QWidgetRepaintManager::paintAndFlush()
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWidgetRepaintManager::paintAndFlush");
+#endif
     qCInfo(lcWidgetPainting) << "Painting and flushing dirty"
         << "top level" << dirty << "and dirty widgets" << dirtyWidgets;
 
@@ -901,6 +909,9 @@ void QWidgetRepaintManager::paintAndFlush()
 
     // Paint the rest with composition.
     if (repaintAllWidgets || !dirtyCopy.isEmpty()) {
+#ifdef Q_OS_OPENHARMONY
+        HiTracer tracer2("Paint the rest with composition");
+#endif
         QWidgetPrivate::DrawWidgetFlags flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive
                 | QWidgetPrivate::UseEffectRegionBounds;
         tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, QPoint(), flags, nullptr, this);
@@ -968,6 +979,9 @@ void QWidgetRepaintManager::markNeedsFlush(QWidget *widget, const QRegion &regio
 */
 void QWidgetRepaintManager::flush()
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("QWidgetRepaintManager::flush");
+#endif
     qCInfo(lcWidgetPainting) << "Flushing top level"
         << topLevelNeedsFlush << "and children" << needsFlushWidgets;
 
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index ce4573f46d3..21a40b09224 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -819,6 +819,11 @@ void QWidgetWindow::handleResizeEvent(QResizeEvent *event)
 void QWidgetWindow::closeEvent(QCloseEvent *event)
 {
     Q_D(QWidgetWindow);
+#ifdef Q_OS_OPENHARMONY
+#if OHOS_SDK_VERSION >= 15
+    m_widget->setProperty("_qohclosereason", event->closeReason());
+#endif
+#endif
     bool accepted = m_widget->d_func()->handleClose(d->inClose ? QWidgetPrivate::CloseWithEvent
                                                                   : QWidgetPrivate::CloseWithSpontaneousEvent);
     event->setAccepted(accepted);
@@ -1124,10 +1129,15 @@ void QWidgetWindow::handleGestureEvent(QNativeGestureEvent *e)
 #ifndef QT_NO_CONTEXTMENU
 void QWidgetWindow::handleContextMenuEvent(QContextMenuEvent *e)
 {
+#ifdef Q_OS_OPENHARMONY
+    if (e->reason() != QContextMenuEvent::TouchScreen)
+        return;
+#else
     // We are only interested in keyboard originating context menu events here,
     // mouse originated context menu events for widgets are generated in mouse handling methods.
     if (e->reason() != QContextMenuEvent::Keyboard)
         return;
+#endif
 
     QWidget *fw = QWidget::keyboardGrabber();
     if (!fw) {
@@ -1143,8 +1153,13 @@ void QWidgetWindow::handleContextMenuEvent(QContextMenuEvent *e)
     }
     if (fw && fw->isEnabled()) {
         QPoint pos = fw->inputMethodQuery(Qt::ImCursorRectangle).toRect().center();
+#ifdef Q_OS_OPENHARMONY
+        QContextMenuEvent widgetEvent(QContextMenuEvent::TouchScreen, pos, fw->mapToGlobal(pos),
+                                      e->modifiers());
+#else
         QContextMenuEvent widgetEvent(QContextMenuEvent::Keyboard, pos, fw->mapToGlobal(pos),
                                       e->modifiers());
+#endif
         QGuiApplication::forwardEvent(fw, &widgetEvent, e);
     }
 }
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index a040516360f..208d250b1da 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -187,6 +187,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
         }
         break; }
     case PE_FrameFocusRect:
+#ifndef Q_OS_OPENHARMONY
         if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(opt)) {
             QColor bg = fropt->backgroundColor;
             QPen oldPen = p->pen();
@@ -204,6 +205,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
             p->drawRect(focusRect.adjusted(0, 0, -1, -1)); //draw pen inclusive
             p->setPen(oldPen);
         }
+#endif
         break;
     case PE_IndicatorMenuCheckMark: {
         const int markW = opt->rect.width() > 7 ? 7 : opt->rect.width();
@@ -574,7 +576,9 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
 #endif // QT_CONFIG(spinbox)
     case PE_PanelTipLabel: {
         const QBrush brush(opt->palette.toolTipBase());
+#ifndef Q_OS_OPENHARMONY
         qDrawPlainRect(p, opt->rect, opt->palette.toolTipText().color(), 1, &brush);
+#endif
         break;
     }
 #if QT_CONFIG(tabbar)
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index e48e17ed3b9..d542b83c2df 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -533,13 +533,17 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid
         ret = 0;
         break;
 
-#if defined(Q_OS_WIN)
+#if defined(Q_OS_WIN) || defined(Q_OS_OPENHARMONY)
     case SH_UnderlineShortcut:
     {
+#ifdef Q_OS_OPENHARMONY
+        ret = 0;
+#else
         ret = 1;
         BOOL cues = false;
         SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &cues, 0);
         ret = int(cues);
+#endif
         // Do nothing if we always paint underlines
         Q_D(const QWindowsStyle);
         if (!ret && widget && d) {
diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp
index 2a55f014e12..82472d72f99 100644
--- a/src/widgets/util/qsystemtrayicon.cpp
+++ b/src/widgets/util/qsystemtrayicon.cpp
@@ -137,6 +137,15 @@ QSystemTrayIcon::QSystemTrayIcon(const QIcon &icon, QObject *parent)
     setIcon(icon);
 }
 
+#ifdef Q_OS_OPENHARMONY
+QSystemTrayIcon::QSystemTrayIcon(const QIcon &iconLight, const QIcon &iconDark, QObject *parent)
+    : QSystemTrayIcon(parent)
+{
+    setIcon(iconLight, Light);
+    setIcon(iconDark, Dark);
+}
+#endif
+
 /*!
     Removes the icon from the system tray and frees all allocated resources.
 */
@@ -202,6 +211,26 @@ QMenu* QSystemTrayIcon::contextMenu() const
     On Windows, the system tray icon size is 16x16; on X11, the preferred size is
     22x22. The icon will be scaled to the appropriate size as necessary.
 */
+#ifdef Q_OS_OPENHARMONY
+void QSystemTrayIcon::setIcon(const QIcon &icon, IconTheme them)
+{
+    Q_D(QSystemTrayIcon);
+    if (them == Light)
+        d->iconLight = icon;
+    else
+        d->iconDark = icon;
+    d->updateIcon_sys();
+}
+
+QIcon QSystemTrayIcon::icon(IconTheme them) const
+{
+    Q_D(const QSystemTrayIcon);
+    if (them == Light)
+        return d->iconLight;
+    else
+        return d->iconDark;
+}
+#else
 void QSystemTrayIcon::setIcon(const QIcon &icon)
 {
     Q_D(QSystemTrayIcon);
@@ -214,6 +243,7 @@ QIcon QSystemTrayIcon::icon() const
     Q_D(const QSystemTrayIcon);
     return d->icon;
 }
+#endif
 
 /*!
     \property QSystemTrayIcon::toolTip
@@ -277,7 +307,11 @@ void QSystemTrayIcon::setVisible(bool visible)
     Q_D(QSystemTrayIcon);
     if (visible == d->visible)
         return;
+#ifdef Q_OS_OPENHARMONY
+    if (Q_UNLIKELY(visible && d->iconLight.isNull() && d->iconDark.isNull()))
+#else
     if (Q_UNLIKELY(visible && d->icon.isNull()))
+#endif
         qWarning("QSystemTrayIcon::setVisible: No Icon set");
     d->visible = visible;
     if (d->visible)
diff --git a/src/widgets/util/qsystemtrayicon.h b/src/widgets/util/qsystemtrayicon.h
index 0a77ba03b7a..4896c0df3ff 100644
--- a/src/widgets/util/qsystemtrayicon.h
+++ b/src/widgets/util/qsystemtrayicon.h
@@ -32,6 +32,9 @@ class Q_WIDGETS_EXPORT QSystemTrayIcon : public QObject
 public:
     QSystemTrayIcon(QObject *parent = nullptr);
     QSystemTrayIcon(const QIcon &icon, QObject *parent = nullptr);
+#ifdef Q_OS_OPENHARMONY
+    QSystemTrayIcon(const QIcon &iconLight, const QIcon &iconDark, QObject *parent = nullptr);
+#endif
     ~QSystemTrayIcon();
 
     enum ActivationReason {
@@ -42,13 +45,25 @@ public:
         MiddleClick
     };
 
+#ifdef Q_OS_OPENHARMONY
+    enum IconTheme {
+        Dark,
+        Light
+    };
+#endif
+
 #if QT_CONFIG(menu)
     void setContextMenu(QMenu *menu);
     QMenu *contextMenu() const;
 #endif
 
+#ifdef Q_OS_OPENHARMONY
+    QIcon icon(IconTheme them = Light) const;
+    void setIcon(const QIcon &icon, IconTheme them = Light);
+#else
     QIcon icon() const;
     void setIcon(const QIcon &icon);
+#endif
 
     QString toolTip() const;
     void setToolTip(const QString &tip);
diff --git a/src/widgets/util/qsystemtrayicon_p.h b/src/widgets/util/qsystemtrayicon_p.h
index 5f9509df4db..a3def9748b0 100644
--- a/src/widgets/util/qsystemtrayicon_p.h
+++ b/src/widgets/util/qsystemtrayicon_p.h
@@ -63,7 +63,12 @@ public:
     void _q_emitActivated(QPlatformSystemTrayIcon::ActivationReason reason);
 
     QPointer<QMenu> menu;
+#ifdef Q_OS_OPENHARMONY
+    QIcon iconLight;
+    QIcon iconDark;
+#else
     QIcon icon;
+#endif
     QString toolTip;
     QSystemTrayIconSys *sys;
     QPlatformSystemTrayIcon *qpa_sys;
diff --git a/src/widgets/util/qsystemtrayicon_qpa.cpp b/src/widgets/util/qsystemtrayicon_qpa.cpp
index 63b24873db3..256086f09d0 100644
--- a/src/widgets/util/qsystemtrayicon_qpa.cpp
+++ b/src/widgets/util/qsystemtrayicon_qpa.cpp
@@ -53,7 +53,11 @@ QRect QSystemTrayIconPrivate::geometry_sys() const
 void QSystemTrayIconPrivate::updateIcon_sys()
 {
     if (qpa_sys)
+#ifdef Q_OS_OPENHARMONY
+        qpa_sys->updateIcon(iconLight, iconDark);
+#else
         qpa_sys->updateIcon(icon);
+#endif
 }
 
 void QSystemTrayIconPrivate::updateMenu_sys()
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index e534501cb7d..b77e80582fc 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -1002,7 +1002,7 @@ bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event)
             && (event->position().toPoint() - state->pressPos).manhattanLength()
                 > QApplication::startDragDistance()) {
 
-#ifdef Q_OS_MACOS
+#if defined(Q_OS_MACOS) || defined(Q_OS_OPENHARMONY)
             if (windowHandle() && !q->isFloating()) {
                 // When using native widgets on mac, we have not yet been successful in
                 // starting a drag on an NSView that belongs to one window (QMainWindow),
@@ -1130,13 +1130,13 @@ void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event)
             if (state == nullptr || !state->dragging)
                 break;
 
-#if !defined(Q_OS_MAC) && !defined(Q_OS_WASM)
+#if !defined(Q_OS_MAC) && !defined(Q_OS_WASM) && !defined(Q_OS_OPENHARMONY)
             if (state->nca)
                 endDrag(EndDragMode::LocationChange);
 #endif
             break;
         case QEvent::NonClientAreaMouseButtonRelease:
-#if defined(Q_OS_MAC) || defined(Q_OS_WASM)
+#if defined(Q_OS_MAC) || defined(Q_OS_WASM) || defined(Q_OS_OPENHARMONY)
                         if (state)
                             endDrag(EndDragMode::LocationChange);
 #endif
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 6d0bc307df1..05f7df6a4af 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -2903,8 +2903,13 @@ void QMenu::mousePressEvent(QMouseEvent *e)
     }
     QMenuPrivate::mouseDown = this;
 
-    QAction *action = d->actionAt(e->position().toPoint());
+    QAction *action = d->actionAt(e->pos());
+#ifdef Q_OS_OPENHARMONY
+    /* NOTE 延迟窗口创建,避免touch事件传递到错误窗口 */
+    d->setCurrentAction(action, 200);
+#else
     d->setCurrentAction(action, 20);
+#endif
     update();
 }
 
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 0a6fc80ba7d..b45af12cc6e 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -705,6 +705,9 @@ QAction *QMenuBarPrivate::getNextAction(const int _start, const int increment) c
 */
 QMenuBar::QMenuBar(QWidget *parent) : QWidget(*new QMenuBarPrivate, parent, { })
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("new QMenuBar");
+#endif
     Q_D(QMenuBar);
     d->init();
 }
diff --git a/src/widgets/widgets/qstatusbar.cpp b/src/widgets/widgets/qstatusbar.cpp
index d526f93a3b2..3cccd705dc6 100644
--- a/src/widgets/widgets/qstatusbar.cpp
+++ b/src/widgets/widgets/qstatusbar.cpp
@@ -191,6 +191,9 @@ QRect QStatusBarPrivate::messageRect() const
 QStatusBar::QStatusBar(QWidget * parent)
     : QWidget(*new QStatusBarPrivate, parent, { })
 {
+#ifdef Q_OS_OPENHARMONY
+    HiTracer tracer("new QStatusBar");
+#endif
     Q_D(QStatusBar);
     d->box = nullptr;
     d->timer = nullptr;
diff --git a/src/widgets/widgets/qtextbrowser.cpp b/src/widgets/widgets/qtextbrowser.cpp
index 1cac46e8a80..927e665573a 100644
--- a/src/widgets/widgets/qtextbrowser.cpp
+++ b/src/widgets/widgets/qtextbrowser.cpp
@@ -144,6 +144,11 @@ QString QTextBrowserPrivate::findFile(const QUrl &name) const
         if (name.scheme() == "assets"_L1)
             fileName = "assets:"_L1 + name.path();
         else
+#endif
+#if defined(Q_OS_OPENHARMONY)
+            if (name.scheme() == "rawfile"_L1)
+                fileName = "rawfile:"_L1 + name.path();
+            else
 #endif
             fileName = name.toLocalFile();
     }
@@ -215,7 +220,10 @@ void QTextBrowserPrivate::_q_activateAnchor(const QString &href)
 #if defined(Q_OS_ANDROID)
             || url.scheme() == "assets"_L1
 #endif
-            || url.scheme() == "qrc"_L1;
+#if defined(Q_OS_OPENHARMONY)
+            || url.scheme() == "rawfile"_L1
+#endif
+            || url.scheme() == QLatin1String("qrc");
     if ((openExternalLinks && !isFileScheme && !url.isRelative())
         || (url.isRelative() && !currentURL.isRelative() && !isFileScheme)) {
         QDesktopServices::openUrl(url);
diff --git a/sync.profile b/sync.profile
index bc85d0e3b29..229faac641d 100644
--- a/sync.profile
+++ b/sync.profile
@@ -33,6 +33,7 @@
     "QtMockStaticResources1" => "$basedir/tests/auto/cmake/test_static_resources/mock_static_resources1",
     "QtTestAutogeneratingCppExports" => "$basedir/tests/auto/cmake/test_generating_cpp_exports/test_autogenerating_cpp_exports",
     "QtTestAutogeneratingCppExportsCustomName" => "$basedir/tests/auto/cmake/test_generating_cpp_exports/test_autogenerating_cpp_exports_custom_name",
+    "QtNapi" => "!>$basedir/src/corelib;$basedir/src/3rdparty/node-addon-api",
 );
 %moduleheaders = ( # restrict the module headers to those found in relative path
     "QtEglFSDeviceIntegration" => "api",
@@ -76,8 +77,9 @@
 my @internal_zlib_headers = ( "crc32.h", "deflate.h", "gzguts.h", "inffast.h", "inffixed.h", "inflate.h", "inftrees.h", "trees.h", "zutil.h" );
 my @zlib_headers = ( "zconf.h", "zlib.h" );
 @ignore_headers = ( @internal_zlib_headers );
-@ignore_for_include_check = ( "qsystemdetection.h", "qcompilerdetection.h", "qprocessordetection.h", @zlib_headers);
-@ignore_for_qt_begin_namespace_check = ( "qt_windows.h", @zlib_headers);
+my @napi_headers = ( "napi.h", "napi-inl.h", "napi-inl.deprecated.h" );
+@ignore_for_include_check = ( "qsystemdetection.h", "qcompilerdetection.h", "qprocessordetection.h", @zlib_headers, @napi_headers);
+@ignore_for_qt_begin_namespace_check = ( "qt_windows.h", @zlib_headers, @napi_headers);
 %inject_headers = (
     "$basedir/src/corelib/global" => [ "qconfig.h", "qconfig_p.h" ],
     "$basedir/src/gui/vulkan" => [ "^qvulkanfunctions.h", "^qvulkanfunctions_p.h" ]
diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
index bf1c165b4f1..4dda225c4f4 100644
--- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
+++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
@@ -313,7 +313,7 @@ void tst_QSettings::cleanupTestFiles()
         QSettings("HKEY_LOCAL_MACHINE\\Software\\bat", QSettings::NativeFormat).clear();
         QSettings("HKEY_LOCAL_MACHINE\\Software\\baz", QSettings::NativeFormat).clear();
     }
-#elif defined(Q_OS_DARWIN)
+#elif defined(Q_OS_DARWIN)|| defined(Q_OS_OPENHARMONY)
     QSettings(QSettings::UserScope, "software.org", "KillerAPP").clear();
     QSettings(QSettings::SystemScope, "software.org", "KillerAPP").clear();
     QSettings(QSettings::UserScope, "other.software.org", "KillerAPP").clear();
@@ -2340,7 +2340,7 @@ void tst_QSettings::fromFile()
         QCOMPARE(settings2.value("alpha").toInt(), 2);
 
         settings1.sync();
-#if !defined(Q_OS_WIN)
+#if !defined(Q_OS_WIN) && !defined(Q_OS_OPENHARMONY)
         QVERIFY(QFile::exists("foo"));
 #endif
         QCOMPARE(settings1.value("alpha").toInt(), 2);
@@ -3310,7 +3310,7 @@ void tst_QSettings::setPath()
         path checks that it has no bad side effects.
     */
     for (int i = 0; i < 2; ++i) {
-#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
+#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) && !defined(Q_OS_OPENHARMONY)
         TEST_PATH(i == 0, "conf", NativeFormat, UserScope, "alpha")
         TEST_PATH(i == 0, "conf", NativeFormat, SystemScope, "beta")
 #endif