From 4e9555e3b3a91089b3675e1429b9120c941c42d0 Mon Sep 17 00:00:00 2001 From: wanghao Date: Mon, 8 Apr 2024 09:44:33 +0800 Subject: [PATCH] =?UTF-8?q?[fix]=20=E6=9B=B4=E6=96=B0=E8=A1=A5=E4=B8=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wanghao --- patch/v5.12.12/qtbase.patch | 1885 +++++++++++++++-------- patch/v5.12.12/qtconnectivity.patch | 82 +- patch/v5.12.12/qtdeclarative.patch | 44 + patch/v5.12.12/qtmultimedia.patch | 28 +- patch/v5.12.12/qtsensors.patch | 22 +- patch/v5.15.12/qtbase.patch | 2154 ++++++++++++++++++--------- patch/v5.15.12/qtconnectivity.patch | 67 +- patch/v5.15.12/qtdeclarative.patch | 883 ++++++++++- patch/v5.15.12/qtmultimedia.patch | 28 +- patch/v5.15.12/qtsensors.patch | 22 +- 10 files changed, 3782 insertions(+), 1433 deletions(-) diff --git a/patch/v5.12.12/qtbase.patch b/patch/v5.12.12/qtbase.patch index 30e6e3a7e5..565e39c774 100644 --- a/patch/v5.12.12/qtbase.patch +++ b/patch/v5.12.12/qtbase.patch @@ -188,7 +188,7 @@ index 40528a65e2..3e563b8cc0 100644 diff --git a/mkspecs/oh-clang/qmake.conf b/mkspecs/oh-clang/qmake.conf new file mode 100644 -index 0000000000..03139d2b22 +index 0000000000..5bfd38b4f5 --- /dev/null +++ b/mkspecs/oh-clang/qmake.conf @@ -0,0 +1,39 @@ @@ -197,7 +197,7 @@ index 0000000000..03139d2b22 +QMAKE_PLATFORM = openharmony +QMAKE_COMPILER = gcc clang llvm + -+CONFIG += unversioned_soname unversioned_libname plugin_with_soname ++CONFIG += unversioned_soname unversioned_libname plugin_with_soname $$QMAKE_PLATFORM + +include(../common/linux.conf) +include(../common/gcc-base-unix.conf) @@ -686,10 +686,10 @@ index 0000000000..7480dc1c20 +#endif // QOPENHARMONYDEFINES_H diff --git a/src/corelib/kernel/qopenharmonyhelpers.cpp b/src/corelib/kernel/qopenharmonyhelpers.cpp new file mode 100644 -index 0000000000..6ac33f6a4a +index 0000000000..9d2664cae6 --- /dev/null +++ b/src/corelib/kernel/qopenharmonyhelpers.cpp -@@ -0,0 +1,129 @@ +@@ -0,0 +1,132 @@ +#include "qopenharmonyhelpers_p.h" +#include "qopenharmonyjsenvironment.h" +#include "qmutex.h" @@ -714,7 +714,7 @@ index 0000000000..6ac33f6a4a + napi_value variant_to_napi_value(const QVariant &value) + { + napi_value ret = nullptr; -+ QVariant::Type t = value.type(); ++ int t = value.userType(); + switch (t) { + case QVariant::Int: + ret = qJs::createInt32(value.toInt()); @@ -738,7 +738,7 @@ index 0000000000..6ac33f6a4a + ret = qJs::createObject(value.toMap()); + break; + default: -+ //Todo other type ++ ret = qJs::createObjectFromUserType(value); + break; + } + return ret; @@ -769,6 +769,9 @@ index 0000000000..6ac33f6a4a + case QMetaType::QByteArrayList: + ret = QVariant::fromValue(qJs::getByteArrayList(value)); + break; ++ case QMetaType::QRect: ++ ret = qJs::getRect(value); ++ break; + default: + //Todo other type + break; @@ -870,18 +873,27 @@ index 0000000000..0c0bd12c64 +#endif // QJNIHELPERS_H diff --git a/src/corelib/kernel/qopenharmonyjsenvironment.cpp b/src/corelib/kernel/qopenharmonyjsenvironment.cpp new file mode 100644 -index 0000000000..7ca972cb29 +index 0000000000..4d39fc5500 --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsenvironment.cpp -@@ -0,0 +1,395 @@ +@@ -0,0 +1,427 @@ +#include "qopenharmonyjsenvironment.h" +#include "qopenharmonydefines.h" +#include "qopenharmonyhelpers_p.h" +#include "qopenharmonyjsfunction.h" + ++#include ++ +static napi_threadsafe_function g_threadsafe_call_js_function = nullptr; +napi_env QOpenHarmonyJsEnvironment::m_env = nullptr; +bool QOpenHarmonyJsEnvironment::m_exit = false; ++static QHash g_creators; ++ ++static void cleanup_creators() ++{ ++ qDeleteAll(g_creators); ++ g_creators.clear(); ++} + +static void callJsFunction(napi_env env, napi_value js_cb, void* context, void* data) { + Q_UNUSED(env); @@ -915,6 +927,7 @@ index 0000000000..7ca972cb29 + if (g_threadsafe_call_js_function == nullptr) { + LOGW("init call js function failed"); + } ++ qAddPostRoutine(cleanup_creators); +} + +void QOpenHarmonyJsEnvironment::quit() @@ -969,6 +982,19 @@ index 0000000000..7ca972cb29 + return result; +} + ++napi_value QOpenHarmonyJsEnvironment::createObjectFromUserType(const QVariant &value) ++{ ++ if (!g_creators.contains(value.userType())) ++ return nullptr; ++ NapiValueCreator *c = g_creators.value(value.userType()); ++ return c->create(value); ++} ++ ++void QOpenHarmonyJsEnvironment::registerCreator(int type, NapiValueCreator *creator) ++{ ++ g_creators.insert(type, creator); ++} ++ +napi_value QOpenHarmonyJsEnvironment::globalObject() { + napi_value _global; + NAPI_CALL(m_env, napi_get_global(m_env, &_global)); @@ -1269,22 +1295,52 @@ index 0000000000..7ca972cb29 +{ + return getDouble(value); +} ++ ++QRect QOpenHarmonyJsEnvironment::getRect(napi_value value) ++{ ++ int64_t left = getInt64(objectPropertyValue(value, "left")); ++ int64_t top = getInt64(objectPropertyValue(value, "top")); ++ int64_t width = getInt64(objectPropertyValue(value, "width")); ++ int64_t height = getInt64(objectPropertyValue(value, "height")); ++ return QRect(left, top, width, height); ++} diff --git a/src/corelib/kernel/qopenharmonyjsenvironment.h b/src/corelib/kernel/qopenharmonyjsenvironment.h new file mode 100644 -index 0000000000..98c7f3a7d4 +index 0000000000..0718f7ee9a --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsenvironment.h -@@ -0,0 +1,121 @@ +@@ -0,0 +1,156 @@ +#ifndef QOPENHARMONYJSENVIRONMENT_H +#define QOPENHARMONYJSENVIRONMENT_H + +#include +#include ++#include + +QT_BEGIN_NAMESPACE +#define qJs QOpenHarmonyJsEnvironment +class QOpenHarmonyJsFunction; + ++struct NapiValueCreator ++{ ++ virtual napi_value create(const QVariant &value) = 0; ++ virtual ~NapiValueCreator() {} ++}; ++ ++template ++struct UserTypeNapiValueCreator : NapiValueCreator ++{ ++ UserTypeNapiValueCreator(std::function &f) : _f(f) {} ++ virtual napi_value create(const QVariant &value) ++ { ++ if (_f && value.canConvert()) { ++ return _f(value.value()); ++ } ++ return nullptr; ++ } ++ std::function _f; ++}; ++ +class Q_CORE_EXPORT QOpenHarmonyJsEnvironment +{ +public: @@ -1315,6 +1371,18 @@ index 0000000000..98c7f3a7d4 + + static napi_value createObject(const QVariantMap &map); + ++ static napi_value createObjectFromUserType(const QVariant &value); ++ ++ template ++ static void registerCreator(std::function &f) ++ { ++ int id = qMetaTypeId(); ++ NapiValueCreator *creator = new UserTypeNapiValueCreator(f); ++ registerCreator(id, creator); ++ } ++ ++ static void registerCreator(int type, NapiValueCreator *creator); ++ + static napi_value globalObject(); + + static napi_value globalThis() @@ -1361,6 +1429,8 @@ index 0000000000..98c7f3a7d4 + + static double getDouble(napi_value value); + ++ static QRect getRect(napi_value value); ++ + static napi_value objectPropertyValue(napi_value object, const QString &propertyName); + + static napi_value initJsObjectLoader(napi_env env, napi_callback_info info); @@ -1398,10 +1468,10 @@ index 0000000000..98c7f3a7d4 +#endif // QOPENHARMONYJSENVIRONMENT_H diff --git a/src/corelib/kernel/qopenharmonyjsfunction.cpp b/src/corelib/kernel/qopenharmonyjsfunction.cpp new file mode 100644 -index 0000000000..e38c6bd9e0 +index 0000000000..dbe216de8f --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsfunction.cpp -@@ -0,0 +1,206 @@ +@@ -0,0 +1,207 @@ +#include "qopenharmonyjsfunction.h" +#include "qopenharmonyjsenvironment.h" +#include "qopenharmonydefines.h" @@ -1436,11 +1506,13 @@ index 0000000000..e38c6bd9e0 + QOpenHarmonyJsObject *m_jsObject; + QVariant m_result; + int m_resultType; ++ napi_ref m_objectRef; + QBasicAtomicInt m_bResultReceived; // bool +}; + +QOpenHarmonyJsFunctionPrivate::QOpenHarmonyJsFunctionPrivate() + : m_resultType(QVariant::Invalid) ++ , m_objectRef(nullptr) +{ + m_bResultReceived.storeRelease(false); +} @@ -1465,13 +1537,13 @@ index 0000000000..e38c6bd9e0 + break; + } + if (!m_bResultReceived.loadAcquire()) { -+ qWarning() << QString("Wait js method %1 result failded").arg(m_name); ++ LOGW("Wait js method %{public}s result failded", qPrintable(m_name)); + } +} + +bool QOpenHarmonyJsFunctionPrivate::hasResult() const +{ -+ return m_resultType != QVariant::Invalid; ++ return m_resultType != QVariant::Invalid && m_resultType != QMetaType::Void; +} + +napi_value QOpenHarmonyJsFunctionPrivate::then(napi_env env, napi_callback_info info) @@ -1488,11 +1560,17 @@ index 0000000000..e38c6bd9e0 + +void QOpenHarmonyJsFunctionPrivate::setResult(napi_value result) +{ ++ if (m_resultType == QOpenHarmonyJsFunction::JsRefType) { ++ LOGI("Get js method %1 result object ref from callback: %{public}s", qPrintable(m_name)); ++ napi_create_reference(qJs::env(), result, 1, &m_objectRef); ++ m_bResultReceived.storeRelease(true); ++ return; ++ } + m_result = QtHarmonyPrivate::napi_value_to_variant(result, m_resultType); + if (m_result.type() == QVariant::ByteArray) { -+ qDebug() << QString("Get js method %1 result from callback QByteArrary length: %2").arg(m_name).arg(m_result.toByteArray().length()); ++ LOGI("Get js method %{public}s result from callback QByteArrary length: %{public}d", qPrintable(m_name), m_result.toByteArray().length()); + } else { -+ qDebug() << QString("Get js method %1 result from callback:").arg(m_name) << m_result; ++ LOGI("Get js method %{public}s result from callback: %{public}s", qPrintable(m_name), qPrintable(m_result.toString())); + } + m_bResultReceived.storeRelease(true); +} @@ -1529,7 +1607,7 @@ index 0000000000..e38c6bd9e0 + napi_is_promise(qJs::env(), result, &is_promise); + napi_valuetype type; + napi_typeof(qJs::env(), result, &type); -+ qDebug() << "the result type is" << type << "the result is promise:" << is_promise; ++ LOGI("the result type is %{public}d the result is promise: %{public}d", type, is_promise); + if (is_promise) { + napi_value then = qJs::objectPropertyValue(result, "then"); + napi_value func = nullptr; @@ -1551,19 +1629,7 @@ index 0000000000..e38c6bd9e0 +{ + d_ptr->m_bResultReceived.storeRelease(false); + d_ptr->m_args = args; -+ bool printArgs = !args.isEmpty(); -+ for (int i = 0 ;i < args.count(); ++i) { -+ if (args.at(i).type() == QMetaType::QByteArray) { -+ printArgs = false; -+ break; -+ } -+ } -+ if (printArgs) { -+ qDebug() << QString("call js function: %1").arg(d_ptr->m_name) << args; -+ } else { -+ qDebug() << QString("call js function: %1").arg(d_ptr->m_name); -+ } -+ ++ LOGI("call js function %{public}s", qPrintable(d_ptr->m_name)); + if (!qJs::callThreadSafeFunction(this)) + return; + if (!d_ptr->hasResult()) { @@ -1578,9 +1644,14 @@ index 0000000000..e38c6bd9e0 + return d_ptr->m_result; +} + -+napi_value QOpenHarmonyJsFunction::attachedObject() const ++napi_ref QOpenHarmonyJsFunction::refResult() const +{ + Q_D(const QOpenHarmonyJsFunction); ++ return d->m_objectRef; ++} ++ ++napi_value QOpenHarmonyJsFunction::attachedObject() const { ++ Q_D(const QOpenHarmonyJsFunction); + return d->m_jsObject->jsObject(); +} + @@ -1610,10 +1681,10 @@ index 0000000000..e38c6bd9e0 +QT_END_NAMESPACE diff --git a/src/corelib/kernel/qopenharmonyjsfunction.h b/src/corelib/kernel/qopenharmonyjsfunction.h new file mode 100644 -index 0000000000..4c982d1784 +index 0000000000..17fb051a7b --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsfunction.h -@@ -0,0 +1,84 @@ +@@ -0,0 +1,94 @@ +#ifndef QOPENHARMONYJSFUNCTION_H +#define QOPENHARMONYJSFUNCTION_H + @@ -1633,8 +1704,16 @@ index 0000000000..4c982d1784 +{ + Q_DECLARE_PRIVATE(QOpenHarmonyJsFunction) +public: ++ enum { JsRefType = QMetaType::User + 1000 }; + ~QOpenHarmonyJsFunction(); + ++ template ++ void callReturnRef(Args &&...args) { ++ QVariantList params; ++ setResultType(JsRefType); ++ call(packParams(params, std::forward(args)...)); ++ } ++ + template + void call(Args&&... args) + { @@ -1644,7 +1723,7 @@ index 0000000000..4c982d1784 + } + + template -+ void call(Args&&... args) ++ void callWithoutReturn(Args&&... args) + { + QVariantList params; + call(packParams(params, std::forward(args)...)); @@ -1657,6 +1736,8 @@ index 0000000000..4c982d1784 + + QVariant jsResult() const; + ++ napi_ref refResult() const; ++ + napi_value attachedObject() const; + + QString name() const; @@ -1805,10 +1886,10 @@ index 0000000000..1680e85b69 + diff --git a/src/corelib/kernel/qopenharmonyjsobject.h b/src/corelib/kernel/qopenharmonyjsobject.h new file mode 100644 -index 0000000000..5c6ab59c0d +index 0000000000..6540813735 --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsobject.h -@@ -0,0 +1,68 @@ +@@ -0,0 +1,79 @@ +#ifndef QOPENHARMONYJSOBJECT_H +#define QOPENHARMONYJSOBJECT_H + @@ -1835,16 +1916,27 @@ index 0000000000..5c6ab59c0d + + bool isValid() const; + ++ template ++ napi_ref callReturnRef(const QString &jsFunction, Args &&...args) ++ { ++ QOpenHarmonyJsFunction *f = getJsFunction(jsFunction); ++ if (f == nullptr) ++ return nullptr; ++ ++ f->callReturnRef(std::forward(args)...); ++ return f->refResult(); ++ } ++ + template + RET call(const QString &jsFunction, Args&&... args); + + template -+ void call(const QString &jsFunction, Args&&... args) ++ void callWithoutReturn(const QString &jsFunction, Args&&... args) + { + QOpenHarmonyJsFunction *f = getJsFunction(jsFunction); + if (f == nullptr) + return; -+ f->call(std::forward(args)...); ++ f->callWithoutReturn(std::forward(args)...); + } + + QOpenHarmonyJsFunction *getJsFunction(const QString &name) const; @@ -1879,7 +1971,7 @@ index 0000000000..5c6ab59c0d +#endif // QOPENHARMONYEGLCORE_H diff --git a/src/corelib/kernel/qopenharmonyjsobjectloader.cpp b/src/corelib/kernel/qopenharmonyjsobjectloader.cpp new file mode 100644 -index 0000000000..f5db262643 +index 0000000000..ef698869ab --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsobjectloader.cpp @@ -0,0 +1,170 @@ @@ -2042,7 +2134,7 @@ index 0000000000..f5db262643 + break; + } + if (!m_bObjectCreated.loadAcquire()) { -+ qWarning() << QString("create type of %1 js object %2 result failded").arg(objectType).arg(objectName); ++ LOGW("create type of %{public}s js object %{public}s result failded", qPrintable(objectType), qPrintable(objectName)); + } +} + @@ -2663,24 +2755,27 @@ index 0000000000..6a4626655c +}; diff --git a/src/openharmony/native/QtCore/JsApplication.ts b/src/openharmony/native/QtCore/JsApplication.ts new file mode 100644 -index 0000000000..9f8c968ddc +index 0000000000..0e5e739335 --- /dev/null +++ b/src/openharmony/native/QtCore/JsApplication.ts -@@ -0,0 +1,156 @@ +@@ -0,0 +1,184 @@ ++import font from '@ohos.font'; ++import fs from '@ohos.file.fs'; +import window from '@ohos.window'; ++import JsLogger from './JsLogger'; +import display from '@ohos.display'; -+import fs from '@ohos.file.fs'; -+import resourceManager from '@ohos.resourceManager'; -+import JsDataStore from './JsDataStore'; ++import { JsWindow } from './JsWindow'; +import { QtQPA } from './JsQtPlatform'; -+import JsLogger from './JsLogger'; ++import JsDataStore from './JsDataStore'; ++import { Font, UIContext } from '@ohos.arkui.UIContext'; +import { JsWindowManager } from './JsWindowManager'; -+import { JsWindow } from './JsWindow'; ++import resourceManager from '@ohos.resourceManager'; + +class JsApplication { + private mainWindow: window.Window = null; + private mainWindowName: string = "opemharmony_qt_mainwindow"; + private qpa: any = QtQPA; ++ private timerId: number | undefined; + + getMainWindow(): window.Window { + return this.mainWindow; @@ -2691,7 +2786,7 @@ index 0000000000..9f8c968ddc + } + + addWindow(name: string, window: JsWindow): void { -+ let obj = JsDataStore.getJsObjectLoader().createObject("JsWindowManager", "JsWindowManager"); ++ let obj = JsDataStore.getJsObjectLoader().createObject("JsWindowManager", "JsWindowManager"); + (obj as JsWindowManager).addWindow(name, window); + } + @@ -2707,40 +2802,52 @@ index 0000000000..9f8c968ddc + let qtMajorVersion: number = this.qpa.qtMajorVersion(); + let QtCoreModule: any = null; + if (qtMajorVersion == 5) -+ QtCoreModule = await import ("libQt5Core.so"); ++ QtCoreModule = await import("libQt5Core.so"); + else if (qtMajorVersion == 6) -+ QtCoreModule = await import ("libQt6Core.so"); ++ QtCoreModule = await import("libQt6Core.so"); + if (QtCoreModule == null) { + JsLogger.fatal("Cannot load QtCore module"); + return; + } ++ + JsDataStore.setQtMajorVersion(qtMajorVersion); + let QtCore = QtCoreModule.default; -+ QtCore.initJsObjectLoader((type: string, name: string, ...args: any[])=>{ ++ QtCore.initJsObjectLoader((type: string, name: string, ...args: any[]) => { + if (JsDataStore.getJsObjectLoader().hasJsObject(name)) + return JsDataStore.getJsObjectLoader().getJsObject(name) + return JsDataStore.getJsObjectLoader().createObject(type, name, ...args); -+ }, (name: string)=>{ ++ }, (name: string) => { + return JsDataStore.getJsObjectLoader().deleteJsObject(name); + }); + JsDataStore.addQtNativeModule("QPA", this.qpa); + JsDataStore.addQtNativeModule("QtCore", QtCore); + this.mainWindow = windowStage.getMainWindowSync(); + let window = new JsWindow(this.mainWindowName, this.mainWindow); -+ let localStore = new LocalStorage({"name": this.mainWindowName}); ++ let localStore = new LocalStorage({ "name": this.mainWindowName }); + await windowStage.loadContent('pages/Index', localStore); + this.addWindow(this.mainWindowName, window); + if (this.qpa != null) { + let p = this.mainWindow.getWindowProperties(); -+ this.updateQtScreen({width: p.windowRect.width, height: p.windowRect.height}); ++ this.updateQtScreen({ width: p.windowRect.width, height: p.windowRect.height }); + } + this.mainWindow.on("windowSizeChange", this.updateQtScreen); -+ windowStage.on("windowStageEvent", (state)=>{ ++ windowStage.on("windowStageEvent", (state) => { + if (this.qpa != null) + this.qpa.updateApplicationState(state); + JsLogger.info("window stage changed %{public}d", state); + }); ++ ++ /* NOTE 获取字体信息 */ ++ let mainClass = await windowStage.getMainWindow(); ++ let font: Font = mainClass.getUIContext().getFont(); ++ let fontList: Array = new Array(); ++ for (let f of font.getSystemFontList()) { ++ let fontInfo: font.FontInfo = font.getFontByName(f); ++ fontList.push(fontInfo.path); ++ } ++ this.qpa.setFontInfos(fontList); + JsDataStore.setWindowStage(windowStage); ++ + await this.extractFilesToCache(); + this.loadQtApplication(); + } @@ -2753,6 +2860,19 @@ index 0000000000..9f8c968ddc + this.qpa.setResourceManager(JsDataStore.getResourceManager()); + let result : boolean = this.qpa.startQtApplication(JsDataStore.getApplicationDirs(), "libentry.so"); + JsLogger.info("load qt application result: %{public}s", result); ++ ++ //周期检测qt应用是否执行完成(1000ms) ++ this.timerId = setInterval(() => { ++ JsLogger.info("check qt app is finish?"); ++ let res = this.qpa.waitForQtAppExit(); ++ if(res == 0) ++ { ++ JsLogger.info("qt application finished"); ++ //鸿蒙程序调用qt程序退出函数 ++ this.quit(); ++ JsDataStore.getContext().getApplicationContext().killAllProcesses(); ++ } ++ }, 1000); + } + + private saveFileToCache(file: resourceManager.RawFileDescriptor, des: string) { @@ -2825,18 +2945,18 @@ index 0000000000..9f8c968ddc +export default new JsApplication; diff --git a/src/openharmony/native/QtCore/JsDataStore.ts b/src/openharmony/native/QtCore/JsDataStore.ts new file mode 100644 -index 0000000000..a43a6e5a97 +index 0000000000..be9a25b667 --- /dev/null +++ b/src/openharmony/native/QtCore/JsDataStore.ts @@ -0,0 +1,136 @@ -+import common from '@ohos.app.ability.common'; +import window from '@ohos.window'; -+import bundleManager from '@ohos.bundle.bundleManager'; -+import resourceManager from '@ohos.resourceManager'; +import HashMap from '@ohos.util.HashMap'; +import { JsQtModule } from './JsQtModule' +import deviceInfo from '@ohos.deviceInfo'; ++import common from '@ohos.app.ability.common'; +import QtJsObjectLoader from './JsObjectLoader'; ++import resourceManager from '@ohos.resourceManager'; ++import bundleManager from '@ohos.bundle.bundleManager'; + +interface ApplicationDirs { + tempDir: string, @@ -2855,7 +2975,7 @@ index 0000000000..a43a6e5a97 + private windowStage: window.WindowStage; + private elementName: bundleManager.ElementName = null; + private jsModules: JsQtModule[] = []; -+ private applicationDirs: ApplicationDirs; ++ private ApplicationDirs: ApplicationDirs; + private qtMajorVersion: number = 0; + private qtNativeModules: HashMap = new HashMap(); + private jsObjectLoader: QtJsObjectLoader = new QtJsObjectLoader; @@ -2876,7 +2996,7 @@ index 0000000000..a43a6e5a97 + distributedFilesDir: appContext.distributedFilesDir, + qmlDir: appContext.cacheDir + "/Qt/qml" + }; -+ this.applicationDirs = dirs; ++ this.ApplicationDirs = dirs; + } + + getContext(): common.UIAbilityContext { @@ -2884,7 +3004,7 @@ index 0000000000..a43a6e5a97 + } + + getApplicationDirs() : ApplicationDirs { -+ return this.applicationDirs; ++ return this.ApplicationDirs; + } + + setElementName(en: bundleManager.ElementName) { @@ -3254,10 +3374,10 @@ index 0000000000..a840215671 +} diff --git a/src/openharmony/native/QtCore/JsInputMethod.ts b/src/openharmony/native/QtCore/JsInputMethod.ts new file mode 100644 -index 0000000000..205a6d9685 +index 0000000000..0984b1c765 --- /dev/null +++ b/src/openharmony/native/QtCore/JsInputMethod.ts -@@ -0,0 +1,248 @@ +@@ -0,0 +1,286 @@ +import JsDataStore from './JsDataStore' +import { BusinessError } from '@ohos.base'; +import inputMethod from '@ohos.inputMethod'; @@ -3265,6 +3385,7 @@ index 0000000000..205a6d9685 + +export class JsInputMethod { + private handler: number = 0; ++ private visable: boolean = false; /* ¼뷨visible״̬ */ + private attached: boolean = false; + private inputMethodController: inputMethod.InputMethodController = inputMethod.getController(); + @@ -3282,6 +3403,33 @@ index 0000000000..205a6d9685 + } + + try { ++ this.inputMethodController.on('sendFunctionKey', (functionKey: inputMethod.FunctionKey) => { ++ console.warn(`Succeeded in subscribing sendFunctionKey, functionKey.enterKeyType: ${functionKey.enterKeyType}`); ++ }); ++ } catch (err) { ++ console.error(`Failed to subscribe sendFunctionKey: ${JSON.stringify(err)}`); ++ } ++ ++ try { ++ this.inputMethodController.on('sendKeyboardStatus', (keyboardStatus: inputMethod.KeyboardStatus) => { ++ console.info(`Succeeded in subscribing sendKeyboardStatus, keyboardStatus: ${keyboardStatus}`); ++ switch (keyboardStatus) { ++ case inputMethod.KeyboardStatus.HIDE: ++ this.visable = false; ++ this.detach(); ++ break; ++ case inputMethod.KeyboardStatus.SHOW: ++ this.visable = true; ++ break; ++ default: ++ break; ++ } ++ }); ++ } catch (err) { ++ console.error(`Failed to subscribe sendKeyboardStatus: ${JSON.stringify(err)}`); ++ } ++ ++ try { + this.inputMethodController.on('deleteLeft', (length: number) => { + console.log(`Succeeded in subscribing deleteLeft, length: ${length}`); + JsDataStore.getQtNativeModule("QPA").deleteLeft(this.handler, length); @@ -3369,56 +3517,66 @@ index 0000000000..205a6d9685 + this.inputMethodController.off('deleteLeft'); + this.inputMethodController.off('deleteRight'); + this.inputMethodController.off('selectByRange'); ++ this.inputMethodController.off('sendFunctionKey'); + this.inputMethodController.off('selectByMovement'); ++ this.inputMethodController.off('sendKeyboardStatus'); + this.inputMethodController.off('handleExtendAction'); + this.inputMethodController.off('getLeftTextOfCursor'); + this.inputMethodController.off('getRightTextOfCursor'); + this.inputMethodController.off('getTextIndexAtCursor'); + } + ++ isInputPanelVisible(): boolean { ++ return this.visable; ++ } ++ + isAttached() { + return this.attached; + } + -+ attach(handler: number): boolean { -+ if (true == this.attached) { -+ return; ++ async attach(handler: number, inputType: number, enterType: number): Promise { ++ if (this.attached) { ++ return true; + } + + if (0 == handler) { + console.error("handle number is error"); -+ return; ++ return false; + } + + this.handler = handler; + try { + let textConfig: inputMethod.TextConfig = { + inputAttribute: { -+ textInputType: inputMethod.TextInputType.MULTILINE, -+ enterKeyType: inputMethod.EnterKeyType.UNSPECIFIED ++ textInputType: inputType, ++ enterKeyType: enterType + } + }; -+ this.inputMethodController.attach(true, textConfig).then(() => { ++ await this.inputMethodController.attach(true, textConfig).then(() => { + this.subscribe(); ++ this.attached = true; + console.log('Succeeded in attaching inputMethod.'); + }).catch((err) => { ++ this.attached = false; + console.error(`Failed to attach: ${JSON.stringify(err)}`); -+ return false; + }) + } catch (err) { ++ this.attached = false; + console.error(`Failed to attach: ${JSON.stringify(err)}`); + } -+ this.attached = true; ++ return this.attached; + } + -+ detach() { ++ async detach(): Promise { + this.unsubscribe(); -+ this.inputMethodController.detach().then(() => { ++ await this.inputMethodController.detach().then(() => { ++ this.attached = false; + console.log('Succeeded in detaching inputMethod.'); + }).catch((err) => { ++ this.attached = true; + console.error(`Failed to detach: ${JSON.stringify(err)}`); + }); -+ this.attached = false; ++ return !this.attached; + } + + showTextInput() { @@ -3807,7 +3965,7 @@ index 0000000000..62861e0292 +} diff --git a/src/openharmony/native/QtCore/JsWindowManager.ts b/src/openharmony/native/QtCore/JsWindowManager.ts new file mode 100644 -index 0000000000..c24c6728c8 +index 0000000000..86263ca195 --- /dev/null +++ b/src/openharmony/native/QtCore/JsWindowManager.ts @@ -0,0 +1,46 @@ @@ -3848,7 +4006,7 @@ index 0000000000..c24c6728c8 + } + } + -+ async destroyWindow(name: string): Promise { ++ async destoryWindow(name: string): Promise { + if (!this.windows.hasKey(name)) + return false; + let window = this.windows.get(name); @@ -3877,11 +4035,10 @@ index 0000000000..1c9156fde0 +OTHER_FILES += $$templates.files diff --git a/src/openharmony/pages/Index.ets b/src/openharmony/pages/Index.ets new file mode 100644 -index 0000000000..16904a1c31 +index 0000000000..c877cc24ef --- /dev/null +++ b/src/openharmony/pages/Index.ets -@@ -0,0 +1,17 @@ -+ +@@ -0,0 +1,14 @@ +@Entry +@Component +struct Index { @@ -3892,9 +4049,7 @@ index 0000000000..16904a1c31 + Row() { + XComponent({id: this.idName, type: 'surface', libraryname: 'plugins_platforms_qopenharmony' }).width("100%").height("100%") + .focusable(true) -+ .onLoad(()=>{ -+ -+ }) ++ .focusOnTouch(true) + } + } +} @@ -5874,10 +6029,10 @@ index 0000000000..1a88d88b24 +#endif // QOPENHARMONYDEFINES_H diff --git a/src/plugins/platforms/openharmony/qopenharmonymain.cpp b/src/plugins/platforms/openharmony/qopenharmonymain.cpp new file mode 100644 -index 0000000000..4425b99cbe +index 0000000000..ca8eefffcc --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonymain.cpp -@@ -0,0 +1,453 @@ +@@ -0,0 +1,451 @@ +#include +#include +#include @@ -5899,9 +6054,9 @@ index 0000000000..4425b99cbe +#include +#include + -+#include "qopenharmonyfileenginehandler.h" -+#include "qopenharmonymain.h" +#include "qopenharmonylog.h" ++#include "qopenharmonymain.h" ++#include "qopenharmonyfileenginehandler.h" +#include "qopenharmonyjswindowmanager.h" +#include "qopenharmonyplatformintegration.h" +#include "qopenharmonyplatformdialoghelpers.h" @@ -5909,6 +6064,7 @@ index 0000000000..4425b99cbe +#include "qopenharmonyplatforminputcontext.h" +#include "qopenharmonyeventdispatcher.h" +#include "qopenharmonyplatformwindow.h" ++#include "qopenharmonyplatformfontdatabase.h" + +extern "C" typedef int (*Main)(int, char **); //use the standard main method to start the application +static Main m_main = nullptr; @@ -5927,23 +6083,16 @@ index 0000000000..4425b99cbe +static QOpenHarmonyPlatformIntegration *m_platformIntegration = nullptr; +static QOpenHarmonyFileEngineHandler *m_openHarmonyFileEngineHandler = nullptr; +static QString m_deviceType = "default"; ++static QList m_applicationParams; + +static void *startMainMethod(void *arg) +{ -+ if (nullptr == arg) { -+ return nullptr; -+ } ++ QVarLengthArray params(m_applicationParams.size()); + -+ QByteArray p((char*)arg); -+ QByteArrayList byts = p.split(' '); -+ QVarLengthArray argvs(byts.length()); -+ int i = 0; -+ for(QByteArray b : byts){ -+ argvs[i] = b.data(); -+ i++; -+ } -+ /* FIXME 启动参数个数问题引起崩溃 */ -+ int ret = m_main(1, const_cast(argvs.data())); ++ for (int i = 0; i < m_applicationParams.size(); i++) ++ params[i] = static_cast(m_applicationParams[i].constData()); ++ ++ int ret = m_main(m_applicationParams.length(), const_cast(params.data())); + + if (m_mainLibraryHnd) { + int res = dlclose(m_mainLibraryHnd); @@ -5993,9 +6142,13 @@ index 0000000000..4425b99cbe + if (!cacheQmlStr.isEmpty()) + qmls << cacheQmlStr.toLatin1(); + ++ QString cacheDir = qJs::getObjectPropertyValue(args[0], "cacheDir"); ++ if (::setenv("QT_HARMONY_CACHE_DIR", cacheDir.toLatin1().constData(), 1) != 0) { ++ LOGE("Can't set environment for QT_HARMONY_CACHE_DIR"); ++ } + + if (::setenv("QT_QPA_PLATFORM_PLUGIN_PATH", libDir.constData(), 1) != 0) { -+ LOGE("Can't set environment for QT_PLUGIN_PATH"); ++ LOGE("Can't set environment for QT_QPA_PLATFORM_PLUGIN_PATH"); + } + if (::setenv("QML_DISABLE_DISK_CACHE", "1", 1) != 0) { + LOGE("Can't set environment for QML_DISABLE_DISK_CACHE"); @@ -6004,17 +6157,32 @@ index 0000000000..4425b99cbe + LOGE("Can't set environment for QT_PLUGIN_PATH"); + } + ++ QByteArrayList boundPath = { libDir }; ++ QByteArray boundImport = boundPath.join(":"); ++ qWarning() << "harmony boundImport import path:" << boundImport; ++ if (::setenv("QT_HARMONY_BUNDLED_LIBS_PATH", boundImport.constData(), 1) != 0) { ++ LOGE("Can't set environment for QT_HARMONY_BUNDLED_LIBS_PATH"); ++ } ++ + QByteArray qmlImportPath = qmls.join(":"); ++ qWarning() << "qml import path:" << qmlImportPath; + if (::setenv("QML2_IMPORT_PATH", qmlImportPath.constData(), 1) != 0) { + LOGE("Can't set environment for QML2_IMPORT_PATH"); + } -+ -+// if (::setenv("QT_DEBUG_PLUGINS", "1", 1) != 0) { -+// LOGE("Can't set environment for QT_DEBUG_PLUGINS"); -+// } -+ ++#if 0 ++ if (::setenv("QT_DEBUG_PLUGINS", "1", 1) != 0) { ++ LOGE("Can't set environment for QT_DEBUG_PLUGINS"); ++ } ++#endif + m_mainLibraryHnd = nullptr; -+ QByteArray fileName = qJs::getString(args[1]).toLatin1(); ++ ++ QByteArray params = qJs::getString(args[1]).toLatin1(); ++ m_applicationParams = params.split('\t'); ++ if (m_applicationParams.empty()) { ++ LOGE("no qt application specified"); ++ return qJs::createBool(false); ++ } ++ QByteArray fileName = m_applicationParams.first(); + LOGI("load qt application %{public}s", fileName.constData()); + + //look for main() @@ -6040,37 +6208,8 @@ index 0000000000..4425b99cbe + + + m_openHarmonyFileEngineHandler = new QOpenHarmonyFileEngineHandler; -+ -+ QByteArray byt = libDir + "/" + fileName; -+ if (3 == argc) { -+ QStringList argvs = qJs::getStringList(args[2]); -+ argvs.prepend(byt); -+ QString tmp = argvs.join(QString(" ")); -+ byt.clear(); -+ byt = tmp.toLocal8Bit(); -+ } -+ -+ int result = pthread_create(&m_qtAppThread, nullptr, startMainMethod, byt.data()); -+ if (result) { -+ LOGW("create qt thread error:%{public}s", result); -+ return qJs::createBool(false); -+ } -+ -+#if 0 -+ void * thread_result; -+ result = pthread_join(m_qtAppThread, &thread_result); -+ if (result) { -+ LOGW("join qt thread error:%{public}s", result); -+ return qJs::createBool(false); -+ } -+ -+ result = pthread_join(m_qtAppThread, &thread_result); -+ if (result == ESRCH) { -+ LOGW("qt thread inexistence"); -+ return qJs::createBool(false); -+ } -+ LOGW("<------------------ join %{public}s", thread_result); -+#endif ++ m_applicationParams[0] = libDir + "/" + fileName; ++ pthread_create(&m_qtAppThread, nullptr, startMainMethod, nullptr); + return qJs::createBool(true); +} + @@ -6224,7 +6363,7 @@ index 0000000000..4425b99cbe + LOGI("quit qt application"); + OH_ResourceManager_ReleaseNativeResourceManager(m_resourceManager); + qJs::quit(); -+ qApp->quit(); ++ //qApp->quit(); + return nullptr; +} + @@ -6233,6 +6372,18 @@ index 0000000000..4425b99cbe + return qJs::createInt32(QT_VERSION_MAJOR); +} + ++static napi_value waitForQtAppExit(napi_env env, napi_callback_info info) ++{ ++ // sem_wait(&m_terminateSemaphore); ++ if (sem_trywait(&m_terminateSemaphore) == 0) { ++ return qJs::createInt32(0); ++ } ++ else ++ { ++ return qJs::createInt32(1); ++ } ++} ++ +/* + * function for module exports + */ @@ -6250,15 +6401,17 @@ index 0000000000..4425b99cbe + DECLARE_NAPI_FUNCTION("quitQtApplication", quitQtApplication), + DECLARE_NAPI_FUNCTION("qtMajorVersion", qtMajorVersion), + DECLARE_NAPI_FUNCTION("setDeviceType", setDeviceType), ++ DECLARE_NAPI_FUNCTION("waitForQtAppExit", waitForQtAppExit), + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); + QOpenHarmonyPlatformInputContext::init(env, exports); ++ QOpenHarmonyPlatformFontDatabase::init(env, exports); + QOpenHarmonyPlatformMessageDialogHelper::init(env, exports); + QOpenHarmonyPlatformFileDialogHelper::init(env, exports); + -+ #ifndef QT_NO_CLIPBOARD ++#ifndef QT_NO_CLIPBOARD + QOpenHarmonyPlatformClipboard::init(env, exports); -+ #endif ++#endif + qJs::init(env); + inited = true; + } @@ -6329,7 +6482,7 @@ index 0000000000..4425b99cbe + if (isPhone()) + return QMargins(); + // Todo read from js -+ return QMargins(3, 72, 3, 3); ++ return QMargins(7, 92, 6, 6); +} diff --git a/src/plugins/platforms/openharmony/qopenharmonymain.h b/src/plugins/platforms/openharmony/qopenharmonymain.h new file mode 100644 @@ -6450,7 +6603,7 @@ index 0000000000..db75831b39 +#endif // QOPENHARMONYPLATFORMBACKINGSTORE_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformclipboard.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatformclipboard.cpp new file mode 100644 -index 0000000000..c0694de72e +index 0000000000..6d4531134a --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformclipboard.cpp @@ -0,0 +1,86 @@ @@ -6518,7 +6671,7 @@ index 0000000000..c0694de72e +{ + if (supportsMode(mode)) { + QString text = (data != 0 && data->hasText() ? data->text() : QString()); -+ m_jsClipboard->call("setClipboardText", text);; ++ m_jsClipboard->callWithoutReturn("setClipboardText", text);; + } + if (data != 0) + data->deleteLater(); @@ -6584,7 +6737,7 @@ index 0000000000..40b3576be4 +#endif // QOPENHARMONYPLATFORMCLIPBOARD_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformdialoghelpers.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatformdialoghelpers.cpp new file mode 100644 -index 0000000000..7368f11911 +index 0000000000..dbd3897b53 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformdialoghelpers.cpp @@ -0,0 +1,298 @@ @@ -6671,7 +6824,7 @@ index 0000000000..7368f11911 + if (!str.isEmpty()) + text += str; + -+ m_jsDialog->call("messageBox", QVariant(qlonglong(static_cast(this))), htmlText(opt->windowTitle()), text, m_buttons); ++ m_jsDialog->callWithoutReturn("messageBox", QVariant(qlonglong(static_cast(this))), htmlText(opt->windowTitle()), text, m_buttons); + m_shown = true; + return true; +} @@ -6861,9 +7014,9 @@ index 0000000000..7368f11911 + return false; + bool open = (opt->acceptMode() == QFileDialogOptions::AcceptOpen); + if (open) -+ m_jsDialog->call("openFileDialog", QVariant(qlonglong(static_cast(this))), m_filter); ++ m_jsDialog->callWithoutReturn("openFileDialog", QVariant(qlonglong(static_cast(this))), m_filter); + else -+ m_jsDialog->call("saveFileDialog", QVariant(qlonglong(static_cast(this))), m_saveFile); ++ m_jsDialog->callWithoutReturn("saveFileDialog", QVariant(qlonglong(static_cast(this))), m_saveFile); + m_shown = true; + return true; +} @@ -6981,23 +7134,61 @@ index 0000000000..39762fdc90 +#endif // QOPENHARMONYPLATFORMDIALOGHELPERS_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformfontdatabase.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatformfontdatabase.cpp new file mode 100644 -index 0000000000..ccad7c3358 +index 0000000000..dc5b6c998f --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformfontdatabase.cpp -@@ -0,0 +1,36 @@ +@@ -0,0 +1,83 @@ +#include ++#include ++#include ++#include + +#include "qopenharmonyplatformfontdatabase.h" + ++static QStringList gs_fonts; ++ ++/* 通过鸿蒙ts接口查询系统提供的字体路径 ++ * 然后传入C++端使用 ++ */ ++static napi_value setFontInfos(napi_env env, napi_callback_info info) ++{ ++ size_t argc = 1; ++ napi_value args[1]; ++ NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); ++ if (argc != 1) { ++ napi_throw_type_error(env, NULL, "Wrong number of arguments"); ++ return nullptr; ++ } ++ ++ if (gs_fonts.isEmpty()) ++ gs_fonts = qJs::getStringList(args[0]); ++ ++ return Q_NULLPTR; ++} ++ +QT_BEGIN_NAMESPACE + +QString QOpenHarmonyPlatformFontDatabase::fontDir() const +{ ++ /* FIMXE 鸿蒙权限收紧,读取该目录会提示读取失败 */ + return QLatin1String("/system/fonts"); +} + +void QOpenHarmonyPlatformFontDatabase::populateFontDatabase() +{ ++ /* FIXME ++ * 使用鸿蒙ts端查询到的字体路径 ++ * 否则,扫描fontDir路径中的字体文件 ++ * (该操作因为鸿蒙系统权限收紧会提示读取目录失败的警告) ++ */ ++ if (!gs_fonts.isEmpty()) { ++ for (const QString &f : qAsConst(gs_fonts)) { ++ const QByteArray file = QFile::encodeName(f); ++ QFreeTypeFontDatabase::addTTFile(QByteArray(), file); ++ } ++ return; ++ } ++ + QString fontpath = fontDir(); + QDir dir(fontpath); + @@ -7019,26 +7210,37 @@ index 0000000000..ccad7c3358 + } +} + ++napi_value QOpenHarmonyPlatformFontDatabase::init(napi_env env, napi_value exports) ++{ ++ napi_property_descriptor desc[] ={ ++ DECLARE_NAPI_FUNCTION("setFontInfos", setFontInfos), ++ }; ++ NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); ++ return nullptr; ++} ++ + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformfontdatabase.h b/src/plugins/platforms/openharmony/qopenharmonyplatformfontdatabase.h new file mode 100644 -index 0000000000..3e38d4f853 +index 0000000000..bfad0a18a1 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformfontdatabase.h -@@ -0,0 +1,17 @@ +@@ -0,0 +1,19 @@ +#ifndef QOPENHARMONYPLATFORMFONTDATABASE_H +#define QOPENHARMONYPLATFORMFONTDATABASE_H + ++#include +#include + +QT_BEGIN_NAMESPACE + +class QOpenHarmonyPlatformFontDatabase: public QFreeTypeFontDatabase +{ -+public: ++public: + QString fontDir() const override; + void populateFontDatabase() override; ++ static napi_value init(napi_env env, napi_value exports); +}; + +QT_END_NAMESPACE @@ -7139,10 +7341,10 @@ index 0000000000..e792d1a019 +#endif // QOPENHARMONYPLATFORMFOREIGNWINDOW_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatforminputcontext.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatforminputcontext.cpp new file mode 100644 -index 0000000000..b73ae5a569 +index 0000000000..d00836a94c --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatforminputcontext.cpp -@@ -0,0 +1,481 @@ +@@ -0,0 +1,1175 @@ +#include "qopenharmonymain.h" +#include "qopenharmonyjsobjectloader.h" +#include "qopenharmonyplatformscreen.h" @@ -7154,6 +7356,7 @@ index 0000000000..b73ae5a569 +#include + +#include ++#include +#include +#include +#include @@ -7163,12 +7366,92 @@ index 0000000000..b73ae5a569 + +#include +#include -+ -+#include +#include ++#include + +QT_BEGIN_NAMESPACE + ++namespace { ++ ++class BatchEditLock ++{ ++public: ++ ++ explicit BatchEditLock(QOpenHarmonyPlatformInputContext *context) ++ : m_context(context) ++ { ++ m_context->beginBatchEdit(); ++ } ++ ++ ~BatchEditLock() ++ { ++ m_context->endBatchEdit(); ++ } ++ ++ BatchEditLock(const BatchEditLock &) = delete; ++ BatchEditLock &operator=(const BatchEditLock &) = delete; ++ ++private: ++ ++ QOpenHarmonyPlatformInputContext *m_context; ++}; ++ ++} // namespace anonymous ++ ++/*! ++ * \brief Qt-鸿蒙平台下的输入类型枚举值映射 ++ * \param hints Qt下的枚举值 ++ * \return 返回Qt-鸿蒙的输入类型映射值 ++ */ ++static int harmonyTextInputType(Qt::InputMethodHints hints) ++{ ++ /* FIXME Qt支持位运算,鸿蒙文本类型不支持位运算的枚举值 */ ++ if(hints.testFlag(Qt::ImhMultiLine)) /* 多行文本类型 */ ++ return 1; ++ if (hints.testFlag(Qt::ImhPreferNumbers) || ++ hints.testFlag(Qt::ImhDigitsOnly)) /* 数字类型 */ ++ return 2; ++ if (hints.testFlag(Qt::ImhDate) || ++ hints.testFlag(Qt::ImhTime)) /* 日期类型 */ ++ return 4; ++ if (hints.testFlag(Qt::ImhHiddenText)) /* 密码类型 */ ++ return 7; ++ if ((hints.testFlag(Qt::ImhDigitsOnly) | ++ hints.testFlag(Qt::ImhFormattedNumbersOnly)) && ++ hints.testFlag(Qt::ImhHiddenText)) /* 数字密码类型 */ ++ return 8; ++ if (hints.testFlag(Qt::ImhDialableCharactersOnly)) /* 电话号码类型 */ ++ return 3; ++ if (hints.testFlag(Qt::ImhEmailCharactersOnly)) /* 邮箱地址类型 */ ++ return 5; ++ if (hints.testFlag(Qt::ImhUrlCharactersOnly)) /* 链接类型 */ ++ return 6; ++ ++ return 0; /* 默认文本类型 */ ++} ++/*! ++ * \brief Qt-鸿蒙平台下的EnterKey功能值映射 ++ * \param type Qt下的EnterKey功能枚举值 ++ * \return 返回Qt-鸿蒙的EnterKey功能映射值 ++ */ ++static int harmonyEnterKeyType(Qt::EnterKeyType type) ++{ ++ switch (type) { ++ case Qt::EnterKeyDone: ++ case Qt::EnterKeyDefault: ++ return 6; ++ case Qt::EnterKeyReturn: ++ case Qt::EnterKeyPrevious: ++ return 7; ++ case Qt::EnterKeyGo: return 2; ++ case Qt::EnterKeySend: return 4; ++ case Qt::EnterKeySearch: return 3; ++ case Qt::EnterKeyNext:return 5; ++ default: break; ++ } ++ return 0; ++} ++ +static QOpenHarmonyPlatformInputContext *m_openHarmonyInputContext = 0; + +static napi_value insertText(napi_env env, napi_callback_info info) @@ -7274,15 +7557,446 @@ index 0000000000..b73ae5a569 + return nullptr; +} + -+void QOpenHarmonyPlatformInputContext::sendKeyEvent(QKeyEvent *event) ++void QOpenHarmonyPlatformInputContext::dispatchKeyEvent(OH_NativeXComponent_KeyCode code, ++ OH_NativeXComponent_KeyAction action, ++ OH_NativeXComponent_EventSourceType stype, ++ int64_t deviceId, ++ int64_t timeStamp) ++{ ++ Q_UNUSED(deviceId);Q_UNUSED(timeStamp); ++ static QHash sKeyType{ ++ { OH_NATIVEXCOMPONENT_KEY_ACTION_DOWN, QEvent::KeyPress }, ++ { OH_NATIVEXCOMPONENT_KEY_ACTION_UP, QEvent::KeyRelease }, ++ }; ++ ++ ++ static QHash 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_Enter }, ++ { KEY_DEL, Qt::Key_Back }, ++ { KEY_GRAVE, Qt::Key_Apostrophe }, ++ { 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_Return }, ++ //{ 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 } ++ }; ++ ++ static QHash 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}, ++ }; ++ ++ /* 有修饰符按下时记录按下的修饰符 ++ * 松开时移除修饰符记录 ++ */ ++ ++ Qt::KeyboardModifiers modifiers(Qt::NoModifier); ++ QEvent::Type t = sKeyType.value(action, QEvent::None); ++ Qt::KeyboardModifier m = sKeyModifers.value(code, Qt::NoModifier); ++ if (Qt::NoModifier != m && QEvent::KeyPress == t){ ++ modifiers |= m; ++ m_mpd.insert(m); ++ } ++ else if (Qt::NoModifier != m && QEvent::KeyRelease == t) { ++ m_mpd.remove(m); ++ } ++ ++ Qt::Key k = sKeyMap.value(code, Qt::Key_unknown); ++ ++ int nativeModifier = KEY_UNKNOWN; ++ for (Qt::KeyboardModifier mf : m_mpd) ++ nativeModifier |= int(mf); ++ ++ QKeyEvent *kEvent = new QKeyEvent(t, k, modifiers, code, code, nativeModifier); ++ /* NOTE 因为鸿蒙回调在其他线程,这里事件处理只能通过线程队列发送 */ ++ QGuiApplication::postEvent(m_focusObject, kEvent); ++ ++ /* 快捷点组合判断 */ ++ if (m_mpd.contains(Qt::ControlModifier) && KEY_A == code) ++ QMetaObject::invokeMethod(this, "sendShortcut", Qt::QueuedConnection, ++ Q_ARG(int, QKeySequence::SelectAll)); ++ else if (m_mpd.contains(Qt::ControlModifier) && KEY_C == code) ++ QMetaObject::invokeMethod(this, "sendShortcut", Qt::QueuedConnection, ++ Q_ARG(int, QKeySequence::Copy)); ++ else if (m_mpd.contains(Qt::ControlModifier) && KEY_V == code) ++ QMetaObject::invokeMethod(this, "sendShortcut", Qt::QueuedConnection, ++ Q_ARG(int, QKeySequence::Paste)); ++} ++ ++void QOpenHarmonyPlatformInputContext::sendShortcut(int key) +{ -+ QGuiApplication::sendEvent(m_focusObject, event); ++ QKeySequence::StandardKey skey = QKeySequence::StandardKey(key); ++ QKeySequence sequence(skey); ++ for (int i = 0; i < sequence.count(); ++i) { ++ const int keys = sequence[i]; ++ Qt::Key key = Qt::Key(keys & ~Qt::KeyboardModifierMask); ++ Qt::KeyboardModifiers mod = Qt::KeyboardModifiers(keys & Qt::KeyboardModifierMask); ++ ++ QKeyEvent pressEvent(QEvent::KeyPress, key, mod); ++ QKeyEvent releaseEvent(QEvent::KeyRelease, key, mod); ++ ++ QGuiApplication::sendEvent(m_focusObject, &pressEvent); ++ QGuiApplication::sendEvent(m_focusObject, &releaseEvent); ++ } ++} ++ ++void QOpenHarmonyPlatformInputContext::updateCursorPosition() ++{ ++ // qWarning() << "<--------------::::" << Q_FUNC_INFO; +} + +QOpenHarmonyPlatformInputContext::QOpenHarmonyPlatformInputContext() + : QPlatformInputContext() + , m_composingTextStart(-1) + , m_composingCursor(-1) ++ , m_batchEditNestingLevel(0) + , m_focusObject(Q_NULLPTR) +{ + m_jsInputCtl = qJsObjectLoader->create("JsInputMethod"); @@ -7293,17 +8007,188 @@ index 0000000000..b73ae5a569 +{ + m_openHarmonyInputContext = Q_NULLPTR; +} ++/*! ++ * \brief 检查输入上下文是否具有指定的功能 ++ * \param capability 枚举值,用于指定功能类型 ++ * \return 返回布尔值,如果具有指定功能,则返回 true,否则返回 false ++ */ ++bool QOpenHarmonyPlatformInputContext::hasCapability(Capability capability) const ++{ ++ switch (capability) { ++ case HiddenTextCapability: ++ return false; ++ default:break; ++ } ++ return true; ++} ++/*! ++ * \brief 重置输入法状态,将输入法状态恢复到默认状态 ++ */ ++void QOpenHarmonyPlatformInputContext::reset() ++{ ++ // qWarning() << "<-----------::" << Q_FUNC_INFO; ++ focusObjectStopComposing(); ++ m_batchEditNestingLevel = 0; + -+QOpenHarmonyPlatformInputContext *QOpenHarmonyPlatformInputContext::openHarmonyInputContext() ++ if (m_jsInputCtl->call("isAttached")) ++ m_jsInputCtl->call("detach"); ++ ++ clearInput(); ++ emitInputPanelVisibleChanged(); ++} ++/*! ++ * \brief 提交当前输入法状态,将当前输入法状态应用到文本编辑器中 ++ */ ++void QOpenHarmonyPlatformInputContext::commit() +{ -+ return m_openHarmonyInputContext; ++ // qWarning() << "<-----------::" << Q_FUNC_INFO; ++ if(m_jsInputCtl->call("isAttached")) ++ m_jsInputCtl->call("detach"); ++} ++/*! ++ * \brief 编辑器更新通知。由QInputMethod::update()调用 ++ * 函数的作用是更新输入上下文的状态,以便与应用程序的输入方法通信 ++ * 并响应输入法相关的查询,一般流程如下: ++ * 1.当输入法状态发生变化,或者焦点对象发生变化时 ++ * QGuiApplication 会调用当前活动的 QPlatformInputContext 对象的 update 函数 ++ * ++ * 2.在 update 函数内部,QPlatformInputContext 可以查询焦点对象的相关信息, ++ * 例如文本内容、光标位置等,然后将这些信息传递给输入法对象 ++ * ++ * 3.输入法对象根据接收到的信息更新其状态,并相应地调整显示内容或行为 ++ * 4.用户与输入法进行交互,输入文本或者调整输入法的设置 ++ * 5.当用户输入完成或者输入法状态发生变化时,输入法对象可能会触发输入法事件, ++ * 通知 QPlatformInputContext 对象更新状态 ++ */ ++void QOpenHarmonyPlatformInputContext::update(Qt::InputMethodQueries queries) ++{ ++ // qWarning() << "<-----------::" << Q_FUNC_INFO; ++ QSharedPointer query = focusObjectInputMethodQuery(queries); ++ if (query.isNull()) ++ return; ++ ++#warning TODO extract the needed data from query +} + ++/*! ++ * \brief 调用输入法的动作,以执行指定的操作,如向前移动光标、向后删除等 ++ * \param act 动作类型 ++ * \param cursorPosition 光标位置 ++ */ +void QOpenHarmonyPlatformInputContext::invokeAction(QInputMethod::Action act, int cursorPosition) +{ -+ qInfo() << "QOpenHarmonyPlatformInputContext<===================invokeAction:" -+ << act -+ << cursorPosition; ++ // qWarning() << "<-----------::" << Q_FUNC_INFO; ++#warning TODO Handle ++ Q_UNUSED(act); ++ Q_UNUSED(cursorPosition); ++} ++/*! ++ * \brief 过滤输入事件,以便输入上下文可以处理输入事件并相应地调整输入法状态 ++ * \param event 输入事件 ++ * \return 返回布尔值 ++ */ ++bool QOpenHarmonyPlatformInputContext::filterEvent(const QEvent *event) ++{ ++ return QPlatformInputContext::filterEvent(event); ++} ++/*! ++ * \brief 获取键盘区域的矩形范围,以便应用程序可以根据键盘的显示状态调整布局 ++ * \return 返回键盘区域矩形大小 ++ */ ++QRectF QOpenHarmonyPlatformInputContext::keyboardRect() const ++{ ++ //TODO acquire softkeyborad rect ++ return QRectF(); ++} ++ ++/*! ++ * \brief 返回布尔值,指示输入面板是否处于动画状态 ++ * \return 返回布尔值 ++ */ ++bool QOpenHarmonyPlatformInputContext::isAnimating() const ++{ ++ return false; ++} ++/*! ++ * \brief 显示输入面板 ++ */ ++void QOpenHarmonyPlatformInputContext::showInputPanel() ++{ ++ // qWarning() << "<-----------::" << Q_FUNC_INFO; ++ QSharedPointer query = focusObjectInputMethodQuery(); ++ if (query.isNull()) ++ return; ++ ++ disconnect(m_updateCursorPosConnection); ++ if (qGuiApp->focusObject()->metaObject()->indexOfSignal("cursorPositionChanged(int,int)") >= 0) // QLineEdit breaks the pattern ++ m_updateCursorPosConnection = connect(qGuiApp->focusObject(), SIGNAL(cursorPositionChanged(int,int)), this, SLOT(updateCursorPosition())); ++ else ++ m_updateCursorPosConnection = connect(qGuiApp->focusObject(), SIGNAL(cursorPositionChanged()), this, SLOT(updateCursorPosition())); ++ ++ Qt::InputMethodHints hints = query->value(Qt::ImHints).value(); ++ Qt::EnterKeyType enterType = query->value(Qt::ImEnterKeyType).value(); ++ ++ bool isAttached = m_jsInputCtl->call("isAttached"); ++ if (!isAttached) ++ m_jsInputCtl->call("attach", QVariant(qlonglong(static_cast(this))), ++ harmonyTextInputType(hints), ++ harmonyEnterKeyType(enterType)); ++ ++ emitInputPanelVisibleChanged(); ++} ++/*! ++ * \brief 隐藏输入面板 ++ */ ++void QOpenHarmonyPlatformInputContext::hideInputPanel() ++{ ++ // qWarning() << "<-----------::" << Q_FUNC_INFO; ++#if 0 ++ if(m_jsInputCtl->call("isAttached")) ++ m_jsInputCtl->call("detach"); ++#endif ++ clearInput(); ++ emitInputPanelVisibleChanged(); ++} ++/*! ++ * \brief 返回布尔值,指示输入面板的可见性状态 ++ * \return 返回布尔值 ++ */ ++bool QOpenHarmonyPlatformInputContext::isInputPanelVisible() const ++{ ++ bool visible = m_jsInputCtl->call("isInputPanelVisible"); ++ return visible; ++} ++/*! ++ * \brief 设置获得焦点的对象 ++ * \param object 对象指针 ++ */ ++void QOpenHarmonyPlatformInputContext::setFocusObject(QObject *object) ++{ ++ if (object != m_focusObject) { ++ m_focusObject = object; ++ reset(); ++ } ++ QPlatformInputContext::setFocusObject(object); ++} ++ ++bool QOpenHarmonyPlatformInputContext::beginBatchEdit() ++{ ++ ++m_batchEditNestingLevel; ++ return true; ++} ++ ++bool QOpenHarmonyPlatformInputContext::endBatchEdit() ++{ ++ if (--m_batchEditNestingLevel == 0) { //ending batch edit mode ++ //focusObjectStartComposing(); ++ updateCursorPosition(); ++ } ++ return true; ++} ++ ++QOpenHarmonyPlatformInputContext *QOpenHarmonyPlatformInputContext::openHarmonyInputContext() ++{ ++ return m_openHarmonyInputContext; +} + +void QOpenHarmonyPlatformInputContext::setPlatformIntegration(QOpenHarmonyPlatformIntegration *integration) @@ -7393,63 +8278,6 @@ index 0000000000..b73ae5a569 + QWindowSystemInterface::handleTouchEvent(window, touchDevice, m_touchPoints); +} + -+void QOpenHarmonyPlatformInputContext::reset() -+{ -+ qInfo() << "QOpenHarmonyPlatformInputContext<===================reset:"; -+ clearInput(); -+} -+ -+void QOpenHarmonyPlatformInputContext::commit() -+{ -+ qInfo() << "QOpenHarmonyPlatformInputContext<===================commit:" << m_composingText; -+} -+ -+void QOpenHarmonyPlatformInputContext::showInputPanel() -+{ -+ qInfo() << "QOpenHarmonyPlatformInputContext<===================showInputPanel:"; -+ bool isAttached = m_jsInputCtl->call("isAttached"); -+ if (!isAttached) -+ m_jsInputCtl->call("attach", QVariant(qlonglong(static_cast(this)))); -+} -+ -+void QOpenHarmonyPlatformInputContext::hideInputPanel() -+{ -+ m_jsInputCtl->call("detach"); -+ clearInput(); -+ qInfo() << "QOpenHarmonyPlatformInputContext<===================hideInputPanel:"; -+} -+ -+bool QOpenHarmonyPlatformInputContext::isAnimating() const -+{ -+ return false; -+} -+ -+QRectF QOpenHarmonyPlatformInputContext::keyboardRect() const -+{ -+ //TODO acquire softkeyborad rect -+ return QRectF(); -+} -+ -+void QOpenHarmonyPlatformInputContext::update(Qt::InputMethodQueries) -+{ -+ // qInfo() << "QOpenHarmonyPlatformInputContext<============================update"; -+} -+ -+void QOpenHarmonyPlatformInputContext::setFocusObject(QObject *object) -+{ -+ if (object != m_focusObject) { -+ m_focusObject = object; -+ reset(); -+ } -+ QPlatformInputContext::setFocusObject(object); -+} -+ -+bool QOpenHarmonyPlatformInputContext::isInputPanelVisible() const -+{ -+ //TODO acquire softkeyborad visable -+ return false; -+} -+ +void QOpenHarmonyPlatformInputContext::setComposingText(const QString &text) +{ + m_composingText = text; @@ -7493,6 +8321,7 @@ index 0000000000..b73ae5a569 + m_composingText.clear(); + m_composingTextStart = -1; + m_composingCursor = -1; ++ // m_extractedText.clear(); +} + +void QOpenHarmonyPlatformInputContext::commitText(QString text) @@ -7551,8 +8380,6 @@ index 0000000000..b73ae5a569 + return; + + const int absolutecursorPos = getAbsoluteCursorPosition(query); -+ qWarning() << absolutecursorPos << "<============"; -+ + const QString &selectText = query->value(Qt::ImCurrentSelection).toString(); + const int selectLength = selectText.length(); + int beginPos = absolutecursorPos; @@ -7620,16 +8447,85 @@ index 0000000000..b73ae5a569 + return m_composingCursor != -1; +} + ++void QOpenHarmonyPlatformInputContext::focusObjectStartComposing() ++{ ++ if (focusObjectIsComposing() || m_composingText.isEmpty()) ++ return; ++ ++ // Composing strings containing newline characters are rare and may cause problems ++ if (m_composingText.contains(QLatin1Char('\n'))) ++ return; ++ ++ QSharedPointer query = focusObjectInputMethodQuery(); ++ if (!query) ++ return; ++ ++ if (query->value(Qt::ImCursorPosition).toInt() != query->value(Qt::ImAnchorPosition).toInt()) ++ return; ++ ++ const int absoluteCursorPos = getAbsoluteCursorPosition(query); ++ if (absoluteCursorPos < m_composingTextStart ++ || absoluteCursorPos > m_composingTextStart + m_composingText.length()) ++ return; ++ ++ m_composingCursor = absoluteCursorPos; ++ ++ QTextCharFormat underlined; ++ underlined.setFontUnderline(true); ++ ++ QInputMethodEvent event(m_composingText, { ++ { QInputMethodEvent::Cursor, absoluteCursorPos - m_composingTextStart, 1 }, ++ { QInputMethodEvent::TextFormat, 0, m_composingText.length(), underlined } ++ }); ++ ++ event.setCommitString({}, m_composingTextStart - absoluteCursorPos, m_composingText.length()); ++ ++ QGuiApplication::sendEvent(m_focusObject, &event); ++} ++ ++bool QOpenHarmonyPlatformInputContext::focusObjectStopComposing() ++{ ++ if (!focusObjectIsComposing()) ++ return true; // not composing ++ ++ QSharedPointer query = focusObjectInputMethodQuery(); ++ if (query.isNull()) ++ return false; ++ ++ const int blockPos = getBlockPosition(query); ++ const int localCursorPos = m_composingCursor - blockPos; ++ ++ m_composingCursor = -1; ++ ++ { ++ // commit the composing test ++ QList attributes; ++ QInputMethodEvent event(QString(), attributes); ++ event.setCommitString(m_composingText); ++ sendInputMethodEvent(&event); ++ } ++ { ++ // Moving Qt's cursor to where the preedit cursor used to be ++ QList attributes; ++ attributes.append( ++ QInputMethodEvent::Attribute(QInputMethodEvent::Selection, localCursorPos, 0)); ++ QInputMethodEvent event(QString(), attributes); ++ sendInputMethodEvent(&event); ++ } ++ ++ return true; ++} ++ + +QT_END_NAMESPACE + + diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatforminputcontext.h b/src/plugins/platforms/openharmony/qopenharmonyplatforminputcontext.h new file mode 100644 -index 0000000000..7e2a334fd5 +index 0000000000..62fb0fadfc --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatforminputcontext.h -@@ -0,0 +1,74 @@ +@@ -0,0 +1,95 @@ +#ifndef QOPENHARMONYPLATFORMINPUTCONTEXT_H +#define QOPENHARMONYPLATFORMINPUTCONTEXT_H + @@ -7637,6 +8533,8 @@ index 0000000000..7e2a334fd5 +#include +#include +#include ++#include ++#include + +class QOpenHarmonyJsObject; +class QOpenHarmonyPlatformIntegration; @@ -7650,31 +8548,47 @@ index 0000000000..7e2a334fd5 + QOpenHarmonyPlatformInputContext(); + ~QOpenHarmonyPlatformInputContext() override; + -+ void clear(); -+ void touchBegin(); -+ void touchEnd(int id); ++ /* 判断输入上下文是否有效 */ ++ 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; ++ QRectF keyboardRect() const override; ++ ++ bool isAnimating() const override; ++ + void showInputPanel() override; + void hideInputPanel() override; -+ bool isAnimating() const override; -+ QRectF keyboardRect() const override; -+ void update(Qt::InputMethodQueries) override; -+ void setFocusObject(QObject *object) override; -+ bool isValid() const override { return true; } + bool isInputPanelVisible() const override; ++ ++ void setFocusObject(QObject *object) override; ++ ++ bool beginBatchEdit(); ++ bool endBatchEdit(); ++ ++ void clear(); ++ void touchBegin(); ++ void touchEnd(int id); + void setComposingText(const QString &text); + void touchAdd(int id, int action, float force, float x, float y); + static QOpenHarmonyPlatformInputContext * openHarmonyInputContext(); -+ void invokeAction(QInputMethod::Action act, int cursorPosition) override; + void setPlatformIntegration(QOpenHarmonyPlatformIntegration *integration); + static napi_value init(napi_env env, napi_value exports); -+ void sendKeyEvent(QKeyEvent *event); ++ void dispatchKeyEvent(OH_NativeXComponent_KeyCode code, ++ OH_NativeXComponent_KeyAction action, ++ OH_NativeXComponent_EventSourceType stype, int64_t deviceId, int64_t timeStamp); ++ Q_INVOKABLE void sendShortcut(int key); + -+public Q_SLOTS: ++public Q_SLOTS: ++ void updateCursorPosition(); + void mousePress(float x, float y); + void mouseRelease(float x, float y); -+ void touchDown(float x, float y); ++ void touchDown(float x, float y); + +private Q_SLOTS: + void clearInput(); @@ -7685,7 +8599,9 @@ index 0000000000..7e2a334fd5 + +private: + bool focusObjectIsComposing() const; -+ void sendInputMethodEvent(QInputMethodEvent *event); ++ void focusObjectStartComposing(); ++ bool focusObjectStopComposing(); ++ void sendInputMethodEvent(QInputMethodEvent *event); + QSharedPointer focusObjectInputMethodQuery(Qt::InputMethodQueries queries = Qt::ImQueryAll); + +private: @@ -7693,11 +8609,12 @@ index 0000000000..7e2a334fd5 + int m_composingTextStart; + int m_composingCursor; + QObject *m_focusObject; ++ int m_batchEditNestingLevel; ++ QSet m_mpd; /* 记录按下的修饰键 */ + bool m_ignoreMouseEvents = false; + QMetaObject::Connection m_updateCursorPosConnection; + QOpenHarmonyPlatformIntegration *m_integration = nullptr; -+ QList m_touchPoints; -+ ++ QList m_touchPoints; + QSharedPointer m_jsInputCtl; +}; + @@ -7706,7 +8623,7 @@ index 0000000000..7e2a334fd5 +#endif // QOPENHARMONYPLATFORMINPUTCONTEXT_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformintegration.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatformintegration.cpp new file mode 100644 -index 0000000000..c8cb187363 +index 0000000000..c397f8fe4f --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformintegration.cpp @@ -0,0 +1,296 @@ @@ -7900,11 +8817,11 @@ index 0000000000..c8cb187363 + } + return QPlatformIntegration::defaultWindowState(flags); +} -+ ++/* NOTE 改主题名称和加载的样式插件相关联 */ +static const QLatin1String openharmonyThemeName("openharmony"); +QStringList QOpenHarmonyPlatformIntegration::themeNames() const +{ -+ return QStringList(QString(openharmonyThemeName)); ++ return QStringList{ "harmonyos", QString(openharmonyThemeName) }; +} + +QPlatformTheme *QOpenHarmonyPlatformIntegration::createPlatformTheme(const QString &name) const @@ -9036,18 +9953,76 @@ index 0000000000..20bec988ab +#endif diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformtheme.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatformtheme.cpp new file mode 100644 -index 0000000000..e10fd6b9a1 +index 0000000000..84b3ec2649 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformtheme.cpp -@@ -0,0 +1,42 @@ +@@ -0,0 +1,119 @@ ++#include ++#include ++#include +#include "qopenharmonyplatformtheme.h" +#include "qopenharmonyplatformdialoghelpers.h" + +#include ++#include + -+QOpenHarmonyPlatformTheme::QOpenHarmonyPlatformTheme() ++static QPalette qt_harmonyPalette() +{ ++#if 1 ++ QColor base("#FFFFFF"); ++ QColor text("#182431"); ++ QColor window("#FFFFFF"); ++ QColor button("#0C182431"); ++ QColor windowText("#182431"); ++ QColor brightText("#FFFFFF"); ++ QColor dark = button.darker(); ++ QColor light = button.lighter(); ++ QColor mid = button.lighter(130); ++ ++ QPalette harmonyPalette(windowText, button, light, dark, mid, text, brightText, base, window); ++ ++ return harmonyPalette; ++#endif ++ ++#if 0 ++ QColor backGround(239, 239, 239); ++ QColor light = backGround.lighter(150); ++ QColor mid(backGround.darker(130)); ++ QColor midLight = mid.lighter(110); ++ QColor base = Qt::white; ++ QColor disabledBase(backGround); ++ QColor dark = backGround.darker(150); ++ QColor darkDisabled = QColor(209, 209, 209).darker(110); ++ QColor text = Qt::black; ++ QColor hightlightedText = Qt::white; ++ QColor disabledText = QColor(190, 190, 190); ++ QColor button = backGround; ++ QColor shadow = dark.darker(135); ++ QColor disabledShadow = shadow.lighter(150); ++ ++ QPalette fusionPalette(Qt::black,backGround,light,dark,mid,text,base); ++ fusionPalette.setBrush(QPalette::Midlight, midLight); ++ fusionPalette.setBrush(QPalette::Button, button); ++ fusionPalette.setBrush(QPalette::Shadow, shadow); ++ fusionPalette.setBrush(QPalette::HighlightedText, hightlightedText); ++ ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::Text, disabledText); ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::WindowText, disabledText); ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledText); ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::Base, disabledBase); ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::Dark, darkDisabled); ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::Shadow, disabledShadow); ++ ++ fusionPalette.setBrush(QPalette::Active, QPalette::Highlight, QColor(48, 140, 198)); ++ fusionPalette.setBrush(QPalette::Inactive, QPalette::Highlight, QColor(48, 140, 198)); ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::Highlight, QColor(145, 145, 145)); ++ return fusionPalette; ++#endif ++} + ++QOpenHarmonyPlatformTheme::QOpenHarmonyPlatformTheme() ++{ ++ QGuiApplication::setPalette(qt_harmonyPalette()); +} + +QString QOpenHarmonyPlatformTheme::standardButtonText(int button) const @@ -9071,6 +10046,15 @@ index 0000000000..e10fd6b9a1 + return true; +} + ++const QPalette *QOpenHarmonyPlatformTheme::palette(Palette type) const ++{ ++ if (type == QPlatformTheme::SystemPalette) { ++ QPalette *p = new QPalette(qt_harmonyPalette()); ++ return p; ++ } ++ return nullptr; ++} ++ +QPlatformDialogHelper *QOpenHarmonyPlatformTheme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const +{ + switch (type) { @@ -9082,23 +10066,36 @@ index 0000000000..e10fd6b9a1 + return 0; + } +} ++ ++QVariant QOpenHarmonyPlatformTheme::themeHint(ThemeHint hint) const ++{ ++ switch(hint) { ++ case ThemeHint::StyleNames: ++ return QVariant(QStringList{ "harmonyos", "openharmony" }); /* FIXME 暂时认为OpenHarmony HarmonyOS是两种不同的主题样式 */ ++ default: ++ return QPlatformTheme::themeHint(hint); ++ } ++} diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformtheme.h b/src/plugins/platforms/openharmony/qopenharmonyplatformtheme.h new file mode 100644 -index 0000000000..06de62426a +index 0000000000..34ee717e33 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformtheme.h -@@ -0,0 +1,15 @@ +@@ -0,0 +1,18 @@ +#ifndef QOPENHARMONYPLATFORMTHEME_H +#define QOPENHARMONYPLATFORMTHEME_H + ++#include +#include + +class QOpenHarmonyPlatformTheme: public QPlatformTheme +{ +public: + QOpenHarmonyPlatformTheme(); ++ 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; +}; + @@ -9389,10 +10386,10 @@ index 0000000000..02a723f2c0 +#endif // QOPENHARMONYPLATFORMWINDOW_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyxcomponent.cpp b/src/plugins/platforms/openharmony/qopenharmonyxcomponent.cpp new file mode 100644 -index 0000000000..3323641bb0 +index 0000000000..0d43504bb1 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyxcomponent.cpp -@@ -0,0 +1,635 @@ +@@ -0,0 +1,257 @@ +#include +#include + @@ -9404,8 +10401,6 @@ index 0000000000..3323641bb0 +#include "qopenharmonyplatformwindow.h" +#include "qopenharmonylog.h" +#include "qopenharmonymain.h" -+#include -+#include + +QOpenHarmonyXComponent::QOpenHarmonyXComponent(OH_NativeXComponent *component) + : m_nativeComponent(component) @@ -9464,9 +10459,8 @@ index 0000000000..3323641bb0 +} + +void QOpenHarmonyXComponent::dispatchKeyEvent(OH_NativeXComponent *component, void *window) -+{ ++{ + Q_UNUSED(window); -+ + QOpenHarmonyPlatformInputContext *context = QOpenHarmonyPlatformInputContext::openHarmonyInputContext(); + if (Q_NULLPTR == context) + return; @@ -9495,385 +10489,9 @@ index 0000000000..3323641bb0 + if (Q_NULLPTR == context) + return; +#endif -+ static QHash sKeyType{ -+ { OH_NATIVEXCOMPONENT_KEY_ACTION_DOWN, QEvent::KeyPress }, -+ { OH_NATIVEXCOMPONENT_KEY_ACTION_UP, QEvent::KeyRelease }, -+ }; -+ -+ -+ static QHash 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_Back }, -+ { KEY_GRAVE, Qt::Key_Apostrophe }, -+ { 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_Return }, -+ //{ 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 } -+ }; ++ context->dispatchKeyEvent(code, action, sourceType, deviceId, timeStamp); + -+ static QHash 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}, -+ }; -+ static int nativeModifier = Qt::NoModifier; -+ if (sKeyModifers.keys().contains(code)) -+ nativeModifier |= code; -+ -+ Qt::Key k = sKeyMap.value(code, Qt::Key_unknown); -+ QEvent::Type t = sKeyType.value(action, QEvent::None); -+ Qt::KeyboardModifiers modifiers(Qt::NoModifier); -+ modifiers |= sKeyModifers.value(code, Qt::NoModifier); -+ -+ QKeyEvent kEvent(t, k, modifiers, code, code, nativeModifier); -+ context->sendKeyEvent(&kEvent); ++ //nativeModifier = Qt::NoModifier; + //QWindowSystemInterface::handleKeyEvent(Q_NULLPTR, ulong(timeStamp), t, k, modifiers); + + } else { @@ -9963,6 +10581,7 @@ index 0000000000..3323641bb0 + } + + ret = OH_NativeXComponent_RegisterKeyEventCallback(component, &QOpenHarmonyXComponent::dispatchKeyEvent); ++ qWarning() << "OH_NativeXComponent_RegisterKeyEventCallback ret:" << ret; + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) + LOGI("set surface keybord callback failed"); + diff --git a/patch/v5.12.12/qtconnectivity.patch b/patch/v5.12.12/qtconnectivity.patch index 10cdda7f94..ecdefb517d 100644 --- a/patch/v5.12.12/qtconnectivity.patch +++ b/patch/v5.12.12/qtconnectivity.patch @@ -163,7 +163,7 @@ index 00000000..5a2d24cf +#endif // BLUETOOTHDATARECEIVER_P_H diff --git a/src/bluetooth/openharmony/lowenergynotificationhub.cpp b/src/bluetooth/openharmony/lowenergynotificationhub.cpp new file mode 100644 -index 00000000..ded1be45 +index 00000000..e757d324 --- /dev/null +++ b/src/bluetooth/openharmony/lowenergynotificationhub.cpp @@ -0,0 +1,367 @@ @@ -216,7 +216,7 @@ index 00000000..ded1be45 + } + + hubMap()->insert(jsToCtoken, this); -+ m_jsBluetoothLe->call("setQtObject", jsToCtoken); ++ m_jsBluetoothLe->callWithoutReturn("setQtObject", jsToCtoken); + lock.unlock(); +} + @@ -1075,7 +1075,7 @@ index 00000000..5ddd0e36 +#endif // OPENHARMONYSERVICEDISCOVERYRECEIVER_H diff --git a/src/bluetooth/openharmony/serveracceptancethread.cpp b/src/bluetooth/openharmony/serveracceptancethread.cpp new file mode 100644 -index 00000000..193f8371 +index 00000000..d9e11afe --- /dev/null +++ b/src/bluetooth/openharmony/serveracceptancethread.cpp @@ -0,0 +1,201 @@ @@ -1228,14 +1228,14 @@ index 00000000..193f8371 + tempUuid.remove(0,1); //remove first '{' + + bool isSecure = !(secFlags == QBluetooth::NoSecurity); -+ jsThread->call("listen", tempUuid, m_serviceName, isSecure); ++ jsThread->callWithoutReturn("listen", tempUuid, m_serviceName, isSecure); +} + +void ServerAcceptanceThread::stop() +{ + if (jsThread->isValid()) { + qCDebug(QT_BT_OPENHARMONY) << "Closing server socket"; -+ jsThread->call("close"); ++ jsThread->callWithoutReturn("close"); + } +} + @@ -1277,7 +1277,7 @@ index 00000000..193f8371 +{ + while (!pendingSockets.isEmpty()) { + int socket = pendingSockets.takeFirst(); -+ jsThread->call("closeClient", socket); ++ jsThread->callWithoutReturn("closeClient", socket); + } +} diff --git a/src/bluetooth/openharmony/serveracceptancethread_p.h b/src/bluetooth/openharmony/serveracceptancethread_p.h @@ -1351,7 +1351,7 @@ index 6eab11fb..49d27923 100644 QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_ohos.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_ohos.cpp new file mode 100644 -index 00000000..060c8aef +index 00000000..6cf0e437 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_ohos.cpp @@ -0,0 +1,276 @@ @@ -1595,7 +1595,7 @@ index 00000000..060c8aef + m_active = BtleScanActive; + + -+ m_jsBluetoothManager->call("startBLEScan"); ++ m_jsBluetoothManager->callWithoutReturn("startBLEScan"); + + // wait interval and sum up what was found + if (!leScanTimeout) { @@ -1616,7 +1616,7 @@ index 00000000..060c8aef + +void QBluetoothDeviceDiscoveryAgentPrivate::stopLowEnergyScan() +{ -+ m_jsBluetoothManager->call("stopBLEScan"); ++ m_jsBluetoothManager->callWithoutReturn("stopBLEScan"); + + m_active = NoScanActive; + @@ -1701,7 +1701,7 @@ index 9f6d1e1b..59bdd36b 100644 diff --git a/src/bluetooth/qbluetoothlocaldevice_ohos.cpp b/src/bluetooth/qbluetoothlocaldevice_ohos.cpp new file mode 100644 -index 00000000..dfe5f7b2 +index 00000000..d3d3869d --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice_ohos.cpp @@ -0,0 +1,332 @@ @@ -1910,12 +1910,12 @@ index 00000000..dfe5f7b2 + setHostMode(QBluetoothLocalDevice::HostPoweredOff); + d_ptr->pendingHostModeTransition = true; + } else { -+ d_ptr->m_jsBluetoothManager->call("setScanMode", 1); ++ d_ptr->m_jsBluetoothManager->callWithoutReturn("setScanMode", 1); + } + } else if (mode == QBluetoothLocalDevice::HostDiscoverable) { -+ d_ptr->m_jsBluetoothManager->call("setScanMode", 2); ++ d_ptr->m_jsBluetoothManager->callWithoutReturn("setScanMode", 2); + } else if (mode == QBluetoothLocalDevice::HostDiscoverableLimitedInquiry) { -+ d_ptr->m_jsBluetoothManager->call("setScanMode", 3); ++ d_ptr->m_jsBluetoothManager->callWithoutReturn("setScanMode", 3); + } +} + @@ -2473,7 +2473,7 @@ index 53ce98e5..d9c9a9b8 100644 } diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_ohos.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_ohos.cpp new file mode 100644 -index 00000000..ffc400d6 +index 00000000..ae6c7cfc --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_ohos.cpp @@ -0,0 +1,445 @@ @@ -2647,7 +2647,7 @@ index 00000000..ffc400d6 + _q_serviceDiscoveryFinished(); + } + qWarning() << "<===============LLLLL---"; -+ m_jsAdapter->call("fetchService"); ++ m_jsAdapter->callWithoutReturn("fetchService"); + qWarning() << "<===============LLLLL---222"; + } +} @@ -3785,7 +3785,7 @@ index 6b4c17d6..0115700f 100644 return; diff --git a/src/bluetooth/qlowenergycontroller_ohos.cpp b/src/bluetooth/qlowenergycontroller_ohos.cpp new file mode 100644 -index 00000000..73fb98eb +index 00000000..efca9358 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_ohos.cpp @@ -0,0 +1,871 @@ @@ -3826,7 +3826,7 @@ index 00000000..73fb98eb +{ + if (role == QLowEnergyController::PeripheralRole) { + if (hub) -+ hub->jsObject()->call("disconnectServer"); ++ hub->jsObject()->callWithoutReturn("disconnectServer"); + } +} + @@ -3905,9 +3905,9 @@ index 00000000..73fb98eb + + if (hub) { + if (role == QLowEnergyController::PeripheralRole) -+ hub->jsObject()->call("disconnectServer"); ++ hub->jsObject()->callWithoutReturn("disconnectServer"); + else -+ hub->jsObject()->call("disconnect"); ++ hub->jsObject()->callWithoutReturn("disconnect"); + } + + if (oldState == QLowEnergyController::ConnectingState) @@ -4585,7 +4585,7 @@ index 00000000..73fb98eb +void QLowEnergyControllerPrivateOpenHarmony::stopAdvertising() +{ + setState(QLowEnergyController::UnconnectedState); -+ hub->jsObject()->call("stopAdvertising"); ++ hub->jsObject()->callWithoutReturn("stopAdvertising"); +} + +void QLowEnergyControllerPrivateOpenHarmony::requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) @@ -6102,7 +6102,7 @@ index 00000000..bd9cc9a5 +#endif // QNEARFIELDMANAGER_OPENHARMONY_P_H diff --git a/src/nfc/qnearfieldtarget_openharmony.cpp b/src/nfc/qnearfieldtarget_openharmony.cpp new file mode 100644 -index 00000000..fa9533e2 +index 00000000..6de0a783 --- /dev/null +++ b/src/nfc/qnearfieldtarget_openharmony.cpp @@ -0,0 +1,366 @@ @@ -6324,7 +6324,7 @@ index 00000000..fa9533e2 + + const QNdefMessage &message = messages.first(); + QByteArray ba = message.toByteArray(); -+ m_jsTag->call(writeMethod, ba); ++ m_jsTag->callWithoutReturn(writeMethod, ba); + + if (!m_keepConnection) + disconnect(); // IOException at this point does not matter anymore. @@ -6586,7 +6586,7 @@ index 00000000..cb8a815b +#endif // QNEARFIELDTARGET_OPENHARMONY_P_H diff --git a/src/openharmony/bluetooth/bluetooth.pro b/src/openharmony/bluetooth/bluetooth.pro new file mode 100644 -index 00000000..fa4a2436 +index 00000000..f063639d --- /dev/null +++ b/src/openharmony/bluetooth/bluetooth.pro @@ -0,0 +1,9 @@ @@ -6594,7 +6594,7 @@ index 00000000..fa4a2436 + +CONFIG -= qt + -+templates.files += $$files($$PWD/native/QtBluetooth/*.ts, true) ++templates.files += $$files($$PWD/native/QtBluetooth/*, true) +templates.path = $$[QT_INSTALL_PREFIX]/openharmony/qtconnectivity +templates.base = $$PWD + @@ -8282,10 +8282,10 @@ index 00000000..be9b65ab \ No newline at end of file diff --git a/src/openharmony/nfc/native/QtNfc/JsNfc.ts b/src/openharmony/nfc/native/QtNfc/JsNfc.ts new file mode 100644 -index 00000000..cf7558d8 +index 00000000..baf23923 --- /dev/null +++ b/src/openharmony/nfc/native/QtNfc/JsNfc.ts -@@ -0,0 +1,63 @@ +@@ -0,0 +1,60 @@ +import controller from '@ohos.nfc.controller'; +import tag from '@ohos.nfc.tag'; +import HashMap from '@ohos.util.HashMap'; @@ -8296,10 +8296,9 @@ index 00000000..cf7558d8 + +export class JsNfc { + private tagsIndex: number = 0; -+ private tags: HashMap = null; + + constructor() { -+ this.tags = new HashMap; ++ + } + + createTag(tagInfo: tag.TagInfo) { @@ -8307,11 +8306,9 @@ index 00000000..cf7558d8 + JsLogger.info("no TagInfo to be created, ignore it."); + return; + } -+ let nfcTag = new JsNfcTag(tagInfo); + this.tagsIndex++; -+ this.tags.set(this.tagsIndex, nfcTag); + let name = "tagInfo" + this.tagsIndex; -+ JsDataStore.initObject(name, nfcTag); ++ JsDataStore.getJsObjectLoader().createObject("JsNfcTag", name, tagInfo); + JsDataStore.getQtNativeModule("QtNfc").nfcTargetDetected(name) + } + @@ -8325,7 +8322,7 @@ index 00000000..cf7558d8 + let discTech = [tag.NFC_A, tag.NFC_B]; + tag.registerForegroundDispatch(JsDataStore.getElementName(), discTech, (err : BusinessError, tagInfo : tag.TagInfo) =>{ + JsLogger.info("foreground callback: tag found tagInfo = %{public}s", JSON.stringify(tagInfo)); -+ JsDataStore.getQtNativeModule("QtNfc").createTag(tagInfo); ++ this.createTag(tagInfo); + }); + } catch (e) { + JsLogger.error("registerForegroundDispatch error: " + e.message); @@ -8352,24 +8349,27 @@ index 00000000..cf7558d8 \ No newline at end of file diff --git a/src/openharmony/nfc/native/QtNfc/JsNfcModule.ts b/src/openharmony/nfc/native/QtNfc/JsNfcModule.ts new file mode 100644 -index 00000000..83474c74 +index 00000000..f2f58169 --- /dev/null +++ b/src/openharmony/nfc/native/QtNfc/JsNfcModule.ts -@@ -0,0 +1,34 @@ -+import { JsQtModule } from '../QtCore/JsQtModule'; +@@ -0,0 +1,37 @@ ++import { JsQtModule, ObjectBuilder } from '../QtCore/JsQtModule'; +import JsDataStore from '../QtCore/JsDataStore'; +import JsLogger from '../QtCore/JsLogger'; +import { JsNfc } from './JsNfc'; +import { JsNfcTag } from './JsNfcTag'; ++import tag from '@ohos.nfc.tag'; + +class JsNfcModule extends JsQtModule { + + public constructor() { + super() -+ this.moduleJsObjects = { -+ JsNfc, -+ JsNfcTag -+ }; ++ this.moduleJsObjects.set("JsNfc", new ObjectBuilder<[]>(() =>{ ++ return new JsNfc(); ++ })); ++ this.moduleJsObjects.set("JsNfc", new ObjectBuilder<[tag.TagInfo]>((tagInfo: tag.TagInfo) =>{ ++ return new JsNfcTag(tagInfo); ++ })); + this.loadQtModule(); + } + @@ -8571,7 +8571,7 @@ index 00000000..ed1834b7 \ No newline at end of file diff --git a/src/openharmony/nfc/nfc.pro b/src/openharmony/nfc/nfc.pro new file mode 100644 -index 00000000..00614707 +index 00000000..cbbfd2f8 --- /dev/null +++ b/src/openharmony/nfc/nfc.pro @@ -0,0 +1,11 @@ @@ -8579,7 +8579,7 @@ index 00000000..00614707 + +CONFIG -= qt + -+templates.files += $$files($$PWD/native/QtNfc/*.ts, true) ++templates.files += $$files($$PWD/native/QtNfc/*, true) +templates.path = $$[QT_INSTALL_PREFIX]/openharmony/qtconnectivity +templates.base = $$PWD + diff --git a/patch/v5.12.12/qtdeclarative.patch b/patch/v5.12.12/qtdeclarative.patch index 2919763bc8..88fa7a6ea4 100644 --- a/patch/v5.12.12/qtdeclarative.patch +++ b/patch/v5.12.12/qtdeclarative.patch @@ -90,6 +90,50 @@ index 99031e1e74..dcfc473da2 100644 return toLocalFile(url); } +diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp +index ba8dce4b6e..aece49ed34 100644 +--- a/src/qml/qml/qqmlimport.cpp ++++ b/src/qml/qml/qqmlimport.cpp +@@ -1823,6 +1823,19 @@ QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e) + + addImportPath(QStringLiteral("qrc:/qt-project.org/imports")); + addImportPath(QCoreApplication::applicationDirPath()); ++/* FIXME 因为鸿蒙权限限制 ++ * 将QML插件的加载和qml脚本的加载进行了区分 ++ */ ++#if defined(Q_OS_OPENHARMONY) ++ addImportPath(QStringLiteral("qrc:/harmony_rcc_bundle/qml")); ++ if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QT_HARMONY_BUNDLED_LIBS_PATH"))) { ++ const QString envImportPath = qEnvironmentVariable("QT_HARMONY_BUNDLED_LIBS_PATH"); ++ QLatin1Char pathSep(':'); ++ QStringList paths = envImportPath.split(pathSep, QString::SkipEmptyParts); ++ for (int ii = paths.count() - 1; ii >= 0; --ii) ++ addPluginPath(paths.at(ii)); ++ } ++#endif + } + + QQmlImportDatabase::~QQmlImportDatabase() +@@ -1862,8 +1875,17 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, + else + resolvedPath = pluginPath; + } +- +- // hack for resources, should probably go away ++/* FIXME 因为鸿蒙安全限制,QML脚本和扩展插件加载路径有区别 ++ * 使用环境变量QT_HARMONY_BUNDLED_LIBS_PATH的值替换鸿蒙rawfile资源文件的路径 ++ * 用以qml扩展插件的加载 ++ */ ++#if defined(Q_OS_OPENHARMONY) ++ if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QT_HARMONY_CACHE_DIR"))) { ++ QString cacheQmlStr = qEnvironmentVariable("QT_HARMONY_CACHE_DIR"); ++ resolvedPath = QString(qmldirPath).replace(cacheQmlStr, pluginPath); ++ } ++#endif ++ // hack for resources, should probably go away + if (resolvedPath.startsWith(Colon)) + resolvedPath = QCoreApplication::applicationDirPath(); + diff --git a/src/qml/qml/qqmlplatform.cpp b/src/qml/qml/qqmlplatform.cpp index 0acf20bbb4..27f22c19a3 100644 --- a/src/qml/qml/qqmlplatform.cpp diff --git a/patch/v5.12.12/qtmultimedia.patch b/patch/v5.12.12/qtmultimedia.patch index 843e74970c..f487b999cd 100644 --- a/patch/v5.12.12/qtmultimedia.patch +++ b/patch/v5.12.12/qtmultimedia.patch @@ -287,11 +287,11 @@ index 000000000..7a3fc0e63 + diff --git a/src/openharmony/native/QtMultiMedia/JsMultiMediaModule.ts b/src/openharmony/native/QtMultiMedia/JsMultiMediaModule.ts new file mode 100644 -index 000000000..851ab4432 +index 000000000..cd08a2070 --- /dev/null +++ b/src/openharmony/native/QtMultiMedia/JsMultiMediaModule.ts -@@ -0,0 +1,38 @@ -+import { JsQtModule } from '../QtCore/JsQtModule'; +@@ -0,0 +1,44 @@ ++import { JsQtModule, ObjectBuilder } from '../QtCore/JsQtModule'; +import JsDataStore from '../QtCore/JsDataStore'; +import JsLogger from '../QtCore/JsLogger'; +import { JsAudioManager } from './JsAudioManager' @@ -303,12 +303,18 @@ index 000000000..851ab4432 + + public constructor() { + super() -+ this.moduleJsObjects = { -+ JsAudioManager, -+ JsMediaRecorder, -+ JsMultimediaUtils, -+ JsCameraManager -+ }; ++ this.moduleJsObjects.set("JsAudioManager", new ObjectBuilder<[]>(() =>{ ++ return new JsAudioManager(); ++ })); ++ this.moduleJsObjects.set("JsMediaRecorder", new ObjectBuilder<[]>(() =>{ ++ return new JsMediaRecorder(); ++ })); ++ this.moduleJsObjects.set("JsMultimediaUtils", new ObjectBuilder<[]>(() =>{ ++ return new JsMultimediaUtils(); ++ })); ++ this.moduleJsObjects.set("JsCameraManager", new ObjectBuilder<[]>(() =>{ ++ return new JsCameraManager(); ++ })); + this.loadQtModule(); + } + @@ -358,7 +364,7 @@ index 000000000..3adf5fe55 +} diff --git a/src/openharmony/openharmony.pro b/src/openharmony/openharmony.pro new file mode 100644 -index 000000000..966d9dcf0 +index 000000000..6f97b7df9 --- /dev/null +++ b/src/openharmony/openharmony.pro @@ -0,0 +1,9 @@ @@ -366,7 +372,7 @@ index 000000000..966d9dcf0 + +CONFIG -= qt + -+templates.files += $$files($$PWD/native/QtMultiMedia/*.ts, true) ++templates.files += $$files($$PWD/native/QtMultiMedia/*, true) +templates.path = $$[QT_INSTALL_PREFIX]/openharmony/qtmultimedia +templates.base = $$PWD + diff --git a/patch/v5.12.12/qtsensors.patch b/patch/v5.12.12/qtsensors.patch index 6a1ea061b5..3c6c96f30b 100644 --- a/patch/v5.12.12/qtsensors.patch +++ b/patch/v5.12.12/qtsensors.patch @@ -137,11 +137,11 @@ index 00000000..51919095 \ No newline at end of file diff --git a/src/openharmony/native/QtSensors/JsSensorsModule.ts b/src/openharmony/native/QtSensors/JsSensorsModule.ts new file mode 100644 -index 00000000..1d426bcf +index 00000000..8e328f10 --- /dev/null +++ b/src/openharmony/native/QtSensors/JsSensorsModule.ts -@@ -0,0 +1,24 @@ -+import { JsQtModule } from '../QtCore/JsQtModule'; +@@ -0,0 +1,26 @@ ++import { JsQtModule, ObjectBuilder } from '../QtCore/JsQtModule'; +import JsDataStore from '../QtCore/JsDataStore'; +import JsSensor from './JsSensor'; +import JsSensorManager from './JsSensorManager'; @@ -150,10 +150,12 @@ index 00000000..1d426bcf + + public constructor() { + super() -+ this.moduleJsObjects = { -+ JsSensor, -+ JsSensorManager -+ }; ++ this.moduleJsObjects.set("JsSensor", new ObjectBuilder<[number]>((id: number) =>{ ++ return new JsSensor(id); ++ })); ++ this.moduleJsObjects.set("JsSensorManager", new ObjectBuilder<[]>(() =>{ ++ return new JsSensorManager(); ++ })); + this.loadQtModule(); + } + @@ -1132,7 +1134,7 @@ index 00000000..aa0907df +#endif // SENSORBACKEND_H diff --git a/src/plugins/sensors/openharmony/sensormanager.cpp b/src/plugins/sensors/openharmony/sensormanager.cpp new file mode 100644 -index 00000000..cfa50cb0 +index 00000000..b368d556 --- /dev/null +++ b/src/plugins/sensors/openharmony/sensormanager.cpp @@ -0,0 +1,114 @@ @@ -1209,12 +1211,12 @@ index 00000000..cfa50cb0 + +void JsSensor::stop(int id) +{ -+ m_jsSensor->call("stop", id); ++ m_jsSensor->callWithoutReturn("stop", id); +} + +void JsSensor::start(int id, int rate) +{ -+ m_jsSensor->call("start", id, rate); ++ m_jsSensor->callWithoutReturn("start", id, rate); +} + +QString JsSensor::hardwareVersion(int id) const diff --git a/patch/v5.15.12/qtbase.patch b/patch/v5.15.12/qtbase.patch index 8f62014a3e..f51264abe8 100644 --- a/patch/v5.15.12/qtbase.patch +++ b/patch/v5.15.12/qtbase.patch @@ -162,7 +162,7 @@ index 573d717eea..94b8dd5666 100644 diff --git a/mkspecs/oh-clang/qmake.conf b/mkspecs/oh-clang/qmake.conf new file mode 100644 -index 0000000000..03139d2b22 +index 0000000000..5bfd38b4f5 --- /dev/null +++ b/mkspecs/oh-clang/qmake.conf @@ -0,0 +1,39 @@ @@ -171,7 +171,7 @@ index 0000000000..03139d2b22 +QMAKE_PLATFORM = openharmony +QMAKE_COMPILER = gcc clang llvm + -+CONFIG += unversioned_soname unversioned_libname plugin_with_soname ++CONFIG += unversioned_soname unversioned_libname plugin_with_soname $$QMAKE_PLATFORM + +include(../common/linux.conf) +include(../common/gcc-base-unix.conf) @@ -660,10 +660,10 @@ index 0000000000..7480dc1c20 +#endif // QOPENHARMONYDEFINES_H diff --git a/src/corelib/kernel/qopenharmonyhelpers.cpp b/src/corelib/kernel/qopenharmonyhelpers.cpp new file mode 100644 -index 0000000000..6ac33f6a4a +index 0000000000..9d2664cae6 --- /dev/null +++ b/src/corelib/kernel/qopenharmonyhelpers.cpp -@@ -0,0 +1,129 @@ +@@ -0,0 +1,132 @@ +#include "qopenharmonyhelpers_p.h" +#include "qopenharmonyjsenvironment.h" +#include "qmutex.h" @@ -688,7 +688,7 @@ index 0000000000..6ac33f6a4a + napi_value variant_to_napi_value(const QVariant &value) + { + napi_value ret = nullptr; -+ QVariant::Type t = value.type(); ++ int t = value.userType(); + switch (t) { + case QVariant::Int: + ret = qJs::createInt32(value.toInt()); @@ -712,7 +712,7 @@ index 0000000000..6ac33f6a4a + ret = qJs::createObject(value.toMap()); + break; + default: -+ //Todo other type ++ ret = qJs::createObjectFromUserType(value); + break; + } + return ret; @@ -743,6 +743,9 @@ index 0000000000..6ac33f6a4a + case QMetaType::QByteArrayList: + ret = QVariant::fromValue(qJs::getByteArrayList(value)); + break; ++ case QMetaType::QRect: ++ ret = qJs::getRect(value); ++ break; + default: + //Todo other type + break; @@ -844,19 +847,27 @@ index 0000000000..0c0bd12c64 +#endif // QJNIHELPERS_H diff --git a/src/corelib/kernel/qopenharmonyjsenvironment.cpp b/src/corelib/kernel/qopenharmonyjsenvironment.cpp new file mode 100644 -index 0000000000..8b8af52eee +index 0000000000..9fb36e755e --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsenvironment.cpp -@@ -0,0 +1,402 @@ +@@ -0,0 +1,425 @@ +#include "qopenharmonyjsenvironment.h" +#include "qopenharmonydefines.h" +#include "qopenharmonyhelpers_p.h" +#include "qopenharmonyjsfunction.h" + ++#include ++ +static napi_threadsafe_function g_threadsafe_call_js_function = nullptr; -+static napi_threadsafe_function g_threadsafe_remove_object_function = nullptr; +napi_env QOpenHarmonyJsEnvironment::m_env = nullptr; +bool QOpenHarmonyJsEnvironment::m_exit = false; ++static QHash g_creators; ++ ++static void cleanup_creators() ++{ ++ qDeleteAll(g_creators); ++ g_creators.clear(); ++} + +static void callJsFunction(napi_env env, napi_value js_cb, void* context, void* data) { + Q_UNUSED(env); @@ -890,6 +901,7 @@ index 0000000000..8b8af52eee + if (g_threadsafe_call_js_function == nullptr) { + LOGW("init call js function failed"); + } ++ qAddPostRoutine(cleanup_creators); +} + +void QOpenHarmonyJsEnvironment::quit() @@ -942,6 +954,19 @@ index 0000000000..8b8af52eee + return result; +} + ++napi_value QOpenHarmonyJsEnvironment::createObjectFromUserType(const QVariant &value) ++{ ++ if (!g_creators.contains(value.userType())) ++ return nullptr; ++ NapiValueCreator *c = g_creators.value(value.userType()); ++ return c->create(value); ++} ++ ++void QOpenHarmonyJsEnvironment::registerCreator(int type, NapiValueCreator *creator) ++{ ++ g_creators.insert(type, creator); ++} ++ +napi_value QOpenHarmonyJsEnvironment::globalObject() { + napi_value _global; + NAPI_CALL(m_env, napi_get_global(m_env, &_global)); @@ -963,14 +988,6 @@ index 0000000000..8b8af52eee + return napi_call_threadsafe_function(g_threadsafe_call_js_function, func, napi_tsfn_blocking) == napi_ok; +} + -+void QOpenHarmonyJsEnvironment::threadSafeRemoveObject(const QString &objectName) -+{ -+ napi_acquire_threadsafe_function(g_threadsafe_remove_object_function); -+ QByteArray dataArray = objectName.toLatin1(); -+ char *_data = dataArray.data(); -+ napi_call_threadsafe_function(g_threadsafe_remove_object_function, (void *)_data, napi_tsfn_blocking); -+} -+ +QString QOpenHarmonyJsEnvironment::getString(napi_value value) +{ + size_t strLen = 0; @@ -1250,22 +1267,52 @@ index 0000000000..8b8af52eee +{ + return getDouble(value); +} ++ ++QRect QOpenHarmonyJsEnvironment::getRect(napi_value value) ++{ ++ int64_t left = getInt64(objectPropertyValue(value, "left")); ++ int64_t top = getInt64(objectPropertyValue(value, "top")); ++ int64_t width = getInt64(objectPropertyValue(value, "width")); ++ int64_t height = getInt64(objectPropertyValue(value, "height")); ++ return QRect(left, top, width, height); ++} diff --git a/src/corelib/kernel/qopenharmonyjsenvironment.h b/src/corelib/kernel/qopenharmonyjsenvironment.h new file mode 100644 -index 0000000000..0390478e5b +index 0000000000..0718f7ee9a --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsenvironment.h -@@ -0,0 +1,122 @@ +@@ -0,0 +1,156 @@ +#ifndef QOPENHARMONYJSENVIRONMENT_H +#define QOPENHARMONYJSENVIRONMENT_H + +#include +#include ++#include + +QT_BEGIN_NAMESPACE +#define qJs QOpenHarmonyJsEnvironment +class QOpenHarmonyJsFunction; + ++struct NapiValueCreator ++{ ++ virtual napi_value create(const QVariant &value) = 0; ++ virtual ~NapiValueCreator() {} ++}; ++ ++template ++struct UserTypeNapiValueCreator : NapiValueCreator ++{ ++ UserTypeNapiValueCreator(std::function &f) : _f(f) {} ++ virtual napi_value create(const QVariant &value) ++ { ++ if (_f && value.canConvert()) { ++ return _f(value.value()); ++ } ++ return nullptr; ++ } ++ std::function _f; ++}; ++ +class Q_CORE_EXPORT QOpenHarmonyJsEnvironment +{ +public: @@ -1296,6 +1343,18 @@ index 0000000000..0390478e5b + + static napi_value createObject(const QVariantMap &map); + ++ static napi_value createObjectFromUserType(const QVariant &value); ++ ++ template ++ static void registerCreator(std::function &f) ++ { ++ int id = qMetaTypeId(); ++ NapiValueCreator *creator = new UserTypeNapiValueCreator(f); ++ registerCreator(id, creator); ++ } ++ ++ static void registerCreator(int type, NapiValueCreator *creator); ++ + static napi_value globalObject(); + + static napi_value globalThis() @@ -1322,7 +1381,6 @@ index 0000000000..0390478e5b + static napi_value callFunction(napi_value object, napi_value function, int argc = 0, const napi_value *argv = nullptr); + + static bool callThreadSafeFunction(QOpenHarmonyJsFunction *func); -+ static void threadSafeRemoveObject(const QString &objectName); + + static QString getString(napi_value value); + @@ -1343,6 +1401,8 @@ index 0000000000..0390478e5b + + static double getDouble(napi_value value); + ++ static QRect getRect(napi_value value); ++ + static napi_value objectPropertyValue(napi_value object, const QString &propertyName); + + static napi_value initJsObjectLoader(napi_env env, napi_callback_info info); @@ -1380,10 +1440,10 @@ index 0000000000..0390478e5b +#endif // QOPENHARMONYJSENVIRONMENT_H diff --git a/src/corelib/kernel/qopenharmonyjsfunction.cpp b/src/corelib/kernel/qopenharmonyjsfunction.cpp new file mode 100644 -index 0000000000..e38c6bd9e0 +index 0000000000..dbe216de8f --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsfunction.cpp -@@ -0,0 +1,206 @@ +@@ -0,0 +1,207 @@ +#include "qopenharmonyjsfunction.h" +#include "qopenharmonyjsenvironment.h" +#include "qopenharmonydefines.h" @@ -1418,11 +1478,13 @@ index 0000000000..e38c6bd9e0 + QOpenHarmonyJsObject *m_jsObject; + QVariant m_result; + int m_resultType; ++ napi_ref m_objectRef; + QBasicAtomicInt m_bResultReceived; // bool +}; + +QOpenHarmonyJsFunctionPrivate::QOpenHarmonyJsFunctionPrivate() + : m_resultType(QVariant::Invalid) ++ , m_objectRef(nullptr) +{ + m_bResultReceived.storeRelease(false); +} @@ -1447,13 +1509,13 @@ index 0000000000..e38c6bd9e0 + break; + } + if (!m_bResultReceived.loadAcquire()) { -+ qWarning() << QString("Wait js method %1 result failded").arg(m_name); ++ LOGW("Wait js method %{public}s result failded", qPrintable(m_name)); + } +} + +bool QOpenHarmonyJsFunctionPrivate::hasResult() const +{ -+ return m_resultType != QVariant::Invalid; ++ return m_resultType != QVariant::Invalid && m_resultType != QMetaType::Void; +} + +napi_value QOpenHarmonyJsFunctionPrivate::then(napi_env env, napi_callback_info info) @@ -1470,11 +1532,17 @@ index 0000000000..e38c6bd9e0 + +void QOpenHarmonyJsFunctionPrivate::setResult(napi_value result) +{ ++ if (m_resultType == QOpenHarmonyJsFunction::JsRefType) { ++ LOGI("Get js method %1 result object ref from callback: %{public}s", qPrintable(m_name)); ++ napi_create_reference(qJs::env(), result, 1, &m_objectRef); ++ m_bResultReceived.storeRelease(true); ++ return; ++ } + m_result = QtHarmonyPrivate::napi_value_to_variant(result, m_resultType); + if (m_result.type() == QVariant::ByteArray) { -+ qDebug() << QString("Get js method %1 result from callback QByteArrary length: %2").arg(m_name).arg(m_result.toByteArray().length()); ++ LOGI("Get js method %{public}s result from callback QByteArrary length: %{public}d", qPrintable(m_name), m_result.toByteArray().length()); + } else { -+ qDebug() << QString("Get js method %1 result from callback:").arg(m_name) << m_result; ++ LOGI("Get js method %{public}s result from callback: %{public}s", qPrintable(m_name), qPrintable(m_result.toString())); + } + m_bResultReceived.storeRelease(true); +} @@ -1511,7 +1579,7 @@ index 0000000000..e38c6bd9e0 + napi_is_promise(qJs::env(), result, &is_promise); + napi_valuetype type; + napi_typeof(qJs::env(), result, &type); -+ qDebug() << "the result type is" << type << "the result is promise:" << is_promise; ++ LOGI("the result type is %{public}d the result is promise: %{public}d", type, is_promise); + if (is_promise) { + napi_value then = qJs::objectPropertyValue(result, "then"); + napi_value func = nullptr; @@ -1533,19 +1601,7 @@ index 0000000000..e38c6bd9e0 +{ + d_ptr->m_bResultReceived.storeRelease(false); + d_ptr->m_args = args; -+ bool printArgs = !args.isEmpty(); -+ for (int i = 0 ;i < args.count(); ++i) { -+ if (args.at(i).type() == QMetaType::QByteArray) { -+ printArgs = false; -+ break; -+ } -+ } -+ if (printArgs) { -+ qDebug() << QString("call js function: %1").arg(d_ptr->m_name) << args; -+ } else { -+ qDebug() << QString("call js function: %1").arg(d_ptr->m_name); -+ } -+ ++ LOGI("call js function %{public}s", qPrintable(d_ptr->m_name)); + if (!qJs::callThreadSafeFunction(this)) + return; + if (!d_ptr->hasResult()) { @@ -1560,9 +1616,14 @@ index 0000000000..e38c6bd9e0 + return d_ptr->m_result; +} + -+napi_value QOpenHarmonyJsFunction::attachedObject() const ++napi_ref QOpenHarmonyJsFunction::refResult() const +{ + Q_D(const QOpenHarmonyJsFunction); ++ return d->m_objectRef; ++} ++ ++napi_value QOpenHarmonyJsFunction::attachedObject() const { ++ Q_D(const QOpenHarmonyJsFunction); + return d->m_jsObject->jsObject(); +} + @@ -1592,10 +1653,10 @@ index 0000000000..e38c6bd9e0 +QT_END_NAMESPACE diff --git a/src/corelib/kernel/qopenharmonyjsfunction.h b/src/corelib/kernel/qopenharmonyjsfunction.h new file mode 100644 -index 0000000000..4c982d1784 +index 0000000000..17fb051a7b --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsfunction.h -@@ -0,0 +1,84 @@ +@@ -0,0 +1,94 @@ +#ifndef QOPENHARMONYJSFUNCTION_H +#define QOPENHARMONYJSFUNCTION_H + @@ -1615,8 +1676,16 @@ index 0000000000..4c982d1784 +{ + Q_DECLARE_PRIVATE(QOpenHarmonyJsFunction) +public: ++ enum { JsRefType = QMetaType::User + 1000 }; + ~QOpenHarmonyJsFunction(); + ++ template ++ void callReturnRef(Args &&...args) { ++ QVariantList params; ++ setResultType(JsRefType); ++ call(packParams(params, std::forward(args)...)); ++ } ++ + template + void call(Args&&... args) + { @@ -1626,7 +1695,7 @@ index 0000000000..4c982d1784 + } + + template -+ void call(Args&&... args) ++ void callWithoutReturn(Args&&... args) + { + QVariantList params; + call(packParams(params, std::forward(args)...)); @@ -1639,6 +1708,8 @@ index 0000000000..4c982d1784 + + QVariant jsResult() const; + ++ napi_ref refResult() const; ++ + napi_value attachedObject() const; + + QString name() const; @@ -1682,10 +1753,10 @@ index 0000000000..4c982d1784 +#endif // QOPENHARMONYJSFUNCTION_H diff --git a/src/corelib/kernel/qopenharmonyjsobject.cpp b/src/corelib/kernel/qopenharmonyjsobject.cpp new file mode 100644 -index 0000000000..9141921922 +index 0000000000..1680e85b69 --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsobject.cpp -@@ -0,0 +1,95 @@ +@@ -0,0 +1,99 @@ +#include "qopenharmonyjsobject.h" +#include "qopenharmonydefines.h" +#include "qopenharmonyjsfunction.h" @@ -1717,14 +1788,13 @@ index 0000000000..9141921922 + : d_ptr(new QOpenHarmonyJsObjectPrivate(objectType, objectName)) +{ + d_ptr->q_ptr = this; -+ // ʹref, ++ // 必须使用ref, 否则会崩溃 + napi_create_reference(qJs::env(), jsObject, 1, &d_ptr->m_jsObject); +} + +QOpenHarmonyJsObject::~QOpenHarmonyJsObject() +{ + napi_delete_reference(qJs::env(), d_ptr->m_jsObject); -+ Q_D(QOpenHarmonyJsObject); +} + +bool QOpenHarmonyJsObject::isValid() const @@ -1745,6 +1815,11 @@ index 0000000000..9141921922 + return function; +} + ++QString QOpenHarmonyJsObject::uniqueName() const ++{ ++ return objectType() + "_" + objectName(); ++} ++ +QString QOpenHarmonyJsObject::objectType() const +{ + Q_D(const QOpenHarmonyJsObject); @@ -1783,10 +1858,10 @@ index 0000000000..9141921922 + diff --git a/src/corelib/kernel/qopenharmonyjsobject.h b/src/corelib/kernel/qopenharmonyjsobject.h new file mode 100644 -index 0000000000..c6c69a6ea1 +index 0000000000..6540813735 --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsobject.h -@@ -0,0 +1,66 @@ +@@ -0,0 +1,79 @@ +#ifndef QOPENHARMONYJSOBJECT_H +#define QOPENHARMONYJSOBJECT_H + @@ -1813,16 +1888,27 @@ index 0000000000..c6c69a6ea1 + + bool isValid() const; + ++ template ++ napi_ref callReturnRef(const QString &jsFunction, Args &&...args) ++ { ++ QOpenHarmonyJsFunction *f = getJsFunction(jsFunction); ++ if (f == nullptr) ++ return nullptr; ++ ++ f->callReturnRef(std::forward(args)...); ++ return f->refResult(); ++ } ++ + template + RET call(const QString &jsFunction, Args&&... args); + + template -+ void call(const QString &jsFunction, Args&&... args) ++ void callWithoutReturn(const QString &jsFunction, Args&&... args) + { + QOpenHarmonyJsFunction *f = getJsFunction(jsFunction); + if (f == nullptr) + return; -+ f->call(std::forward(args)...); ++ f->callWithoutReturn(std::forward(args)...); + } + + QOpenHarmonyJsFunction *getJsFunction(const QString &name) const; @@ -1830,6 +1916,8 @@ index 0000000000..c6c69a6ea1 + QString objectName() const; + QString objectType() const; + ++ QString uniqueName() const; ++ +private: + Q_DISABLE_COPY(QOpenHarmonyJsObject) + QOpenHarmonyJsObject(const QString &objectType, const QString &objectName, napi_value jsObject); @@ -1855,14 +1943,15 @@ index 0000000000..c6c69a6ea1 +#endif // QOPENHARMONYEGLCORE_H diff --git a/src/corelib/kernel/qopenharmonyjsobjectloader.cpp b/src/corelib/kernel/qopenharmonyjsobjectloader.cpp new file mode 100644 -index 0000000000..d2b86a87fd +index 0000000000..ef698869ab --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsobjectloader.cpp -@@ -0,0 +1,169 @@ +@@ -0,0 +1,170 @@ +#include "qopenharmonyjsobjectloader.h" +#include "qopenharmonyjsobject.h" +#include "qopenharmonyjsobjectpool.h" +#include "qopenharmonyhelpers_p.h" ++#include "qopenharmonydefines.h" + +#include +#include @@ -1975,7 +2064,7 @@ index 0000000000..d2b86a87fd + +QSharedPointer QOpenHarmonyJsObjectLoader::create(const QString &objectType, const QString &objectName, const QVariantList &constructArgs) +{ -+ qDebug() << "request js object: " << objectType << objectName; ++ LOGI("request js object: %{public}s %{public}s", qPrintable(objectType), qPrintable(objectName)); + if (objectType.isEmpty()) + return QSharedPointer(); + @@ -2017,7 +2106,7 @@ index 0000000000..d2b86a87fd + break; + } + if (!m_bObjectCreated.loadAcquire()) { -+ qWarning() << QString("create type of %1 js object %2 result failded").arg(objectType).arg(objectName); ++ LOGW("create type of %{public}s js object %{public}s result failded", qPrintable(objectType), qPrintable(objectName)); + } +} + @@ -2072,10 +2161,10 @@ index 0000000000..6ef2855374 +#endif // QOPENHARMONYEGLCORE_H diff --git a/src/corelib/kernel/qopenharmonyjsobjectpool.cpp b/src/corelib/kernel/qopenharmonyjsobjectpool.cpp new file mode 100644 -index 0000000000..3f2c85d689 +index 0000000000..5812add919 --- /dev/null +++ b/src/corelib/kernel/qopenharmonyjsobjectpool.cpp -@@ -0,0 +1,71 @@ +@@ -0,0 +1,72 @@ +#include "qopenharmonyjsobjectpool.h" +#include "qopenharmonydefines.h" +#include "qopenharmonyjsfunction.h" @@ -2117,13 +2206,13 @@ index 0000000000..3f2c85d689 +QSharedPointer QOpenHarmonyJsObjectPoolPrivate::add(const QString &objectType, const QString &objectName, napi_value jsObject) +{ + QSharedPointer object = QSharedPointer::create(objectType, objectName, jsObject); -+ m_jsObjects.insert(uniqueName(objectName, objectType), object); ++ m_jsObjects.insert(object->uniqueName(), object); + return object; +} + +QString QOpenHarmonyJsObjectPoolPrivate::uniqueName(const QString &objectType, const QString &objectName) const +{ -+ return objectName+ "_" + objectType; ++ return objectType + "_" + objectName; +} + +bool QOpenHarmonyJsObjectPool::remove(const QString &name) @@ -2132,12 +2221,13 @@ index 0000000000..3f2c85d689 + if (d->m_jsObjects.contains(name)) { + QSharedPointer object = d->m_jsObjects.take(name); + } ++ return true; +} + +QSharedPointer QOpenHarmonyJsObjectPool::find(const QString &objectType, const QString &objectName) +{ + Q_D(QOpenHarmonyJsObjectPool); -+ return d->m_jsObjects.value(d->uniqueName(objectName, objectType)); ++ return d->m_jsObjects.value(d->uniqueName(objectType, objectName)); +} + +void QOpenHarmonyJsObjectPool::create(const QString &objectType, const QString &objectName, napi_value jsObject) @@ -2496,24 +2586,27 @@ index 0000000000..6a4626655c +}; diff --git a/src/openharmony/native/QtCore/JsApplication.ts b/src/openharmony/native/QtCore/JsApplication.ts new file mode 100644 -index 0000000000..e5bd848229 +index 0000000000..80c3160c50 --- /dev/null +++ b/src/openharmony/native/QtCore/JsApplication.ts -@@ -0,0 +1,156 @@ +@@ -0,0 +1,183 @@ ++import font from '@ohos.font'; ++import fs from '@ohos.file.fs'; +import window from '@ohos.window'; ++import JsLogger from './JsLogger'; +import display from '@ohos.display'; -+import fs from '@ohos.file.fs'; -+import resourceManager from '@ohos.resourceManager'; -+import JsDataStore from './JsDataStore'; ++import { JsWindow } from './JsWindow'; +import { QtQPA } from './JsQtPlatform'; -+import JsLogger from './JsLogger'; ++import JsDataStore from './JsDataStore'; ++import { Font, UIContext } from '@ohos.arkui.UIContext'; +import { JsWindowManager } from './JsWindowManager'; -+import { JsWindow } from './JsWindow'; ++import resourceManager from '@ohos.resourceManager'; + +class JsApplication { + private mainWindow: window.Window = null; + private mainWindowName: string = "opemharmony_qt_mainwindow"; + private qpa: any = QtQPA; ++ private timerId: number | undefined; + + getMainWindow(): window.Window { + return this.mainWindow; @@ -2524,7 +2617,7 @@ index 0000000000..e5bd848229 + } + + addWindow(name: string, window: JsWindow): void { -+ let obj = JsDataStore.getJsObjectLoader().createObject("JsWindowManager", "JsWindowManager"); ++ let obj = JsDataStore.getJsObjectLoader().createObject("JsWindowManager", "JsWindowManager"); + (obj as JsWindowManager).addWindow(name, window); + } + @@ -2540,40 +2633,52 @@ index 0000000000..e5bd848229 + let qtMajorVersion: number = this.qpa.qtMajorVersion(); + let QtCoreModule: any = null; + if (qtMajorVersion == 5) -+ QtCoreModule = await import ("libQt5Core.so"); ++ QtCoreModule = await import("libQt5Core.so"); + else if (qtMajorVersion == 6) -+ QtCoreModule = await import ("libQt6Core.so"); ++ QtCoreModule = await import("libQt6Core.so"); + if (QtCoreModule == null) { + JsLogger.fatal("Cannot load QtCore module"); + return; + } ++ + JsDataStore.setQtMajorVersion(qtMajorVersion); + let QtCore = QtCoreModule.default; -+ QtCore.initJsObjectLoader((type: string, name: string, ...args: any[])=>{ ++ QtCore.initJsObjectLoader((type: string, name: string, ...args: any[]) => { + if (JsDataStore.getJsObjectLoader().hasJsObject(name)) + return JsDataStore.getJsObjectLoader().getJsObject(name) + return JsDataStore.getJsObjectLoader().createObject(type, name, ...args); -+ }, (name: string)=>{ ++ }, (name: string) => { + return JsDataStore.getJsObjectLoader().deleteJsObject(name); + }); + JsDataStore.addQtNativeModule("QPA", this.qpa); + JsDataStore.addQtNativeModule("QtCore", QtCore); + this.mainWindow = windowStage.getMainWindowSync(); + let window = new JsWindow(this.mainWindowName, this.mainWindow); -+ let localStore = new LocalStorage({"name": this.mainWindowName}); ++ let localStore = new LocalStorage({ "name": this.mainWindowName }); + await windowStage.loadContent('pages/Index', localStore); + this.addWindow(this.mainWindowName, window); + if (this.qpa != null) { + let p = this.mainWindow.getWindowProperties(); -+ this.updateQtScreen({width: p.windowRect.width, height: p.windowRect.height}); ++ this.updateQtScreen({ width: p.windowRect.width, height: p.windowRect.height }); + } + this.mainWindow.on("windowSizeChange", this.updateQtScreen); -+ windowStage.on("windowStageEvent", (state)=>{ ++ windowStage.on("windowStageEvent", (state) => { + if (this.qpa != null) + this.qpa.updateApplicationState(state); + JsLogger.info("window stage changed %{public}d", state); + }); ++ ++ /* NOTE 获取字体信息 */ ++ let mainClass = await windowStage.getMainWindow(); ++ let font: Font = mainClass.getUIContext().getFont(); ++ let fontList: Array = new Array(); ++ for (let f of font.getSystemFontList()) { ++ let fontInfo: font.FontInfo = font.getFontByName(f); ++ fontList.push(fontInfo.path); ++ } ++ this.qpa.setFontInfos(fontList); + JsDataStore.setWindowStage(windowStage); ++ + await this.extractFilesToCache(); + this.loadQtApplication(); + } @@ -2586,6 +2691,18 @@ index 0000000000..e5bd848229 + this.qpa.setResourceManager(JsDataStore.getResourceManager()); + let result : boolean = this.qpa.startQtApplication(JsDataStore.getApplicationDirs(), "libentry.so"); + JsLogger.info("load qt application result: %{public}s", result); ++ ++ //周期检测qt应用是否执行完成(1000ms) ++ this.timerId = setInterval(() => { ++ let res = this.qpa.waitForQtAppExit(); ++ if(res == 0) ++ { ++ JsLogger.info("qt application finished"); ++ //鸿蒙程序调用qt程序退出函数 ++ this.quit(); ++ JsDataStore.getContext().getApplicationContext().killAllProcesses(); ++ } ++ }, 1000); + } + + private saveFileToCache(file: resourceManager.RawFileDescriptor, des: string) { @@ -2656,21 +2773,20 @@ index 0000000000..e5bd848229 +} + +export default new JsApplication; -\ No newline at end of file diff --git a/src/openharmony/native/QtCore/JsDataStore.ts b/src/openharmony/native/QtCore/JsDataStore.ts new file mode 100644 -index 0000000000..a43a6e5a97 +index 0000000000..be9a25b667 --- /dev/null +++ b/src/openharmony/native/QtCore/JsDataStore.ts @@ -0,0 +1,136 @@ -+import common from '@ohos.app.ability.common'; +import window from '@ohos.window'; -+import bundleManager from '@ohos.bundle.bundleManager'; -+import resourceManager from '@ohos.resourceManager'; +import HashMap from '@ohos.util.HashMap'; +import { JsQtModule } from './JsQtModule' +import deviceInfo from '@ohos.deviceInfo'; ++import common from '@ohos.app.ability.common'; +import QtJsObjectLoader from './JsObjectLoader'; ++import resourceManager from '@ohos.resourceManager'; ++import bundleManager from '@ohos.bundle.bundleManager'; + +interface ApplicationDirs { + tempDir: string, @@ -2689,7 +2805,7 @@ index 0000000000..a43a6e5a97 + private windowStage: window.WindowStage; + private elementName: bundleManager.ElementName = null; + private jsModules: JsQtModule[] = []; -+ private applicationDirs: ApplicationDirs; ++ private ApplicationDirs: ApplicationDirs; + private qtMajorVersion: number = 0; + private qtNativeModules: HashMap = new HashMap(); + private jsObjectLoader: QtJsObjectLoader = new QtJsObjectLoader; @@ -2710,7 +2826,7 @@ index 0000000000..a43a6e5a97 + distributedFilesDir: appContext.distributedFilesDir, + qmlDir: appContext.cacheDir + "/Qt/qml" + }; -+ this.applicationDirs = dirs; ++ this.ApplicationDirs = dirs; + } + + getContext(): common.UIAbilityContext { @@ -2718,7 +2834,7 @@ index 0000000000..a43a6e5a97 + } + + getApplicationDirs() : ApplicationDirs { -+ return this.applicationDirs; ++ return this.ApplicationDirs; + } + + setElementName(en: bundleManager.ElementName) { @@ -3088,10 +3204,10 @@ index 0000000000..a840215671 +} diff --git a/src/openharmony/native/QtCore/JsInputMethod.ts b/src/openharmony/native/QtCore/JsInputMethod.ts new file mode 100644 -index 0000000000..205a6d9685 +index 0000000000..97d3cd37a4 --- /dev/null +++ b/src/openharmony/native/QtCore/JsInputMethod.ts -@@ -0,0 +1,248 @@ +@@ -0,0 +1,286 @@ +import JsDataStore from './JsDataStore' +import { BusinessError } from '@ohos.base'; +import inputMethod from '@ohos.inputMethod'; @@ -3099,6 +3215,7 @@ index 0000000000..205a6d9685 + +export class JsInputMethod { + private handler: number = 0; ++ private visable: boolean = false; /* 记录输入法visible状态 */ + private attached: boolean = false; + private inputMethodController: inputMethod.InputMethodController = inputMethod.getController(); + @@ -3116,6 +3233,33 @@ index 0000000000..205a6d9685 + } + + try { ++ this.inputMethodController.on('sendFunctionKey', (functionKey: inputMethod.FunctionKey) => { ++ console.warn(`Succeeded in subscribing sendFunctionKey, functionKey.enterKeyType: ${functionKey.enterKeyType}`); ++ }); ++ } catch (err) { ++ console.error(`Failed to subscribe sendFunctionKey: ${JSON.stringify(err)}`); ++ } ++ ++ try { ++ this.inputMethodController.on('sendKeyboardStatus', (keyboardStatus: inputMethod.KeyboardStatus) => { ++ console.info(`Succeeded in subscribing sendKeyboardStatus, keyboardStatus: ${keyboardStatus}`); ++ switch (keyboardStatus) { ++ case inputMethod.KeyboardStatus.HIDE: ++ this.visable = false; ++ this.detach(); ++ break; ++ case inputMethod.KeyboardStatus.SHOW: ++ this.visable = true; ++ break; ++ default: ++ break; ++ } ++ }); ++ } catch (err) { ++ console.error(`Failed to subscribe sendKeyboardStatus: ${JSON.stringify(err)}`); ++ } ++ ++ try { + this.inputMethodController.on('deleteLeft', (length: number) => { + console.log(`Succeeded in subscribing deleteLeft, length: ${length}`); + JsDataStore.getQtNativeModule("QPA").deleteLeft(this.handler, length); @@ -3203,56 +3347,66 @@ index 0000000000..205a6d9685 + this.inputMethodController.off('deleteLeft'); + this.inputMethodController.off('deleteRight'); + this.inputMethodController.off('selectByRange'); ++ this.inputMethodController.off('sendFunctionKey'); + this.inputMethodController.off('selectByMovement'); ++ this.inputMethodController.off('sendKeyboardStatus'); + this.inputMethodController.off('handleExtendAction'); + this.inputMethodController.off('getLeftTextOfCursor'); + this.inputMethodController.off('getRightTextOfCursor'); + this.inputMethodController.off('getTextIndexAtCursor'); + } + ++ isInputPanelVisible(): boolean { ++ return this.visable; ++ } ++ + isAttached() { + return this.attached; + } + -+ attach(handler: number): boolean { -+ if (true == this.attached) { -+ return; ++ async attach(handler: number, inputType: number, enterType: number): Promise { ++ if (this.attached) { ++ return true; + } + + if (0 == handler) { + console.error("handle number is error"); -+ return; ++ return false; + } + + this.handler = handler; + try { + let textConfig: inputMethod.TextConfig = { + inputAttribute: { -+ textInputType: inputMethod.TextInputType.MULTILINE, -+ enterKeyType: inputMethod.EnterKeyType.UNSPECIFIED ++ textInputType: inputType, ++ enterKeyType: enterType + } + }; -+ this.inputMethodController.attach(true, textConfig).then(() => { ++ await this.inputMethodController.attach(true, textConfig).then(() => { + this.subscribe(); ++ this.attached = true; + console.log('Succeeded in attaching inputMethod.'); + }).catch((err) => { ++ this.attached = false; + console.error(`Failed to attach: ${JSON.stringify(err)}`); -+ return false; + }) + } catch (err) { ++ this.attached = false; + console.error(`Failed to attach: ${JSON.stringify(err)}`); + } -+ this.attached = true; ++ return this.attached; + } + -+ detach() { ++ async detach(): Promise { + this.unsubscribe(); -+ this.inputMethodController.detach().then(() => { ++ await this.inputMethodController.detach().then(() => { ++ this.attached = false; + console.log('Succeeded in detaching inputMethod.'); + }).catch((err) => { ++ this.attached = true; + console.error(`Failed to detach: ${JSON.stringify(err)}`); + }); -+ this.attached = false; ++ return !this.attached; + } + + showTextInput() { @@ -3525,16 +3679,17 @@ index 0000000000..0a2a0f6b00 \ No newline at end of file diff --git a/src/openharmony/native/QtCore/JsQtPlatform.ts b/src/openharmony/native/QtCore/JsQtPlatform.ts new file mode 100644 -index 0000000000..c3396b5886 +index 0000000000..f5ae8781bd --- /dev/null +++ b/src/openharmony/native/QtCore/JsQtPlatform.ts -@@ -0,0 +1,23 @@ +@@ -0,0 +1,25 @@ +import { JsQtModule } from './JsQtModule' +import { JsDialog } from './JsDialog' +import { JsPasteBoard } from './JsPasteBoard' +import { JsInputMethod } from './JsInputMethod' +import { JsWindowManager } from './JsWindowManager' +import { JsFile } from './JsFile' ++import { JsUrl } from './JsUrl' +import qpa from 'libplugins_platforms_qopenharmony.so' + +class JsQtPlatform extends JsQtModule { @@ -3546,12 +3701,45 @@ index 0000000000..c3396b5886 + JsPasteBoard, + JsInputMethod, + JsWindowManager, -+ JsFile ++ JsFile, ++ JsUrl + }; + } +} +export default new JsQtPlatform; +export const QtQPA : Object = qpa +diff --git a/src/openharmony/native/QtCore/JsUrl.ts b/src/openharmony/native/QtCore/JsUrl.ts +new file mode 100644 +index 0000000000..7328ee0659 +--- /dev/null ++++ b/src/openharmony/native/QtCore/JsUrl.ts +@@ -0,0 +1,25 @@ ++import JSLogger from './JsLogger' ++import common from '@ohos.app.ability.common'; ++import Want from '@ohos.app.ability.Want'; ++import { BusinessError } from '@ohos.base'; ++import JsDataStore from './JsDataStore'; ++ ++ ++export class JsUrl { ++ constructor() {} ++ ++ async openUrl(inUri: string): Promise { ++ let wantInfo: Want = { ++ action: 'ohos.want.action.viewData', ++ entities: ['entity.system.browsable'], ++ uri: inUri ++ } ++ let context: common.UIAbilityContext = JsDataStore.getContext(); ++ context.startAbility(wantInfo).then(() => { ++ JSLogger.info("open url success!!!!") ++ }).catch((err: BusinessError) => { ++ JSLogger.error("open url error!!!!") ++ }) ++ return true; ++ } ++} +\ No newline at end of file diff --git a/src/openharmony/native/QtCore/JsWindow.ts b/src/openharmony/native/QtCore/JsWindow.ts new file mode 100644 index 0000000000..369eb9fbe0 @@ -3641,7 +3829,7 @@ index 0000000000..369eb9fbe0 +} diff --git a/src/openharmony/native/QtCore/JsWindowManager.ts b/src/openharmony/native/QtCore/JsWindowManager.ts new file mode 100644 -index 0000000000..c24c6728c8 +index 0000000000..86263ca195 --- /dev/null +++ b/src/openharmony/native/QtCore/JsWindowManager.ts @@ -0,0 +1,46 @@ @@ -3682,7 +3870,7 @@ index 0000000000..c24c6728c8 + } + } + -+ async destroyWindow(name: string): Promise { ++ async destoryWindow(name: string): Promise { + if (!this.windows.hasKey(name)) + return false; + let window = this.windows.get(name); @@ -3711,11 +3899,10 @@ index 0000000000..1c9156fde0 +OTHER_FILES += $$templates.files diff --git a/src/openharmony/pages/Index.ets b/src/openharmony/pages/Index.ets new file mode 100644 -index 0000000000..16904a1c31 +index 0000000000..c877cc24ef --- /dev/null +++ b/src/openharmony/pages/Index.ets -@@ -0,0 +1,17 @@ -+ +@@ -0,0 +1,14 @@ +@Entry +@Component +struct Index { @@ -3726,9 +3913,7 @@ index 0000000000..16904a1c31 + Row() { + XComponent({id: this.idName, type: 'surface', libraryname: 'plugins_platforms_qopenharmony' }).width("100%").height("100%") + .focusable(true) -+ .onLoad(()=>{ -+ -+ }) ++ .focusOnTouch(true) + } + } +} @@ -3743,10 +3928,10 @@ index 0000000000..886625295c +} diff --git a/src/plugins/platforms/openharmony/openharmony.pro b/src/plugins/platforms/openharmony/openharmony.pro new file mode 100644 -index 0000000000..2f236e120f +index 0000000000..36259aab21 --- /dev/null +++ b/src/plugins/platforms/openharmony/openharmony.pro -@@ -0,0 +1,71 @@ +@@ -0,0 +1,73 @@ +TARGET = qopenharmony + +LIBS += -lEGL -lace_napi.z -lace_ndk.z -lrawfile.z @@ -3785,7 +3970,8 @@ index 0000000000..2f236e120f + $$PWD/qopenharmonyplatformdialoghelpers.h \ + $$PWD/qopenharmonydrag.h \ + $$PWD/qopenharmonyfileenginehandler.h \ -+ $$PWD/qopenharmonyjswindow.h ++ $$PWD/qopenharmonyjswindow.h \ ++ $$PWD/qopenharmonyplatformservices.h + +SOURCES += $$PWD/qopenharmonyplatformplugin.cpp \ + $$PWD/qopenharmonyplatformwindow.cpp \ @@ -3808,7 +3994,8 @@ index 0000000000..2f236e120f + $$PWD/qopenharmonyplatformclipboard.cpp \ + $$PWD/qopenharmonydrag.cpp \ + $$PWD/qopenharmonyfileenginehandler.cpp \ -+ $$PWD/qopenharmonyjswindow.cpp ++ $$PWD/qopenharmonyjswindow.cpp \ ++ $$PWD/qopenharmonyplatformservices.cpp + + +PLUGIN_TYPE = platforms @@ -4584,7 +4771,7 @@ index 0000000000..51fe72e96e +#endif // QOPENHARMONYEVENTDISPATCHER_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyfileenginehandler.cpp b/src/plugins/platforms/openharmony/qopenharmonyfileenginehandler.cpp new file mode 100644 -index 0000000000..b3e4fd2f07 +index 0000000000..a2a7dec9d4 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyfileenginehandler.cpp @@ -0,0 +1,466 @@ @@ -4826,7 +5013,7 @@ index 0000000000..b3e4fd2f07 + { + close(); + if (!m_jsFile.isNull()) { -+ qJsObjectLoader->remove(m_fileHandler); ++ qJsObjectLoader->remove(m_jsFile->uniqueName()); + } + } + @@ -5670,10 +5857,10 @@ index 0000000000..1a88d88b24 +#endif // QOPENHARMONYDEFINES_H diff --git a/src/plugins/platforms/openharmony/qopenharmonymain.cpp b/src/plugins/platforms/openharmony/qopenharmonymain.cpp new file mode 100644 -index 0000000000..efabe40ee5 +index 0000000000..ca8eefffcc --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonymain.cpp -@@ -0,0 +1,453 @@ +@@ -0,0 +1,451 @@ +#include +#include +#include @@ -5695,9 +5882,9 @@ index 0000000000..efabe40ee5 +#include +#include + -+#include "qopenharmonyfileenginehandler.h" -+#include "qopenharmonymain.h" +#include "qopenharmonylog.h" ++#include "qopenharmonymain.h" ++#include "qopenharmonyfileenginehandler.h" +#include "qopenharmonyjswindowmanager.h" +#include "qopenharmonyplatformintegration.h" +#include "qopenharmonyplatformdialoghelpers.h" @@ -5705,6 +5892,7 @@ index 0000000000..efabe40ee5 +#include "qopenharmonyplatforminputcontext.h" +#include "qopenharmonyeventdispatcher.h" +#include "qopenharmonyplatformwindow.h" ++#include "qopenharmonyplatformfontdatabase.h" + +extern "C" typedef int (*Main)(int, char **); //use the standard main method to start the application +static Main m_main = nullptr; @@ -5723,23 +5911,16 @@ index 0000000000..efabe40ee5 +static QOpenHarmonyPlatformIntegration *m_platformIntegration = nullptr; +static QOpenHarmonyFileEngineHandler *m_openHarmonyFileEngineHandler = nullptr; +static QString m_deviceType = "default"; ++static QList m_applicationParams; + +static void *startMainMethod(void *arg) +{ -+ if (nullptr == arg) { -+ return nullptr; -+ } ++ QVarLengthArray params(m_applicationParams.size()); + -+ QByteArray p((char*)arg); -+ QByteArrayList byts = p.split(' '); -+ QVarLengthArray argvs(byts.length()); -+ int i = 0; -+ for(QByteArray b : byts){ -+ argvs[i] = b.data(); -+ i++; -+ } -+ /* FIXME 启动参数个数问题引起崩溃 */ -+ int ret = m_main(1, const_cast(argvs.data())); ++ for (int i = 0; i < m_applicationParams.size(); i++) ++ params[i] = static_cast(m_applicationParams[i].constData()); ++ ++ int ret = m_main(m_applicationParams.length(), const_cast(params.data())); + + if (m_mainLibraryHnd) { + int res = dlclose(m_mainLibraryHnd); @@ -5789,9 +5970,13 @@ index 0000000000..efabe40ee5 + if (!cacheQmlStr.isEmpty()) + qmls << cacheQmlStr.toLatin1(); + ++ QString cacheDir = qJs::getObjectPropertyValue(args[0], "cacheDir"); ++ if (::setenv("QT_HARMONY_CACHE_DIR", cacheDir.toLatin1().constData(), 1) != 0) { ++ LOGE("Can't set environment for QT_HARMONY_CACHE_DIR"); ++ } + + if (::setenv("QT_QPA_PLATFORM_PLUGIN_PATH", libDir.constData(), 1) != 0) { -+ LOGE("Can't set environment for QT_PLUGIN_PATH"); ++ LOGE("Can't set environment for QT_QPA_PLATFORM_PLUGIN_PATH"); + } + if (::setenv("QML_DISABLE_DISK_CACHE", "1", 1) != 0) { + LOGE("Can't set environment for QML_DISABLE_DISK_CACHE"); @@ -5800,17 +5985,32 @@ index 0000000000..efabe40ee5 + LOGE("Can't set environment for QT_PLUGIN_PATH"); + } + ++ QByteArrayList boundPath = { libDir }; ++ QByteArray boundImport = boundPath.join(":"); ++ qWarning() << "harmony boundImport import path:" << boundImport; ++ if (::setenv("QT_HARMONY_BUNDLED_LIBS_PATH", boundImport.constData(), 1) != 0) { ++ LOGE("Can't set environment for QT_HARMONY_BUNDLED_LIBS_PATH"); ++ } ++ + QByteArray qmlImportPath = qmls.join(":"); ++ qWarning() << "qml import path:" << qmlImportPath; + if (::setenv("QML2_IMPORT_PATH", qmlImportPath.constData(), 1) != 0) { + LOGE("Can't set environment for QML2_IMPORT_PATH"); + } -+ -+// if (::setenv("QT_DEBUG_PLUGINS", "1", 1) != 0) { -+// LOGE("Can't set environment for QT_DEBUG_PLUGINS"); -+// } -+ ++#if 0 ++ if (::setenv("QT_DEBUG_PLUGINS", "1", 1) != 0) { ++ LOGE("Can't set environment for QT_DEBUG_PLUGINS"); ++ } ++#endif + m_mainLibraryHnd = nullptr; -+ QByteArray fileName = qJs::getString(args[1]).toLatin1(); ++ ++ QByteArray params = qJs::getString(args[1]).toLatin1(); ++ m_applicationParams = params.split('\t'); ++ if (m_applicationParams.empty()) { ++ LOGE("no qt application specified"); ++ return qJs::createBool(false); ++ } ++ QByteArray fileName = m_applicationParams.first(); + LOGI("load qt application %{public}s", fileName.constData()); + + //look for main() @@ -5836,37 +6036,8 @@ index 0000000000..efabe40ee5 + + + m_openHarmonyFileEngineHandler = new QOpenHarmonyFileEngineHandler; -+ -+ QByteArray byt = libDir + "/" + fileName; -+ if (3 == argc) { -+ QStringList argvs = qJs::getStringList(args[2]); -+ argvs.prepend(byt); -+ QString tmp = argvs.join(QString(" ")); -+ byt.clear(); -+ byt = tmp.toLocal8Bit(); -+ } -+ -+ int result = pthread_create(&m_qtAppThread, nullptr, startMainMethod, byt.data()); -+ if (result) { -+ LOGW("create qt thread error:%{public}s", result); -+ return qJs::createBool(false); -+ } -+ -+#if 0 -+ void * thread_result; -+ result = pthread_join(m_qtAppThread, &thread_result); -+ if (result) { -+ LOGW("join qt thread error:%{public}s", result); -+ return qJs::createBool(false); -+ } -+ -+ result = pthread_join(m_qtAppThread, &thread_result); -+ if (result == ESRCH) { -+ LOGW("qt thread inexistence"); -+ return qJs::createBool(false); -+ } -+ LOGW("<------------------ join %{public}s", thread_result); -+#endif ++ m_applicationParams[0] = libDir + "/" + fileName; ++ pthread_create(&m_qtAppThread, nullptr, startMainMethod, nullptr); + return qJs::createBool(true); +} + @@ -6020,7 +6191,7 @@ index 0000000000..efabe40ee5 + LOGI("quit qt application"); + OH_ResourceManager_ReleaseNativeResourceManager(m_resourceManager); + qJs::quit(); -+ qApp->quit(); ++ //qApp->quit(); + return nullptr; +} + @@ -6029,6 +6200,18 @@ index 0000000000..efabe40ee5 + return qJs::createInt32(QT_VERSION_MAJOR); +} + ++static napi_value waitForQtAppExit(napi_env env, napi_callback_info info) ++{ ++ // sem_wait(&m_terminateSemaphore); ++ if (sem_trywait(&m_terminateSemaphore) == 0) { ++ return qJs::createInt32(0); ++ } ++ else ++ { ++ return qJs::createInt32(1); ++ } ++} ++ +/* + * function for module exports + */ @@ -6046,9 +6229,11 @@ index 0000000000..efabe40ee5 + DECLARE_NAPI_FUNCTION("quitQtApplication", quitQtApplication), + DECLARE_NAPI_FUNCTION("qtMajorVersion", qtMajorVersion), + DECLARE_NAPI_FUNCTION("setDeviceType", setDeviceType), ++ DECLARE_NAPI_FUNCTION("waitForQtAppExit", waitForQtAppExit), + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); + QOpenHarmonyPlatformInputContext::init(env, exports); ++ QOpenHarmonyPlatformFontDatabase::init(env, exports); + QOpenHarmonyPlatformMessageDialogHelper::init(env, exports); + QOpenHarmonyPlatformFileDialogHelper::init(env, exports); + @@ -6125,7 +6310,7 @@ index 0000000000..efabe40ee5 + if (isPhone()) + return QMargins(); + // Todo read from js -+ return QMargins(3, 72, 3, 3); ++ return QMargins(7, 92, 6, 6); +} diff --git a/src/plugins/platforms/openharmony/qopenharmonymain.h b/src/plugins/platforms/openharmony/qopenharmonymain.h new file mode 100644 @@ -6246,7 +6431,7 @@ index 0000000000..db75831b39 +#endif // QOPENHARMONYPLATFORMBACKINGSTORE_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformclipboard.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatformclipboard.cpp new file mode 100644 -index 0000000000..c0694de72e +index 0000000000..d5504bed0d --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformclipboard.cpp @@ -0,0 +1,86 @@ @@ -6314,7 +6499,7 @@ index 0000000000..c0694de72e +{ + if (supportsMode(mode)) { + QString text = (data != 0 && data->hasText() ? data->text() : QString()); -+ m_jsClipboard->call("setClipboardText", text);; ++ m_jsClipboard->callWithoutReturn("setClipboardText", text); + } + if (data != 0) + data->deleteLater(); @@ -6380,7 +6565,7 @@ index 0000000000..40b3576be4 +#endif // QOPENHARMONYPLATFORMCLIPBOARD_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformdialoghelpers.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatformdialoghelpers.cpp new file mode 100644 -index 0000000000..7368f11911 +index 0000000000..dbd3897b53 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformdialoghelpers.cpp @@ -0,0 +1,298 @@ @@ -6467,7 +6652,7 @@ index 0000000000..7368f11911 + if (!str.isEmpty()) + text += str; + -+ m_jsDialog->call("messageBox", QVariant(qlonglong(static_cast(this))), htmlText(opt->windowTitle()), text, m_buttons); ++ m_jsDialog->callWithoutReturn("messageBox", QVariant(qlonglong(static_cast(this))), htmlText(opt->windowTitle()), text, m_buttons); + m_shown = true; + return true; +} @@ -6657,9 +6842,9 @@ index 0000000000..7368f11911 + return false; + bool open = (opt->acceptMode() == QFileDialogOptions::AcceptOpen); + if (open) -+ m_jsDialog->call("openFileDialog", QVariant(qlonglong(static_cast(this))), m_filter); ++ m_jsDialog->callWithoutReturn("openFileDialog", QVariant(qlonglong(static_cast(this))), m_filter); + else -+ m_jsDialog->call("saveFileDialog", QVariant(qlonglong(static_cast(this))), m_saveFile); ++ m_jsDialog->callWithoutReturn("saveFileDialog", QVariant(qlonglong(static_cast(this))), m_saveFile); + m_shown = true; + return true; +} @@ -6777,30 +6962,68 @@ index 0000000000..39762fdc90 +#endif // QOPENHARMONYPLATFORMDIALOGHELPERS_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformfontdatabase.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatformfontdatabase.cpp new file mode 100644 -index 0000000000..82131d485a +index 0000000000..dc5b6c998f --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformfontdatabase.cpp -@@ -0,0 +1,36 @@ +@@ -0,0 +1,83 @@ +#include ++#include ++#include ++#include + +#include "qopenharmonyplatformfontdatabase.h" + ++static QStringList gs_fonts; ++ ++/* 通过鸿蒙ts接口查询系统提供的字体路径 ++ * 然后传入C++端使用 ++ */ ++static napi_value setFontInfos(napi_env env, napi_callback_info info) ++{ ++ size_t argc = 1; ++ napi_value args[1]; ++ NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); ++ if (argc != 1) { ++ napi_throw_type_error(env, NULL, "Wrong number of arguments"); ++ return nullptr; ++ } ++ ++ if (gs_fonts.isEmpty()) ++ gs_fonts = qJs::getStringList(args[0]); ++ ++ return Q_NULLPTR; ++} ++ +QT_BEGIN_NAMESPACE + +QString QOpenHarmonyPlatformFontDatabase::fontDir() const +{ ++ /* FIMXE 鸿蒙权限收紧,读取该目录会提示读取失败 */ + return QLatin1String("/system/fonts"); +} + +void QOpenHarmonyPlatformFontDatabase::populateFontDatabase() +{ ++ /* FIXME ++ * 使用鸿蒙ts端查询到的字体路径 ++ * 否则,扫描fontDir路径中的字体文件 ++ * (该操作因为鸿蒙系统权限收紧会提示读取目录失败的警告) ++ */ ++ if (!gs_fonts.isEmpty()) { ++ for (const QString &f : qAsConst(gs_fonts)) { ++ const QByteArray file = QFile::encodeName(f); ++ QFreeTypeFontDatabase::addTTFile(QByteArray(), file); ++ } ++ return; ++ } ++ + QString fontpath = fontDir(); + QDir dir(fontpath); + + if (Q_UNLIKELY(!dir.exists())) { + qWarning("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?", + qPrintable(fontpath)); -+ //Todo Qtʹ_statȡ״̬Ϣʱ-1Ȩޱܾ.ʹentryInfoListܹгĿ¼µ ++ //Todo Qt使用_stat函数获取状态信息时返回-1,权限被拒绝.但是使用entryInfoList能够列出目录下的字体 + } + + QStringList nameFilters; @@ -6815,26 +7038,37 @@ index 0000000000..82131d485a + } +} + ++napi_value QOpenHarmonyPlatformFontDatabase::init(napi_env env, napi_value exports) ++{ ++ napi_property_descriptor desc[] ={ ++ DECLARE_NAPI_FUNCTION("setFontInfos", setFontInfos), ++ }; ++ NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); ++ return nullptr; ++} ++ + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformfontdatabase.h b/src/plugins/platforms/openharmony/qopenharmonyplatformfontdatabase.h new file mode 100644 -index 0000000000..3e38d4f853 +index 0000000000..bfad0a18a1 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformfontdatabase.h -@@ -0,0 +1,17 @@ +@@ -0,0 +1,19 @@ +#ifndef QOPENHARMONYPLATFORMFONTDATABASE_H +#define QOPENHARMONYPLATFORMFONTDATABASE_H + ++#include +#include + +QT_BEGIN_NAMESPACE + +class QOpenHarmonyPlatformFontDatabase: public QFreeTypeFontDatabase +{ -+public: ++public: + QString fontDir() const override; + void populateFontDatabase() override; ++ static napi_value init(napi_env env, napi_value exports); +}; + +QT_END_NAMESPACE @@ -6935,10 +7169,10 @@ index 0000000000..e792d1a019 +#endif // QOPENHARMONYPLATFORMFOREIGNWINDOW_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatforminputcontext.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatforminputcontext.cpp new file mode 100644 -index 0000000000..b73ae5a569 +index 0000000000..d00836a94c --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatforminputcontext.cpp -@@ -0,0 +1,481 @@ +@@ -0,0 +1,1175 @@ +#include "qopenharmonymain.h" +#include "qopenharmonyjsobjectloader.h" +#include "qopenharmonyplatformscreen.h" @@ -6950,6 +7184,7 @@ index 0000000000..b73ae5a569 +#include + +#include ++#include +#include +#include +#include @@ -6959,12 +7194,92 @@ index 0000000000..b73ae5a569 + +#include +#include -+ -+#include +#include ++#include + +QT_BEGIN_NAMESPACE + ++namespace { ++ ++class BatchEditLock ++{ ++public: ++ ++ explicit BatchEditLock(QOpenHarmonyPlatformInputContext *context) ++ : m_context(context) ++ { ++ m_context->beginBatchEdit(); ++ } ++ ++ ~BatchEditLock() ++ { ++ m_context->endBatchEdit(); ++ } ++ ++ BatchEditLock(const BatchEditLock &) = delete; ++ BatchEditLock &operator=(const BatchEditLock &) = delete; ++ ++private: ++ ++ QOpenHarmonyPlatformInputContext *m_context; ++}; ++ ++} // namespace anonymous ++ ++/*! ++ * \brief Qt-鸿蒙平台下的输入类型枚举值映射 ++ * \param hints Qt下的枚举值 ++ * \return 返回Qt-鸿蒙的输入类型映射值 ++ */ ++static int harmonyTextInputType(Qt::InputMethodHints hints) ++{ ++ /* FIXME Qt支持位运算,鸿蒙文本类型不支持位运算的枚举值 */ ++ if(hints.testFlag(Qt::ImhMultiLine)) /* 多行文本类型 */ ++ return 1; ++ if (hints.testFlag(Qt::ImhPreferNumbers) || ++ hints.testFlag(Qt::ImhDigitsOnly)) /* 数字类型 */ ++ return 2; ++ if (hints.testFlag(Qt::ImhDate) || ++ hints.testFlag(Qt::ImhTime)) /* 日期类型 */ ++ return 4; ++ if (hints.testFlag(Qt::ImhHiddenText)) /* 密码类型 */ ++ return 7; ++ if ((hints.testFlag(Qt::ImhDigitsOnly) | ++ hints.testFlag(Qt::ImhFormattedNumbersOnly)) && ++ hints.testFlag(Qt::ImhHiddenText)) /* 数字密码类型 */ ++ return 8; ++ if (hints.testFlag(Qt::ImhDialableCharactersOnly)) /* 电话号码类型 */ ++ return 3; ++ if (hints.testFlag(Qt::ImhEmailCharactersOnly)) /* 邮箱地址类型 */ ++ return 5; ++ if (hints.testFlag(Qt::ImhUrlCharactersOnly)) /* 链接类型 */ ++ return 6; ++ ++ return 0; /* 默认文本类型 */ ++} ++/*! ++ * \brief Qt-鸿蒙平台下的EnterKey功能值映射 ++ * \param type Qt下的EnterKey功能枚举值 ++ * \return 返回Qt-鸿蒙的EnterKey功能映射值 ++ */ ++static int harmonyEnterKeyType(Qt::EnterKeyType type) ++{ ++ switch (type) { ++ case Qt::EnterKeyDone: ++ case Qt::EnterKeyDefault: ++ return 6; ++ case Qt::EnterKeyReturn: ++ case Qt::EnterKeyPrevious: ++ return 7; ++ case Qt::EnterKeyGo: return 2; ++ case Qt::EnterKeySend: return 4; ++ case Qt::EnterKeySearch: return 3; ++ case Qt::EnterKeyNext:return 5; ++ default: break; ++ } ++ return 0; ++} ++ +static QOpenHarmonyPlatformInputContext *m_openHarmonyInputContext = 0; + +static napi_value insertText(napi_env env, napi_callback_info info) @@ -7070,16 +7385,447 @@ index 0000000000..b73ae5a569 + return nullptr; +} + -+void QOpenHarmonyPlatformInputContext::sendKeyEvent(QKeyEvent *event) -+{ -+ QGuiApplication::sendEvent(m_focusObject, event); ++void QOpenHarmonyPlatformInputContext::dispatchKeyEvent(OH_NativeXComponent_KeyCode code, ++ OH_NativeXComponent_KeyAction action, ++ OH_NativeXComponent_EventSourceType stype, ++ int64_t deviceId, ++ int64_t timeStamp) ++{ ++ Q_UNUSED(deviceId);Q_UNUSED(timeStamp); ++ static QHash sKeyType{ ++ { OH_NATIVEXCOMPONENT_KEY_ACTION_DOWN, QEvent::KeyPress }, ++ { OH_NATIVEXCOMPONENT_KEY_ACTION_UP, QEvent::KeyRelease }, ++ }; ++ ++ ++ static QHash 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_Enter }, ++ { KEY_DEL, Qt::Key_Back }, ++ { KEY_GRAVE, Qt::Key_Apostrophe }, ++ { 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_Return }, ++ //{ 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 } ++ }; ++ ++ static QHash 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}, ++ }; ++ ++ /* 有修饰符按下时记录按下的修饰符 ++ * 松开时移除修饰符记录 ++ */ ++ ++ Qt::KeyboardModifiers modifiers(Qt::NoModifier); ++ QEvent::Type t = sKeyType.value(action, QEvent::None); ++ Qt::KeyboardModifier m = sKeyModifers.value(code, Qt::NoModifier); ++ if (Qt::NoModifier != m && QEvent::KeyPress == t){ ++ modifiers |= m; ++ m_mpd.insert(m); ++ } ++ else if (Qt::NoModifier != m && QEvent::KeyRelease == t) { ++ m_mpd.remove(m); ++ } ++ ++ Qt::Key k = sKeyMap.value(code, Qt::Key_unknown); ++ ++ int nativeModifier = KEY_UNKNOWN; ++ for (Qt::KeyboardModifier mf : m_mpd) ++ nativeModifier |= int(mf); ++ ++ QKeyEvent *kEvent = new QKeyEvent(t, k, modifiers, code, code, nativeModifier); ++ /* NOTE 因为鸿蒙回调在其他线程,这里事件处理只能通过线程队列发送 */ ++ QGuiApplication::postEvent(m_focusObject, kEvent); ++ ++ /* 快捷点组合判断 */ ++ if (m_mpd.contains(Qt::ControlModifier) && KEY_A == code) ++ QMetaObject::invokeMethod(this, "sendShortcut", Qt::QueuedConnection, ++ Q_ARG(int, QKeySequence::SelectAll)); ++ else if (m_mpd.contains(Qt::ControlModifier) && KEY_C == code) ++ QMetaObject::invokeMethod(this, "sendShortcut", Qt::QueuedConnection, ++ Q_ARG(int, QKeySequence::Copy)); ++ else if (m_mpd.contains(Qt::ControlModifier) && KEY_V == code) ++ QMetaObject::invokeMethod(this, "sendShortcut", Qt::QueuedConnection, ++ Q_ARG(int, QKeySequence::Paste)); +} + -+QOpenHarmonyPlatformInputContext::QOpenHarmonyPlatformInputContext() -+ : QPlatformInputContext() -+ , m_composingTextStart(-1) -+ , m_composingCursor(-1) -+ , m_focusObject(Q_NULLPTR) ++void QOpenHarmonyPlatformInputContext::sendShortcut(int key) ++{ ++ QKeySequence::StandardKey skey = QKeySequence::StandardKey(key); ++ QKeySequence sequence(skey); ++ for (int i = 0; i < sequence.count(); ++i) { ++ const int keys = sequence[i]; ++ Qt::Key key = Qt::Key(keys & ~Qt::KeyboardModifierMask); ++ Qt::KeyboardModifiers mod = Qt::KeyboardModifiers(keys & Qt::KeyboardModifierMask); ++ ++ QKeyEvent pressEvent(QEvent::KeyPress, key, mod); ++ QKeyEvent releaseEvent(QEvent::KeyRelease, key, mod); ++ ++ QGuiApplication::sendEvent(m_focusObject, &pressEvent); ++ QGuiApplication::sendEvent(m_focusObject, &releaseEvent); ++ } ++} ++ ++void QOpenHarmonyPlatformInputContext::updateCursorPosition() ++{ ++ // qWarning() << "<--------------::::" << Q_FUNC_INFO; ++} ++ ++QOpenHarmonyPlatformInputContext::QOpenHarmonyPlatformInputContext() ++ : QPlatformInputContext() ++ , m_composingTextStart(-1) ++ , m_composingCursor(-1) ++ , m_batchEditNestingLevel(0) ++ , m_focusObject(Q_NULLPTR) +{ + m_jsInputCtl = qJsObjectLoader->create("JsInputMethod"); + m_openHarmonyInputContext = this; @@ -7089,17 +7835,188 @@ index 0000000000..b73ae5a569 +{ + m_openHarmonyInputContext = Q_NULLPTR; +} ++/*! ++ * \brief 检查输入上下文是否具有指定的功能 ++ * \param capability 枚举值,用于指定功能类型 ++ * \return 返回布尔值,如果具有指定功能,则返回 true,否则返回 false ++ */ ++bool QOpenHarmonyPlatformInputContext::hasCapability(Capability capability) const ++{ ++ switch (capability) { ++ case HiddenTextCapability: ++ return false; ++ default:break; ++ } ++ return true; ++} ++/*! ++ * \brief 重置输入法状态,将输入法状态恢复到默认状态 ++ */ ++void QOpenHarmonyPlatformInputContext::reset() ++{ ++ // qWarning() << "<-----------::" << Q_FUNC_INFO; ++ focusObjectStopComposing(); ++ m_batchEditNestingLevel = 0; + -+QOpenHarmonyPlatformInputContext *QOpenHarmonyPlatformInputContext::openHarmonyInputContext() ++ if (m_jsInputCtl->call("isAttached")) ++ m_jsInputCtl->call("detach"); ++ ++ clearInput(); ++ emitInputPanelVisibleChanged(); ++} ++/*! ++ * \brief 提交当前输入法状态,将当前输入法状态应用到文本编辑器中 ++ */ ++void QOpenHarmonyPlatformInputContext::commit() +{ -+ return m_openHarmonyInputContext; ++ // qWarning() << "<-----------::" << Q_FUNC_INFO; ++ if(m_jsInputCtl->call("isAttached")) ++ m_jsInputCtl->call("detach"); ++} ++/*! ++ * \brief 编辑器更新通知。由QInputMethod::update()调用 ++ * 函数的作用是更新输入上下文的状态,以便与应用程序的输入方法通信 ++ * 并响应输入法相关的查询,一般流程如下: ++ * 1.当输入法状态发生变化,或者焦点对象发生变化时 ++ * QGuiApplication 会调用当前活动的 QPlatformInputContext 对象的 update 函数 ++ * ++ * 2.在 update 函数内部,QPlatformInputContext 可以查询焦点对象的相关信息, ++ * 例如文本内容、光标位置等,然后将这些信息传递给输入法对象 ++ * ++ * 3.输入法对象根据接收到的信息更新其状态,并相应地调整显示内容或行为 ++ * 4.用户与输入法进行交互,输入文本或者调整输入法的设置 ++ * 5.当用户输入完成或者输入法状态发生变化时,输入法对象可能会触发输入法事件, ++ * 通知 QPlatformInputContext 对象更新状态 ++ */ ++void QOpenHarmonyPlatformInputContext::update(Qt::InputMethodQueries queries) ++{ ++ // qWarning() << "<-----------::" << Q_FUNC_INFO; ++ QSharedPointer query = focusObjectInputMethodQuery(queries); ++ if (query.isNull()) ++ return; ++ ++#warning TODO extract the needed data from query +} + ++/*! ++ * \brief 调用输入法的动作,以执行指定的操作,如向前移动光标、向后删除等 ++ * \param act 动作类型 ++ * \param cursorPosition 光标位置 ++ */ +void QOpenHarmonyPlatformInputContext::invokeAction(QInputMethod::Action act, int cursorPosition) +{ -+ qInfo() << "QOpenHarmonyPlatformInputContext<===================invokeAction:" -+ << act -+ << cursorPosition; ++ // qWarning() << "<-----------::" << Q_FUNC_INFO; ++#warning TODO Handle ++ Q_UNUSED(act); ++ Q_UNUSED(cursorPosition); ++} ++/*! ++ * \brief 过滤输入事件,以便输入上下文可以处理输入事件并相应地调整输入法状态 ++ * \param event 输入事件 ++ * \return 返回布尔值 ++ */ ++bool QOpenHarmonyPlatformInputContext::filterEvent(const QEvent *event) ++{ ++ return QPlatformInputContext::filterEvent(event); ++} ++/*! ++ * \brief 获取键盘区域的矩形范围,以便应用程序可以根据键盘的显示状态调整布局 ++ * \return 返回键盘区域矩形大小 ++ */ ++QRectF QOpenHarmonyPlatformInputContext::keyboardRect() const ++{ ++ //TODO acquire softkeyborad rect ++ return QRectF(); ++} ++ ++/*! ++ * \brief 返回布尔值,指示输入面板是否处于动画状态 ++ * \return 返回布尔值 ++ */ ++bool QOpenHarmonyPlatformInputContext::isAnimating() const ++{ ++ return false; ++} ++/*! ++ * \brief 显示输入面板 ++ */ ++void QOpenHarmonyPlatformInputContext::showInputPanel() ++{ ++ // qWarning() << "<-----------::" << Q_FUNC_INFO; ++ QSharedPointer query = focusObjectInputMethodQuery(); ++ if (query.isNull()) ++ return; ++ ++ disconnect(m_updateCursorPosConnection); ++ if (qGuiApp->focusObject()->metaObject()->indexOfSignal("cursorPositionChanged(int,int)") >= 0) // QLineEdit breaks the pattern ++ m_updateCursorPosConnection = connect(qGuiApp->focusObject(), SIGNAL(cursorPositionChanged(int,int)), this, SLOT(updateCursorPosition())); ++ else ++ m_updateCursorPosConnection = connect(qGuiApp->focusObject(), SIGNAL(cursorPositionChanged()), this, SLOT(updateCursorPosition())); ++ ++ Qt::InputMethodHints hints = query->value(Qt::ImHints).value(); ++ Qt::EnterKeyType enterType = query->value(Qt::ImEnterKeyType).value(); ++ ++ bool isAttached = m_jsInputCtl->call("isAttached"); ++ if (!isAttached) ++ m_jsInputCtl->call("attach", QVariant(qlonglong(static_cast(this))), ++ harmonyTextInputType(hints), ++ harmonyEnterKeyType(enterType)); ++ ++ emitInputPanelVisibleChanged(); ++} ++/*! ++ * \brief 隐藏输入面板 ++ */ ++void QOpenHarmonyPlatformInputContext::hideInputPanel() ++{ ++ // qWarning() << "<-----------::" << Q_FUNC_INFO; ++#if 0 ++ if(m_jsInputCtl->call("isAttached")) ++ m_jsInputCtl->call("detach"); ++#endif ++ clearInput(); ++ emitInputPanelVisibleChanged(); ++} ++/*! ++ * \brief 返回布尔值,指示输入面板的可见性状态 ++ * \return 返回布尔值 ++ */ ++bool QOpenHarmonyPlatformInputContext::isInputPanelVisible() const ++{ ++ bool visible = m_jsInputCtl->call("isInputPanelVisible"); ++ return visible; ++} ++/*! ++ * \brief 设置获得焦点的对象 ++ * \param object 对象指针 ++ */ ++void QOpenHarmonyPlatformInputContext::setFocusObject(QObject *object) ++{ ++ if (object != m_focusObject) { ++ m_focusObject = object; ++ reset(); ++ } ++ QPlatformInputContext::setFocusObject(object); ++} ++ ++bool QOpenHarmonyPlatformInputContext::beginBatchEdit() ++{ ++ ++m_batchEditNestingLevel; ++ return true; ++} ++ ++bool QOpenHarmonyPlatformInputContext::endBatchEdit() ++{ ++ if (--m_batchEditNestingLevel == 0) { //ending batch edit mode ++ //focusObjectStartComposing(); ++ updateCursorPosition(); ++ } ++ return true; ++} ++ ++QOpenHarmonyPlatformInputContext *QOpenHarmonyPlatformInputContext::openHarmonyInputContext() ++{ ++ return m_openHarmonyInputContext; +} + +void QOpenHarmonyPlatformInputContext::setPlatformIntegration(QOpenHarmonyPlatformIntegration *integration) @@ -7189,63 +8106,6 @@ index 0000000000..b73ae5a569 + QWindowSystemInterface::handleTouchEvent(window, touchDevice, m_touchPoints); +} + -+void QOpenHarmonyPlatformInputContext::reset() -+{ -+ qInfo() << "QOpenHarmonyPlatformInputContext<===================reset:"; -+ clearInput(); -+} -+ -+void QOpenHarmonyPlatformInputContext::commit() -+{ -+ qInfo() << "QOpenHarmonyPlatformInputContext<===================commit:" << m_composingText; -+} -+ -+void QOpenHarmonyPlatformInputContext::showInputPanel() -+{ -+ qInfo() << "QOpenHarmonyPlatformInputContext<===================showInputPanel:"; -+ bool isAttached = m_jsInputCtl->call("isAttached"); -+ if (!isAttached) -+ m_jsInputCtl->call("attach", QVariant(qlonglong(static_cast(this)))); -+} -+ -+void QOpenHarmonyPlatformInputContext::hideInputPanel() -+{ -+ m_jsInputCtl->call("detach"); -+ clearInput(); -+ qInfo() << "QOpenHarmonyPlatformInputContext<===================hideInputPanel:"; -+} -+ -+bool QOpenHarmonyPlatformInputContext::isAnimating() const -+{ -+ return false; -+} -+ -+QRectF QOpenHarmonyPlatformInputContext::keyboardRect() const -+{ -+ //TODO acquire softkeyborad rect -+ return QRectF(); -+} -+ -+void QOpenHarmonyPlatformInputContext::update(Qt::InputMethodQueries) -+{ -+ // qInfo() << "QOpenHarmonyPlatformInputContext<============================update"; -+} -+ -+void QOpenHarmonyPlatformInputContext::setFocusObject(QObject *object) -+{ -+ if (object != m_focusObject) { -+ m_focusObject = object; -+ reset(); -+ } -+ QPlatformInputContext::setFocusObject(object); -+} -+ -+bool QOpenHarmonyPlatformInputContext::isInputPanelVisible() const -+{ -+ //TODO acquire softkeyborad visable -+ return false; -+} -+ +void QOpenHarmonyPlatformInputContext::setComposingText(const QString &text) +{ + m_composingText = text; @@ -7289,6 +8149,7 @@ index 0000000000..b73ae5a569 + m_composingText.clear(); + m_composingTextStart = -1; + m_composingCursor = -1; ++ // m_extractedText.clear(); +} + +void QOpenHarmonyPlatformInputContext::commitText(QString text) @@ -7347,8 +8208,6 @@ index 0000000000..b73ae5a569 + return; + + const int absolutecursorPos = getAbsoluteCursorPosition(query); -+ qWarning() << absolutecursorPos << "<============"; -+ + const QString &selectText = query->value(Qt::ImCurrentSelection).toString(); + const int selectLength = selectText.length(); + int beginPos = absolutecursorPos; @@ -7416,16 +8275,85 @@ index 0000000000..b73ae5a569 + return m_composingCursor != -1; +} + ++void QOpenHarmonyPlatformInputContext::focusObjectStartComposing() ++{ ++ if (focusObjectIsComposing() || m_composingText.isEmpty()) ++ return; ++ ++ // Composing strings containing newline characters are rare and may cause problems ++ if (m_composingText.contains(QLatin1Char('\n'))) ++ return; ++ ++ QSharedPointer query = focusObjectInputMethodQuery(); ++ if (!query) ++ return; ++ ++ if (query->value(Qt::ImCursorPosition).toInt() != query->value(Qt::ImAnchorPosition).toInt()) ++ return; ++ ++ const int absoluteCursorPos = getAbsoluteCursorPosition(query); ++ if (absoluteCursorPos < m_composingTextStart ++ || absoluteCursorPos > m_composingTextStart + m_composingText.length()) ++ return; ++ ++ m_composingCursor = absoluteCursorPos; ++ ++ QTextCharFormat underlined; ++ underlined.setFontUnderline(true); ++ ++ QInputMethodEvent event(m_composingText, { ++ { QInputMethodEvent::Cursor, absoluteCursorPos - m_composingTextStart, 1 }, ++ { QInputMethodEvent::TextFormat, 0, m_composingText.length(), underlined } ++ }); ++ ++ event.setCommitString({}, m_composingTextStart - absoluteCursorPos, m_composingText.length()); ++ ++ QGuiApplication::sendEvent(m_focusObject, &event); ++} ++ ++bool QOpenHarmonyPlatformInputContext::focusObjectStopComposing() ++{ ++ if (!focusObjectIsComposing()) ++ return true; // not composing ++ ++ QSharedPointer query = focusObjectInputMethodQuery(); ++ if (query.isNull()) ++ return false; ++ ++ const int blockPos = getBlockPosition(query); ++ const int localCursorPos = m_composingCursor - blockPos; ++ ++ m_composingCursor = -1; ++ ++ { ++ // commit the composing test ++ QList attributes; ++ QInputMethodEvent event(QString(), attributes); ++ event.setCommitString(m_composingText); ++ sendInputMethodEvent(&event); ++ } ++ { ++ // Moving Qt's cursor to where the preedit cursor used to be ++ QList attributes; ++ attributes.append( ++ QInputMethodEvent::Attribute(QInputMethodEvent::Selection, localCursorPos, 0)); ++ QInputMethodEvent event(QString(), attributes); ++ sendInputMethodEvent(&event); ++ } ++ ++ return true; ++} ++ + +QT_END_NAMESPACE + + diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatforminputcontext.h b/src/plugins/platforms/openharmony/qopenharmonyplatforminputcontext.h new file mode 100644 -index 0000000000..7e2a334fd5 +index 0000000000..62fb0fadfc --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatforminputcontext.h -@@ -0,0 +1,74 @@ +@@ -0,0 +1,95 @@ +#ifndef QOPENHARMONYPLATFORMINPUTCONTEXT_H +#define QOPENHARMONYPLATFORMINPUTCONTEXT_H + @@ -7433,6 +8361,8 @@ index 0000000000..7e2a334fd5 +#include +#include +#include ++#include ++#include + +class QOpenHarmonyJsObject; +class QOpenHarmonyPlatformIntegration; @@ -7446,31 +8376,47 @@ index 0000000000..7e2a334fd5 + QOpenHarmonyPlatformInputContext(); + ~QOpenHarmonyPlatformInputContext() override; + -+ void clear(); -+ void touchBegin(); -+ void touchEnd(int id); ++ /* 判断输入上下文是否有效 */ ++ 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; ++ QRectF keyboardRect() const override; ++ ++ bool isAnimating() const override; ++ + void showInputPanel() override; + void hideInputPanel() override; -+ bool isAnimating() const override; -+ QRectF keyboardRect() const override; -+ void update(Qt::InputMethodQueries) override; -+ void setFocusObject(QObject *object) override; -+ bool isValid() const override { return true; } + bool isInputPanelVisible() const override; ++ ++ void setFocusObject(QObject *object) override; ++ ++ bool beginBatchEdit(); ++ bool endBatchEdit(); ++ ++ void clear(); ++ void touchBegin(); ++ void touchEnd(int id); + void setComposingText(const QString &text); + void touchAdd(int id, int action, float force, float x, float y); + static QOpenHarmonyPlatformInputContext * openHarmonyInputContext(); -+ void invokeAction(QInputMethod::Action act, int cursorPosition) override; + void setPlatformIntegration(QOpenHarmonyPlatformIntegration *integration); + static napi_value init(napi_env env, napi_value exports); -+ void sendKeyEvent(QKeyEvent *event); ++ void dispatchKeyEvent(OH_NativeXComponent_KeyCode code, ++ OH_NativeXComponent_KeyAction action, ++ OH_NativeXComponent_EventSourceType stype, int64_t deviceId, int64_t timeStamp); ++ Q_INVOKABLE void sendShortcut(int key); + -+public Q_SLOTS: ++public Q_SLOTS: ++ void updateCursorPosition(); + void mousePress(float x, float y); + void mouseRelease(float x, float y); -+ void touchDown(float x, float y); ++ void touchDown(float x, float y); + +private Q_SLOTS: + void clearInput(); @@ -7481,7 +8427,9 @@ index 0000000000..7e2a334fd5 + +private: + bool focusObjectIsComposing() const; -+ void sendInputMethodEvent(QInputMethodEvent *event); ++ void focusObjectStartComposing(); ++ bool focusObjectStopComposing(); ++ void sendInputMethodEvent(QInputMethodEvent *event); + QSharedPointer focusObjectInputMethodQuery(Qt::InputMethodQueries queries = Qt::ImQueryAll); + +private: @@ -7489,11 +8437,12 @@ index 0000000000..7e2a334fd5 + int m_composingTextStart; + int m_composingCursor; + QObject *m_focusObject; ++ int m_batchEditNestingLevel; ++ QSet m_mpd; /* 记录按下的修饰键 */ + bool m_ignoreMouseEvents = false; + QMetaObject::Connection m_updateCursorPosConnection; + QOpenHarmonyPlatformIntegration *m_integration = nullptr; -+ QList m_touchPoints; -+ ++ QList m_touchPoints; + QSharedPointer m_jsInputCtl; +}; + @@ -7502,10 +8451,10 @@ index 0000000000..7e2a334fd5 +#endif // QOPENHARMONYPLATFORMINPUTCONTEXT_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformintegration.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatformintegration.cpp new file mode 100644 -index 0000000000..c8cb187363 +index 0000000000..dea72d7492 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformintegration.cpp -@@ -0,0 +1,296 @@ +@@ -0,0 +1,304 @@ +#include "qopenharmonyplatformintegration.h" + +#include @@ -7533,6 +8482,8 @@ index 0000000000..c8cb187363 +#include "qopenharmonyplatformtheme.h" +#include "qopenharmonyplatformclipboard.h" +#include "qopenharmonyeglcore.h" ++#include "qopenharmonyplatformservices.h" ++ +#if QT_CONFIG(vulkan) +#include "qopenharmonyplatformvulkaninstance.h" +#endif @@ -7584,6 +8535,7 @@ index 0000000000..c8cb187363 +#endif + + m_platformNativeInterface.reset(new QOpenHarmonyPlatformNativeInterface()); ++ m_platformServices.reset(new QOpenHarmonyPlatformServices()); + QCoreApplication::postEvent(m_platformNativeInterface.data(), new QEvent(QEvent::User)); +} + @@ -7676,6 +8628,11 @@ index 0000000000..c8cb187363 + return m_platformNativeInterface.data(); +} + ++QPlatformServices *QOpenHarmonyPlatformIntegration::services() const ++{ ++ return m_platformServices.data(); ++} ++ +QVariant QOpenHarmonyPlatformIntegration::styleHint(StyleHint hint) const +{ + switch (hint) { @@ -7696,11 +8653,11 @@ index 0000000000..c8cb187363 + } + return QPlatformIntegration::defaultWindowState(flags); +} -+ ++/* NOTE 改主题名称和加载的样式插件相关联 */ +static const QLatin1String openharmonyThemeName("openharmony"); +QStringList QOpenHarmonyPlatformIntegration::themeNames() const +{ -+ return QStringList(QString(openharmonyThemeName)); ++ return QStringList{ "harmonyos", QString(openharmonyThemeName) }; +} + +QPlatformTheme *QOpenHarmonyPlatformIntegration::createPlatformTheme(const QString &name) const @@ -7804,10 +8761,10 @@ index 0000000000..c8cb187363 + diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformintegration.h b/src/plugins/platforms/openharmony/qopenharmonyplatformintegration.h new file mode 100644 -index 0000000000..a1706af0ea +index 0000000000..966cdbdeb5 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformintegration.h -@@ -0,0 +1,133 @@ +@@ -0,0 +1,135 @@ +#ifndef QOPENHARMONYPLATFORMINTERATION_H +#define QOPENHARMONYPLATFORMINTERATION_H + @@ -7816,6 +8773,7 @@ index 0000000000..a1706af0ea +#include +#include +#include ++#include + +#include + @@ -7874,7 +8832,7 @@ index 0000000000..a1706af0ea + + QPlatformInputContext *inputContext() const override; + QPlatformNativeInterface *nativeInterface() const override; -+// QPlatformServices *services() const override; ++ QPlatformServices *services() const override; + +//#ifndef QT_NO_ACCESSIBILITY +// virtual QPlatformAccessibility *accessibility() const override; @@ -7936,6 +8894,7 @@ index 0000000000..a1706af0ea +#endif + + QScopedPointer m_platformNativeInterface; ++ QScopedPointer m_platformServices; +}; + +QT_END_NAMESPACE @@ -8830,20 +9789,160 @@ index 0000000000..20bec988ab + +QT_END_NAMESPACE +#endif +diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformservices.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatformservices.cpp +new file mode 100644 +index 0000000000..a6527dcd59 +--- /dev/null ++++ b/src/plugins/platforms/openharmony/qopenharmonyplatformservices.cpp +@@ -0,0 +1,45 @@ ++#include "qopenharmonyplatformservices.h" ++ ++#include ++#include ++#include ++ ++QT_BEGIN_NAMESPACE ++ ++ ++ ++bool QOpenHarmonyPlatformServices::openUrl(const QUrl &url) ++{ ++ QUrl theUrl(url); ++ ++ if (m_jsService.isNull()) ++ { ++ m_jsService = qJsObjectLoader->create("JsUrl"); ++ } ++ ++ QString urlStr = theUrl.toString(); ++ bool result = m_jsService->call("openUrl", urlStr); ++ return result; ++} ++ ++ ++//TODO ++bool QOpenHarmonyPlatformServices::openDocument(const QUrl &url) ++{ ++ return false; ++} ++ ++//TODO ++QByteArray QOpenHarmonyPlatformServices::desktopEnvironment() const ++{ ++ return nullptr; ++} ++ ++ ++ ++ ++ ++ ++ ++ ++QT_END_NAMESPACE +diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformservices.h b/src/plugins/platforms/openharmony/qopenharmonyplatformservices.h +new file mode 100644 +index 0000000000..b41060aaa0 +--- /dev/null ++++ b/src/plugins/platforms/openharmony/qopenharmonyplatformservices.h +@@ -0,0 +1,25 @@ ++#ifndef QOPENHARMONYPLATFORMSERVICES_H ++#define QOPENHARMONYPLATFORMSERVICES_H ++ ++#include ++#include ++#include ++ ++QT_BEGIN_NAMESPACE ++ ++ ++class QOpenHarmonyPlatformServices : public QPlatformServices ++{ ++public: ++ bool openUrl(const QUrl &url) override; ++ bool openDocument(const QUrl &url) override; ++ QByteArray desktopEnvironment() const override; ++ ++private: ++ QSharedPointer m_jsService; ++}; ++ ++ ++QT_END_NAMESPACE ++ ++#endif diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformtheme.cpp b/src/plugins/platforms/openharmony/qopenharmonyplatformtheme.cpp new file mode 100644 -index 0000000000..e10fd6b9a1 +index 0000000000..84b3ec2649 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformtheme.cpp -@@ -0,0 +1,42 @@ +@@ -0,0 +1,119 @@ ++#include ++#include ++#include +#include "qopenharmonyplatformtheme.h" +#include "qopenharmonyplatformdialoghelpers.h" + +#include ++#include + -+QOpenHarmonyPlatformTheme::QOpenHarmonyPlatformTheme() ++static QPalette qt_harmonyPalette() +{ ++#if 1 ++ QColor base("#FFFFFF"); ++ QColor text("#182431"); ++ QColor window("#FFFFFF"); ++ QColor button("#0C182431"); ++ QColor windowText("#182431"); ++ QColor brightText("#FFFFFF"); ++ QColor dark = button.darker(); ++ QColor light = button.lighter(); ++ QColor mid = button.lighter(130); ++ ++ QPalette harmonyPalette(windowText, button, light, dark, mid, text, brightText, base, window); ++ ++ return harmonyPalette; ++#endif ++ ++#if 0 ++ QColor backGround(239, 239, 239); ++ QColor light = backGround.lighter(150); ++ QColor mid(backGround.darker(130)); ++ QColor midLight = mid.lighter(110); ++ QColor base = Qt::white; ++ QColor disabledBase(backGround); ++ QColor dark = backGround.darker(150); ++ QColor darkDisabled = QColor(209, 209, 209).darker(110); ++ QColor text = Qt::black; ++ QColor hightlightedText = Qt::white; ++ QColor disabledText = QColor(190, 190, 190); ++ QColor button = backGround; ++ QColor shadow = dark.darker(135); ++ QColor disabledShadow = shadow.lighter(150); ++ ++ QPalette fusionPalette(Qt::black,backGround,light,dark,mid,text,base); ++ fusionPalette.setBrush(QPalette::Midlight, midLight); ++ fusionPalette.setBrush(QPalette::Button, button); ++ fusionPalette.setBrush(QPalette::Shadow, shadow); ++ fusionPalette.setBrush(QPalette::HighlightedText, hightlightedText); ++ ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::Text, disabledText); ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::WindowText, disabledText); ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledText); ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::Base, disabledBase); ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::Dark, darkDisabled); ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::Shadow, disabledShadow); ++ ++ fusionPalette.setBrush(QPalette::Active, QPalette::Highlight, QColor(48, 140, 198)); ++ fusionPalette.setBrush(QPalette::Inactive, QPalette::Highlight, QColor(48, 140, 198)); ++ fusionPalette.setBrush(QPalette::Disabled, QPalette::Highlight, QColor(145, 145, 145)); ++ return fusionPalette; ++#endif ++} + ++QOpenHarmonyPlatformTheme::QOpenHarmonyPlatformTheme() ++{ ++ QGuiApplication::setPalette(qt_harmonyPalette()); +} + +QString QOpenHarmonyPlatformTheme::standardButtonText(int button) const @@ -8867,6 +9966,15 @@ index 0000000000..e10fd6b9a1 + return true; +} + ++const QPalette *QOpenHarmonyPlatformTheme::palette(Palette type) const ++{ ++ if (type == QPlatformTheme::SystemPalette) { ++ QPalette *p = new QPalette(qt_harmonyPalette()); ++ return p; ++ } ++ return nullptr; ++} ++ +QPlatformDialogHelper *QOpenHarmonyPlatformTheme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const +{ + switch (type) { @@ -8878,23 +9986,36 @@ index 0000000000..e10fd6b9a1 + return 0; + } +} ++ ++QVariant QOpenHarmonyPlatformTheme::themeHint(ThemeHint hint) const ++{ ++ switch(hint) { ++ case ThemeHint::StyleNames: ++ return QVariant(QStringList{ "harmonyos", "openharmony" }); /* FIXME 暂时认为OpenHarmony HarmonyOS是两种不同的主题样式 */ ++ default: ++ return QPlatformTheme::themeHint(hint); ++ } ++} diff --git a/src/plugins/platforms/openharmony/qopenharmonyplatformtheme.h b/src/plugins/platforms/openharmony/qopenharmonyplatformtheme.h new file mode 100644 -index 0000000000..06de62426a +index 0000000000..34ee717e33 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyplatformtheme.h -@@ -0,0 +1,15 @@ +@@ -0,0 +1,18 @@ +#ifndef QOPENHARMONYPLATFORMTHEME_H +#define QOPENHARMONYPLATFORMTHEME_H + ++#include +#include + +class QOpenHarmonyPlatformTheme: public QPlatformTheme +{ +public: + QOpenHarmonyPlatformTheme(); ++ 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; +}; + @@ -9185,10 +10306,10 @@ index 0000000000..02a723f2c0 +#endif // QOPENHARMONYPLATFORMWINDOW_H diff --git a/src/plugins/platforms/openharmony/qopenharmonyxcomponent.cpp b/src/plugins/platforms/openharmony/qopenharmonyxcomponent.cpp new file mode 100644 -index 0000000000..3323641bb0 +index 0000000000..0d43504bb1 --- /dev/null +++ b/src/plugins/platforms/openharmony/qopenharmonyxcomponent.cpp -@@ -0,0 +1,635 @@ +@@ -0,0 +1,257 @@ +#include +#include + @@ -9200,8 +10321,6 @@ index 0000000000..3323641bb0 +#include "qopenharmonyplatformwindow.h" +#include "qopenharmonylog.h" +#include "qopenharmonymain.h" -+#include -+#include + +QOpenHarmonyXComponent::QOpenHarmonyXComponent(OH_NativeXComponent *component) + : m_nativeComponent(component) @@ -9260,9 +10379,8 @@ index 0000000000..3323641bb0 +} + +void QOpenHarmonyXComponent::dispatchKeyEvent(OH_NativeXComponent *component, void *window) -+{ ++{ + Q_UNUSED(window); -+ + QOpenHarmonyPlatformInputContext *context = QOpenHarmonyPlatformInputContext::openHarmonyInputContext(); + if (Q_NULLPTR == context) + return; @@ -9291,385 +10409,9 @@ index 0000000000..3323641bb0 + if (Q_NULLPTR == context) + return; +#endif -+ static QHash sKeyType{ -+ { OH_NATIVEXCOMPONENT_KEY_ACTION_DOWN, QEvent::KeyPress }, -+ { OH_NATIVEXCOMPONENT_KEY_ACTION_UP, QEvent::KeyRelease }, -+ }; -+ -+ -+ static QHash 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_Back }, -+ { KEY_GRAVE, Qt::Key_Apostrophe }, -+ { 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_Return }, -+ //{ 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 } -+ }; ++ context->dispatchKeyEvent(code, action, sourceType, deviceId, timeStamp); + -+ static QHash 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}, -+ }; -+ static int nativeModifier = Qt::NoModifier; -+ if (sKeyModifers.keys().contains(code)) -+ nativeModifier |= code; -+ -+ Qt::Key k = sKeyMap.value(code, Qt::Key_unknown); -+ QEvent::Type t = sKeyType.value(action, QEvent::None); -+ Qt::KeyboardModifiers modifiers(Qt::NoModifier); -+ modifiers |= sKeyModifers.value(code, Qt::NoModifier); -+ -+ QKeyEvent kEvent(t, k, modifiers, code, code, nativeModifier); -+ context->sendKeyEvent(&kEvent); ++ //nativeModifier = Qt::NoModifier; + //QWindowSystemInterface::handleKeyEvent(Q_NULLPTR, ulong(timeStamp), t, k, modifiers); + + } else { @@ -9759,6 +10501,7 @@ index 0000000000..3323641bb0 + } + + ret = OH_NativeXComponent_RegisterKeyEventCallback(component, &QOpenHarmonyXComponent::dispatchKeyEvent); ++ qWarning() << "OH_NativeXComponent_RegisterKeyEventCallback ret:" << ret; + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) + LOGI("set surface keybord callback failed"); + @@ -9914,6 +10657,16 @@ index 23f838a7fe..f13ef8b9cd 100644 qtConfig(xcb) { SUBDIRS += xcb } +diff --git a/src/plugins/styles/styles.pro b/src/plugins/styles/styles.pro +index 542ad1329a..fb8d978d83 100644 +--- a/src/plugins/styles/styles.pro ++++ b/src/plugins/styles/styles.pro +@@ -6,3 +6,5 @@ qtConfig(style-android): SUBDIRS += android + qtConfig(style-mac): SUBDIRS += mac + + qtConfig(style-windowsvista): SUBDIRS += windowsvista ++ ++# qtConfig(style-harmonyos): SUBDIRS += harmonyos diff --git a/src/src.pro b/src/src.pro index 8990109743..ffa3ca0dcc 100644 --- a/src/src.pro @@ -9977,11 +10730,60 @@ index 8917f0dc0e..7042f00f2d 100644 } void QTestLog::stopLogging() +diff --git a/src/widgets/configure.json b/src/widgets/configure.json +index 0a68f082a2..b3e6991a50 100644 +--- a/src/widgets/configure.json ++++ b/src/widgets/configure.json +@@ -13,7 +13,8 @@ + "style-windowsvista": "boolean", + "style-fusion": "boolean", + "style-mac": "boolean", +- "style-android": "boolean" ++ "style-android": "boolean", ++ "style-harmonyos": "boolean" + } + }, + +@@ -64,6 +65,11 @@ + "autoDetect": "config.android", + "output": [ "privateFeature", "styles" ] + }, ++ "style-harmonyos": { ++ "label": "HarmonyOS", ++ "autoDetect": "config.openharmony", ++ "output": [ "privateFeature", "styles" ] ++ }, + "style-stylesheet": { + "label": "QStyleSheetStyle", + "purpose": "Provides a widget style which is configurable via CSS.", diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp -index 711effefe2..03ced89c4c 100644 +index 711effefe2..f6e2ff564a 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp -@@ -2218,10 +2218,18 @@ QString QFileDialog::getOpenFileName(QWidget *parent, +@@ -1311,11 +1311,22 @@ QStringList QFileDialog::selectedFiles() const + QStringList files; + const QList userSelectedFiles = d->userSelectedFiles(); + files.reserve(userSelectedFiles.size()); ++ ++ ++ QString fileName; + for (const QUrl &file : userSelectedFiles) { ++#ifdef Q_OS_OPENHARMONY ++ fileName = file.toLocalFile(); ++ if (!fileName.isEmpty()) { ++ fileName.prepend("datashare://"); ++ } ++ files.append(fileName); ++#else + if (file.isLocalFile() || file.isEmpty()) + files.append(file.toLocalFile()); + else + files.append(file.toString()); ++#endif + } + if (files.isEmpty() && d->usingWidgets()) { + const FileMode fm = fileMode(); +@@ -2218,10 +2229,18 @@ QString QFileDialog::getOpenFileName(QWidget *parent, const QStringList schemes = QStringList(QStringLiteral("file")); const QUrl selectedUrl = getOpenFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter, selectedFilter, options, schemes); @@ -10000,7 +10802,7 @@ index 711effefe2..03ced89c4c 100644 } /*! -@@ -2581,10 +2589,18 @@ QString QFileDialog::getSaveFileName(QWidget *parent, +@@ -2581,10 +2600,18 @@ QString QFileDialog::getSaveFileName(QWidget *parent, const QStringList schemes = QStringList(QStringLiteral("file")); const QUrl selectedUrl = getSaveFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter, selectedFilter, options, schemes); diff --git a/patch/v5.15.12/qtconnectivity.patch b/patch/v5.15.12/qtconnectivity.patch index 74cd4d0895..a3bbc3c491 100644 --- a/patch/v5.15.12/qtconnectivity.patch +++ b/patch/v5.15.12/qtconnectivity.patch @@ -163,7 +163,7 @@ index 00000000..5a2d24cf +#endif // BLUETOOTHDATARECEIVER_P_H diff --git a/src/bluetooth/openharmony/lowenergynotificationhub.cpp b/src/bluetooth/openharmony/lowenergynotificationhub.cpp new file mode 100644 -index 00000000..ded1be45 +index 00000000..e757d324 --- /dev/null +++ b/src/bluetooth/openharmony/lowenergynotificationhub.cpp @@ -0,0 +1,367 @@ @@ -216,7 +216,7 @@ index 00000000..ded1be45 + } + + hubMap()->insert(jsToCtoken, this); -+ m_jsBluetoothLe->call("setQtObject", jsToCtoken); ++ m_jsBluetoothLe->callWithoutReturn("setQtObject", jsToCtoken); + lock.unlock(); +} + @@ -1075,7 +1075,7 @@ index 00000000..5ddd0e36 +#endif // OPENHARMONYSERVICEDISCOVERYRECEIVER_H diff --git a/src/bluetooth/openharmony/serveracceptancethread.cpp b/src/bluetooth/openharmony/serveracceptancethread.cpp new file mode 100644 -index 00000000..193f8371 +index 00000000..d9e11afe --- /dev/null +++ b/src/bluetooth/openharmony/serveracceptancethread.cpp @@ -0,0 +1,201 @@ @@ -1228,14 +1228,14 @@ index 00000000..193f8371 + tempUuid.remove(0,1); //remove first '{' + + bool isSecure = !(secFlags == QBluetooth::NoSecurity); -+ jsThread->call("listen", tempUuid, m_serviceName, isSecure); ++ jsThread->callWithoutReturn("listen", tempUuid, m_serviceName, isSecure); +} + +void ServerAcceptanceThread::stop() +{ + if (jsThread->isValid()) { + qCDebug(QT_BT_OPENHARMONY) << "Closing server socket"; -+ jsThread->call("close"); ++ jsThread->callWithoutReturn("close"); + } +} + @@ -1277,7 +1277,7 @@ index 00000000..193f8371 +{ + while (!pendingSockets.isEmpty()) { + int socket = pendingSockets.takeFirst(); -+ jsThread->call("closeClient", socket); ++ jsThread->callWithoutReturn("closeClient", socket); + } +} diff --git a/src/bluetooth/openharmony/serveracceptancethread_p.h b/src/bluetooth/openharmony/serveracceptancethread_p.h @@ -1352,7 +1352,7 @@ index 1e8ce0b8..5e9cf19b 100644 QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_ohos.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_ohos.cpp new file mode 100644 -index 00000000..060c8aef +index 00000000..6cf0e437 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_ohos.cpp @@ -0,0 +1,276 @@ @@ -1596,7 +1596,7 @@ index 00000000..060c8aef + m_active = BtleScanActive; + + -+ m_jsBluetoothManager->call("startBLEScan"); ++ m_jsBluetoothManager->callWithoutReturn("startBLEScan"); + + // wait interval and sum up what was found + if (!leScanTimeout) { @@ -1617,7 +1617,7 @@ index 00000000..060c8aef + +void QBluetoothDeviceDiscoveryAgentPrivate::stopLowEnergyScan() +{ -+ m_jsBluetoothManager->call("stopBLEScan"); ++ m_jsBluetoothManager->callWithoutReturn("stopBLEScan"); + + m_active = NoScanActive; + @@ -1702,7 +1702,7 @@ index 9f6d1e1b..59bdd36b 100644 diff --git a/src/bluetooth/qbluetoothlocaldevice_ohos.cpp b/src/bluetooth/qbluetoothlocaldevice_ohos.cpp new file mode 100644 -index 00000000..dfe5f7b2 +index 00000000..d3d3869d --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice_ohos.cpp @@ -0,0 +1,332 @@ @@ -1911,12 +1911,12 @@ index 00000000..dfe5f7b2 + setHostMode(QBluetoothLocalDevice::HostPoweredOff); + d_ptr->pendingHostModeTransition = true; + } else { -+ d_ptr->m_jsBluetoothManager->call("setScanMode", 1); ++ d_ptr->m_jsBluetoothManager->callWithoutReturn("setScanMode", 1); + } + } else if (mode == QBluetoothLocalDevice::HostDiscoverable) { -+ d_ptr->m_jsBluetoothManager->call("setScanMode", 2); ++ d_ptr->m_jsBluetoothManager->callWithoutReturn("setScanMode", 2); + } else if (mode == QBluetoothLocalDevice::HostDiscoverableLimitedInquiry) { -+ d_ptr->m_jsBluetoothManager->call("setScanMode", 3); ++ d_ptr->m_jsBluetoothManager->callWithoutReturn("setScanMode", 3); + } +} + @@ -2411,10 +2411,10 @@ index e76c2311..74e78b2b 100644 /*! diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_ohos.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_ohos.cpp new file mode 100644 -index 00000000..ffc400d6 +index 00000000..2b6af890 --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_ohos.cpp -@@ -0,0 +1,445 @@ +@@ -0,0 +1,436 @@ +#include +#include +#include @@ -2495,7 +2495,6 @@ index 00000000..ffc400d6 +void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) +{ + Q_Q(QBluetoothServiceDiscoveryAgent); -+ qWarning() << "<<<<<<<<------000" << address.toString(); + + if (!m_jsBtMgr->isValid()) { + if (m_deviceAdapterAddress.isNull()) { @@ -2531,7 +2530,6 @@ index 00000000..ffc400d6 +// _q_serviceDiscoveryFinished(); +// return; +// } -+ qWarning() << "<<<<<<<<------222" << address.toString(); + if (mode == QBluetoothServiceDiscoveryAgent::MinimalDiscovery) { + qCDebug(QT_BT_OPENHARMONY) << "Minimal discovery on (" << discoveredDevices.at(0).name() + << ")" << address.toString(); @@ -2545,18 +2543,14 @@ index 00000000..ffc400d6 + _q_serviceDiscoveryFinished(); + return; + } else { -+ qWarning() << "<<<<<<<<------333" << address.toString(); -+// qCDebug(QT_BT_OPENHARMONY) << "Full discovery on (" << discoveredDevices.at(0).name() -+// << ")" << address.toString(); ++ qCDebug(QT_BT_OPENHARMONY) << "Full discovery on (" << discoveredDevices.at(0).name() ++ << ")" << address.toString(); + -+ qWarning() << "<<<<<<<<------333--222" << address.toString(); + //Full discovery uses BluetoothDevice.fetchUuidsWithSdp() + if (!receiver) { + receiver = new OPenHarmonyServiceDiscoveryReceiver(); -+ QString name = QString("QBluetoothServiceDiscoveryAgent_%1").arg(++gi_count); -+ qWarning() << "<<<<<<<<------444" << address.toString(); -+ m_jsBtMgr->call("createServiceAdapter", name, QVariant(qlonglong(static_cast(receiver)))); -+ qWarning() << "<<<<<<<<------555" << address.toString(); ++ QString name = QString("QBluetoothServiceDiscoveryAgent_%1").arg(++gi_count); ++ m_jsBtMgr->call("createServiceAdapter", name, QVariant(qlonglong(static_cast(receiver)))); + m_jsAdapter = qJsObjectLoader->create(name); + QObject::connect(receiver, &OPenHarmonyServiceDiscoveryReceiver::uuidFetchFinished, + q, [this](const QBluetoothAddress &address, const QList& uuids) { @@ -2575,18 +2569,15 @@ index 00000000..ffc400d6 + if (!m_jsAdapter->isValid()) + return; + -+ qWarning() << "<<<<<<<<------666" << address.toString(); ++ + bool ok = m_jsAdapter->call("createAdapter", address.toString()); -+ qWarning() << "<<<<<<<<------777" << address.toString() << ok; + if (!ok) { + receiver->deleteLater(); + receiver = nullptr; + qCWarning(QT_BT_OPENHARMONY) << "Cannot start dynamic fetch."; + _q_serviceDiscoveryFinished(); -+ } -+ qWarning() << "<===============LLLLL---"; -+ m_jsAdapter->call("fetchService"); -+ qWarning() << "<===============LLLLL---222"; ++ } ++ m_jsAdapter->callWithoutReturn("fetchService"); + } +} + @@ -3700,7 +3691,7 @@ index b065555c..df1f09e3 100644 #if QT_CONFIG(winrt_btle_no_pairing) diff --git a/src/bluetooth/qlowenergycontroller_ohos.cpp b/src/bluetooth/qlowenergycontroller_ohos.cpp new file mode 100644 -index 00000000..73fb98eb +index 00000000..efca9358 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_ohos.cpp @@ -0,0 +1,871 @@ @@ -3741,7 +3732,7 @@ index 00000000..73fb98eb +{ + if (role == QLowEnergyController::PeripheralRole) { + if (hub) -+ hub->jsObject()->call("disconnectServer"); ++ hub->jsObject()->callWithoutReturn("disconnectServer"); + } +} + @@ -3820,9 +3811,9 @@ index 00000000..73fb98eb + + if (hub) { + if (role == QLowEnergyController::PeripheralRole) -+ hub->jsObject()->call("disconnectServer"); ++ hub->jsObject()->callWithoutReturn("disconnectServer"); + else -+ hub->jsObject()->call("disconnect"); ++ hub->jsObject()->callWithoutReturn("disconnect"); + } + + if (oldState == QLowEnergyController::ConnectingState) @@ -4500,7 +4491,7 @@ index 00000000..73fb98eb +void QLowEnergyControllerPrivateOpenHarmony::stopAdvertising() +{ + setState(QLowEnergyController::UnconnectedState); -+ hub->jsObject()->call("stopAdvertising"); ++ hub->jsObject()->callWithoutReturn("stopAdvertising"); +} + +void QLowEnergyControllerPrivateOpenHarmony::requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) @@ -6017,7 +6008,7 @@ index 00000000..bd9cc9a5 +#endif // QNEARFIELDMANAGER_OPENHARMONY_P_H diff --git a/src/nfc/qnearfieldtarget_openharmony.cpp b/src/nfc/qnearfieldtarget_openharmony.cpp new file mode 100644 -index 00000000..fa9533e2 +index 00000000..6de0a783 --- /dev/null +++ b/src/nfc/qnearfieldtarget_openharmony.cpp @@ -0,0 +1,366 @@ @@ -6239,7 +6230,7 @@ index 00000000..fa9533e2 + + const QNdefMessage &message = messages.first(); + QByteArray ba = message.toByteArray(); -+ m_jsTag->call(writeMethod, ba); ++ m_jsTag->callWithoutReturn(writeMethod, ba); + + if (!m_keepConnection) + disconnect(); // IOException at this point does not matter anymore. diff --git a/patch/v5.15.12/qtdeclarative.patch b/patch/v5.15.12/qtdeclarative.patch index 52e901b78e..f4e721f898 100644 --- a/patch/v5.15.12/qtdeclarative.patch +++ b/patch/v5.15.12/qtdeclarative.patch @@ -1,5 +1,5 @@ diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp -index 465a342129..982e9e93fd 100644 +index 465a342129..36a383cd4d 100644 --- a/src/qml/qml/qqmlfile.cpp +++ b/src/qml/qml/qqmlfile.cpp @@ -66,7 +66,9 @@ static char file_string[] = "file"; @@ -52,6 +52,15 @@ index 465a342129..982e9e93fd 100644 } else { return false; } +@@ -538,7 +553,7 @@ Local file urls have either a qrc:/ or file:// scheme. + \note On Android, urls with assets:/ scheme are also considered local files. + */ + bool QQmlFile::isLocalFile(const QString &url) +-{ ++{ + if (url.length() < 5 /* qrc:/ */) + return false; + @@ -568,7 +583,14 @@ bool QQmlFile::isLocalFile(const QString &url) url[7] == QLatin1Char(':') && url[8] == QLatin1Char('/'); } @@ -67,6 +76,15 @@ index 465a342129..982e9e93fd 100644 return false; } +@@ -577,7 +599,7 @@ If \a url is a local file returns a path suitable for passing to QFile. Otherwi + empty string. + */ + QString QQmlFile::urlToLocalFileOrQrc(const QUrl& url) +-{ ++{ + if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) { + if (url.authority().isEmpty()) + return QLatin1Char(':') + url.path(); @@ -593,7 +615,13 @@ QString QQmlFile::urlToLocalFileOrQrc(const QUrl& url) return url.toString(); } @@ -82,7 +100,15 @@ index 465a342129..982e9e93fd 100644 return url.toLocalFile(); } -@@ -633,7 +661,11 @@ QString QQmlFile::urlToLocalFileOrQrc(const QString& url) +@@ -614,6 +642,7 @@ empty string. + */ + QString QQmlFile::urlToLocalFileOrQrc(const QString& url) + { ++ //qWarning() << Q_FUNC_INFO << url; + if (url.startsWith(QLatin1String("qrc://"), Qt::CaseInsensitive)) { + if (url.length() > 6) + return QLatin1Char(':') + url.midRef(6); +@@ -633,7 +662,11 @@ QString QQmlFile::urlToLocalFileOrQrc(const QString& url) return url; } #endif @@ -95,6 +121,823 @@ index 465a342129..982e9e93fd 100644 return toLocalFile(url); } +diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp +index e7263d1850..1409bcb993 100644 +--- a/src/qml/qml/qqmlimport.cpp ++++ b/src/qml/qml/qqmlimport.cpp +@@ -95,7 +95,7 @@ QString resolveLocalUrl(const QString &url, const QString &relative) + + QString base = baseRef + relative; + +- // Remove any relative directory elements in the path ++ // Remove any relative directory elements in the path + int length = base.length(); + int index = 0; + while ((index = base.indexOf(QLatin1String("/."), index)) != -1) { +@@ -174,33 +174,33 @@ typedef QPair StaticPluginPair; + \internal + \class QQmlImportInstance + +- A QQmlImportType represents a single import of a document, held within a +- namespace. ++A QQmlImportType represents a single import of a document, held within a ++namespace. + +- \note The uri here may not necessarily be unique (e.g. for file imports). ++\note The uri here may not necessarily be unique (e.g. for file imports). + +- \note Version numbers may be -1 for file imports: this means that no +- version was specified as part of the import. Type resolution will be +- responsible for attempting to find the "best" possible version. ++\note Version numbers may be -1 for file imports: this means that no ++version was specified as part of the import. Type resolution will be ++responsible for attempting to find the "best" possible version. + */ + + /*! + \internal + \class QQmlImportNamespace + +- A QQmlImportNamespace is a way of seperating imports into a local namespace. ++A QQmlImportNamespace is a way of seperating imports into a local namespace. + +- Within a QML document, there is at least one namespace (the +- "unqualified set") where imports without a qualifier are placed, i.e: ++Within a QML document, there is at least one namespace (the ++"unqualified set") where imports without a qualifier are placed, i.e: + +- import QtQuick 2.6 ++ import QtQuick 2.6 + +- will have a single namespace (the unqualified set) containing a single import +- for QtQuick 2.6. However, there may be others if an import statement gives +- a qualifier, i.e the following will result in an additional new +- QQmlImportNamespace in the qualified set: ++will have a single namespace (the unqualified set) containing a single import ++for QtQuick 2.6. However, there may be others if an import statement gives ++a qualifier, i.e the following will result in an additional new ++QQmlImportNamespace in the qualified set: + +- import MyFoo 1.0 as Foo ++ import MyFoo 1.0 as Foo + */ + + class QQmlImportsPrivate +@@ -235,12 +235,12 @@ public: + QString base; + int ref; + +- // storage of data related to imports without a namespace ++ // storage of data related to imports without a namespace + mutable QQmlImportNamespace unqualifiedset; + + QQmlImportNamespace *findQualifiedNamespace(const QHashedStringRef &) const; + +- // storage of data related to imports with a namespace ++ // storage of data related to imports with a namespace + mutable QFieldList qualifiedSets; + + QQmlTypeLoader *typeLoader; +@@ -264,12 +264,12 @@ public: + QString resolvedUri(const QString &dir_arg, QQmlImportDatabase *database); + + QQmlImportInstance *addImportToNamespace(QQmlImportNamespace *nameSpace, +- const QString &uri, const QString &url, +- int vmaj, int vmin, QV4::CompiledData::Import::ImportType type, +- QList *errors, bool lowPrecedence = false); ++ const QString &uri, const QString &url, ++ int vmaj, int vmin, QV4::CompiledData::Import::ImportType type, ++ QList *errors, bool lowPrecedence = false); + + bool populatePluginPairVector(QVector &result, const QString &uri, const QStringList &versionUris, +- const QString &qmldirPath, QList *errors); ++ const QString &qmldirPath, QList *errors); + }; + + /*! +@@ -278,7 +278,7 @@ public: + \internal + */ + QQmlImports::QQmlImports(const QQmlImports ©) +-: d(copy.d) ++ : d(copy.d) + { + ++d->ref; + } +@@ -330,12 +330,12 @@ QUrl QQmlImports::baseUrl() const + /* + \internal + +- This method is responsible for populating data of all types visible in this +- document's imports into the \a cache for resolution elsewhere (e.g. in JS, +- or when loading additional types). ++This method is responsible for populating data of all types visible in this ++document's imports into the \a cache for resolution elsewhere (e.g. in JS, ++or when loading additional types). + +- \note This is for C++ types only. Composite types are handled separately, +- as they do not have a QQmlTypeModule. ++\note This is for C++ types only. Composite types are handled separately, ++as they do not have a QQmlTypeModule. + */ + void QQmlImports::populateCache(QQmlTypeNameCache *cache) const + { +@@ -353,7 +353,7 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache) const + + const QQmlImportNamespace &set = *ns; + +- // positioning is important; we must create the namespace even if there is no module. ++ // positioning is important; we must create the namespace even if there is no module. + QQmlImportRef &typeimport = cache->m_namedImports[set.prefix]; + typeimport.m_qualifier = set.prefix; + +@@ -433,11 +433,11 @@ void findCompositeSingletons(const QQmlImportNamespace &set, QList QQmlImports::resolvedCompositeSingletons() const + { +@@ -454,16 +454,16 @@ QList QQmlImports::resolvedCompositeSi + std::stable_sort(compositeSingletons.begin(), compositeSingletons.end(), + [](const QQmlImports::CompositeSingletonReference &lhs, + const QQmlImports::CompositeSingletonReference &rhs) { +- if (lhs.prefix != rhs.prefix) +- return lhs.prefix < rhs.prefix; ++ if (lhs.prefix != rhs.prefix) ++ return lhs.prefix < rhs.prefix; + +- if (lhs.typeName != rhs.typeName) +- return lhs.typeName < rhs.typeName; ++ if (lhs.typeName != rhs.typeName) ++ return lhs.typeName < rhs.typeName; + +- return lhs.majorVersion != rhs.majorVersion +- ? lhs.majorVersion < rhs.majorVersion +- : lhs.minorVersion < rhs.minorVersion; +- }); ++ return lhs.majorVersion != rhs.majorVersion ++ ? lhs.majorVersion < rhs.majorVersion ++ : lhs.minorVersion < rhs.minorVersion; ++ }); + + return compositeSingletons; + } +@@ -471,8 +471,8 @@ QList QQmlImports::resolvedCompositeSi + /* + \internal + +- Returns a list of scripts imported by this document. This is used by +- QQmlTypeLoader to properly handle dependencies on imported scripts. ++Returns a list of scripts imported by this document. This is used by ++QQmlTypeLoader to properly handle dependencies on imported scripts. + */ + QList QQmlImports::resolvedScripts() const + { +@@ -524,12 +524,12 @@ static QString joinStringRefs(const QVector &refs, const QChar &sep) + /*! + Forms complete paths to a qmldir file, from a base URL, a module URI and version specification. + +- For example, QtQml.Models 2.0: +- - base/QtQml/Models.2.0/qmldir +- - base/QtQml.2.0/Models/qmldir +- - base/QtQml/Models.2/qmldir +- - base/QtQml.2/Models/qmldir +- - base/QtQml/Models/qmldir ++For example, QtQml.Models 2.0: ++- base/QtQml/Models.2.0/qmldir ++- base/QtQml.2.0/Models/qmldir ++- base/QtQml/Models.2/qmldir ++- base/QtQml.2/Models/qmldir ++- base/QtQml/Models/qmldir + */ + QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin) + { +@@ -547,15 +547,15 @@ QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringLi + if (!dir.endsWith(Slash) && !dir.endsWith(Backslash)) + dir += Slash; + +- // append to the end ++ // append to the end + qmlDirPathsPaths += dir + joinStringRefs(parts, Slash) + ver + Slash_qmldir; + + if (version != Unversioned) { + // insert in the middle + for (int index = parts.count() - 2; index >= 0; --index) { + qmlDirPathsPaths += dir + joinStringRefs(parts.mid(0, index + 1), Slash) +- + ver + Slash +- + joinStringRefs(parts.mid(index + 1), Slash) + Slash_qmldir; ++ + ver + Slash ++ + joinStringRefs(parts.mid(index + 1), Slash) + Slash_qmldir; + } + } + } +@@ -579,15 +579,15 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version) + /*! + \internal + +- The given (namespace qualified) \a type is resolved to either +- \list +- \li a QQmlImportNamespace stored at \a ns_return, or +- \li a QQmlType stored at \a type_return, +- \endlist ++The given (namespace qualified) \a type is resolved to either ++\list ++\li a QQmlImportNamespace stored at \a ns_return, or ++\li a QQmlType stored at \a type_return, ++\endlist + +- If any return pointer is 0, the corresponding search is not done. ++If any return pointer is 0, the corresponding search is not done. + +- \sa addFileImport(), addLibraryImport ++\sa addFileImport(), addLibraryImport + */ + bool QQmlImports::resolveType(const QHashedStringRef &type, + QQmlType *type_return, int *vmaj, int *vmin, +@@ -606,9 +606,9 @@ bool QQmlImports::resolveType(const QHashedStringRef &type, + typeRecursionDetected)) { + if (qmlImportTrace()) { + #define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \ +- << ')' << "::resolveType: " << type.toString() << " => " ++ << ')' << "::resolveType: " << type.toString() << " => " + +- if (type_return && type_return->isValid()) { ++ if (type_return && type_return->isValid()) { + if (type_return->isCompositeSingleton()) + RESOLVE_TYPE_DEBUG << type_return->typeName() << ' ' << type_return->sourceUrl() << " TYPE/URL-SINGLETON"; + else if (type_return->isComposite()) +@@ -676,12 +676,12 @@ QQmlDirScripts QQmlImportInstance::getVersionedScripts(const QQmlDirScripts &qml + /*! + \internal + +- Searching \e only in the namespace \a ns (previously returned in a call to +- resolveType(), \a type is found and returned to +- a QQmlType stored at \a type_return. If the type is from a QML file, the returned +- type will be a CompositeType. ++Searching \e only in the namespace \a ns (previously returned in a call to ++resolveType(), \a type is found and returned to ++a QQmlType stored at \a type_return. If the type is from a QML file, the returned ++type will be a CompositeType. + +- If the return pointer is 0, the corresponding search is not done. ++If the return pointer is 0, the corresponding search is not done. + */ + bool QQmlImports::resolveType(QQmlImportNamespace *ns, const QHashedStringRef &type, + QQmlType *type_return, int *vmaj, int *vmin, +@@ -764,7 +764,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt + break; + } + +- // importing version -1 means import ALL versions ++ // importing version -1 means import ALL versions + if ((majversion == -1) || + (implicitlyImported && c.internal) || // allow the implicit import of internal types + (c.majorVersion == majversion && c.minorVersion <= minversion)) { +@@ -788,7 +788,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt + } + } + +- // This is our best candidate so far ++ // This is our best candidate so far + candidate = it; + isCompositeSingleton = c.singleton; + } +@@ -864,7 +864,7 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, + const QVector splitName = type.split(Dot); + auto resolveTypeInNamespace = [&](QHashedStringRef unqualifiedtype, QQmlImportNamespace *nameSpace, QList *errors) -> bool { + if (nameSpace->resolveType(typeLoader, unqualifiedtype, vmajor, vminor, type_return, &base, errors, +- registrationType, typeRecursionDetected)) ++ registrationType, typeRecursionDetected)) + return true; + if (nameSpace->imports.count() == 1 && !nameSpace->imports.at(0)->isLibrary && type_return && nameSpace != &unqualifiedset) { + // qualified, and only 1 url +@@ -1029,9 +1029,9 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS + error.setDescription(QQmlImportDatabase::tr("is ambiguous. Found in %1 and in %2").arg(u1).arg(u2)); + } else { + error.setDescription(QQmlImportDatabase::tr("is ambiguous. Found in %1 in version %2.%3 and %4.%5") +- .arg(u1) +- .arg(import->majversion).arg(import->minversion) +- .arg(import2->majversion).arg(import2->minversion)); ++ .arg(u1) ++ .arg(import->majversion).arg(import->minversion) ++ .arg(import2->majversion).arg(import2->minversion)); + } + errors->prepend(error); + } +@@ -1065,7 +1065,7 @@ void QQmlImportNamespace::setNeedsSorting(bool needsSorting) + } + + QQmlImportsPrivate::QQmlImportsPrivate(QQmlTypeLoader *loader) +-: ref(1), typeLoader(loader) { ++ : ref(1), typeLoader(loader) { + } + + QQmlImportsPrivate::~QQmlImportsPrivate() +@@ -1113,8 +1113,8 @@ static QVector makePlugins() + for (const QStaticPlugin &plugin : staticPlugins) { + const QString iid = plugin.metaData().value(QLatin1String("IID")).toString(); + if (iid == QLatin1String(QQmlEngineExtensionInterface_iid) +- || iid == QLatin1String(QQmlExtensionInterface_iid) +- || iid == QLatin1String(QQmlExtensionInterface_iid_old)) { ++ || iid == QLatin1String(QQmlExtensionInterface_iid) ++ || iid == QLatin1String(QQmlExtensionInterface_iid_old)) { + plugins.append(plugin); + } + } +@@ -1127,20 +1127,20 @@ static QVector makePlugins() + above. + */ + bool QQmlImportsPrivate::populatePluginPairVector(QVector &result, const QString &uri, const QStringList &versionUris, +- const QString &qmldirPath, QList *errors) ++ const QString &qmldirPath, QList *errors) + { + static const QVector plugins = makePlugins(); + for (const QStaticPlugin &plugin : plugins) { + // Since a module can list more than one plugin, we keep iterating even after we found a match. + QObject *instance = plugin.instance(); + if (qobject_cast(instance) +- || qobject_cast(instance)) { ++ || qobject_cast(instance)) { + const QJsonArray metaTagsUriList = plugin.metaData().value(QLatin1String("uri")).toArray(); + if (metaTagsUriList.isEmpty()) { + if (errors) { + QQmlError error; + error.setDescription(QQmlImportDatabase::tr("static plugin for module \"%1\" with name \"%2\" has no metadata URI") +- .arg(uri).arg(QString::fromUtf8(instance->metaObject()->className()))); ++ .arg(uri).arg(QString::fromUtf8(instance->metaObject()->className()))); + error.setUrl(QUrl::fromLocalFile(qmldirPath)); + errors->prepend(error); + } +@@ -1192,8 +1192,8 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, + + if (database->qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(qmldirFilePath)) { + if ((vmaj >= 0 && vmin >= 0) +- ? !QQmlMetaType::isModule(uri, vmaj, vmin) +- : !QQmlMetaType::isAnyModule(uri)) { ++ ? !QQmlMetaType::isModule(uri, vmaj, vmin) ++ : !QQmlMetaType::isAnyModule(uri)) { + QQmlMetaType::qmlRegisterModuleTypes(uri, vmaj); + } + } else { +@@ -1260,7 +1260,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, + QQmlError poppedError = errors->takeFirst(); + QQmlError error; + error.setDescription(QQmlImportDatabase::tr("static plugin for module \"%1\" with name \"%2\" cannot be loaded: %3") +- .arg(uri).arg(QString::fromUtf8(instance->metaObject()->className())).arg(poppedError.description())); ++ .arg(uri).arg(QString::fromUtf8(instance->metaObject()->className())).arg(poppedError.description())); + error.setUrl(QUrl::fromLocalFile(qmldirFilePath)); + errors->prepend(error); + } +@@ -1337,7 +1337,7 @@ QString QQmlImportsPrivate::resolvedUri(const QString &dir_arg, QQmlImportDataba + + stableRelativePath.replace(Backslash, Slash); + +- // remove optional versioning in dot notation from uri ++ // remove optional versioning in dot notation from uri + int versionDot = stableRelativePath.lastIndexOf(Dot); + if (versionDot >= 0) { + int nextSlash = stableRelativePath.indexOf(Slash, versionDot); +@@ -1363,7 +1363,7 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir( + { + Q_ASSERT(vmaj >= 0 && vmin >= 0); // Versions are always specified for libraries + +- // Check cache first ++ // Check cache first + + QQmlImportDatabase::QmldirCache *cacheHead = nullptr; + { +@@ -1385,20 +1385,20 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir( + + QQmlTypeLoader &typeLoader = QQmlEnginePrivate::get(database->engine)->typeLoader; + +- // Interceptor might redirect remote files to local ones. ++ // Interceptor might redirect remote files to local ones. + QQmlAbstractUrlInterceptor *interceptor = typeLoader.engine()->urlInterceptor(); + QStringList localImportPaths = database->importPathList( +- interceptor ? QQmlImportDatabase::LocalOrRemote : QQmlImportDatabase::Local); ++ interceptor ? QQmlImportDatabase::LocalOrRemote : QQmlImportDatabase::Local); + +- // Search local import paths for a matching version ++ // Search local import paths for a matching version + const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths( +- uri, localImportPaths, vmaj, vmin); ++ uri, localImportPaths, vmaj, vmin); + bool pathTurnedRemote = false; + for (QString qmldirPath : qmlDirPaths) { + if (interceptor) { + const QUrl intercepted = interceptor->intercept( +- QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath), +- QQmlAbstractUrlInterceptor::QmldirFile); ++ QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath), ++ QQmlAbstractUrlInterceptor::QmldirFile); + qmldirPath = QQmlFile::urlToLocalFileOrQrc(intercepted); + if (!pathTurnedRemote && qmldirPath.isEmpty() && !QQmlFile::isLocalFile(intercepted)) + pathTurnedRemote = true; +@@ -1460,7 +1460,7 @@ bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent + // This entry clashes with a predecessor + QQmlError error; + error.setDescription(QQmlImportDatabase::tr("\"%1\" version %2.%3 is defined more than once in module \"%4\"") +- .arg(cit->typeName).arg(cit->majorVersion).arg(cit->minorVersion).arg(uri)); ++ .arg(cit->typeName).arg(cit->majorVersion).arg(cit->minorVersion).arg(uri)); + errors->prepend(error); + return false; + } +@@ -1484,7 +1484,7 @@ bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent + // This entry clashes with a predecessor + QQmlError error; + error.setDescription(QQmlImportDatabase::tr("\"%1\" version %2.%3 is defined more than once in module \"%4\"") +- .arg(sit->nameSpace).arg(sit->majorVersion).arg(sit->minorVersion).arg(uri)); ++ .arg(sit->nameSpace).arg(sit->majorVersion).arg(sit->minorVersion).arg(uri)); + errors->prepend(error); + return false; + } +@@ -1526,9 +1526,9 @@ QQmlImportNamespace *QQmlImportsPrivate::importNamespace(const QString &prefix) + } + + QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace *nameSpace, +- const QString &uri, const QString &url, int vmaj, int vmin, +- QV4::CompiledData::Import::ImportType type, +- QList *errors, bool lowPrecedence) ++ const QString &uri, const QString &url, int vmaj, int vmin, ++ QV4::CompiledData::Import::ImportType type, ++ QList *errors, bool lowPrecedence) + { + Q_ASSERT(nameSpace); + Q_ASSERT(errors); +@@ -1581,7 +1581,7 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre + } + } + +- // Ensure that we are actually providing something ++ // Ensure that we are actually providing something + if ((vmaj < 0) || (vmin < 0) || !QQmlMetaType::isModule(uri, vmaj, vmin)) { + if (inserted->qmlDirComponents.isEmpty() && inserted->qmlDirScripts.isEmpty()) { + QQmlError error; +@@ -1612,12 +1612,12 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix + QQmlImportNamespace *nameSpace = importNamespace(prefix); + Q_ASSERT(nameSpace); + +- // The uri for this import. For library imports this is the same as uri +- // specified by the user, but it may be different in the case of file imports. ++ // The uri for this import. For library imports this is the same as uri ++ // specified by the user, but it may be different in the case of file imports. + QString importUri = uri; + QString qmldirUrl = resolveLocalUrl(base, importUri + (importUri.endsWith(Slash) +- ? String_qmldir +- : Slash_qmldir)); ++ ? String_qmldir ++ : Slash_qmldir)); + if (QQmlAbstractUrlInterceptor *interceptor = typeLoader->engine()->urlInterceptor()) { + qmldirUrl = interceptor->intercept(QUrl(qmldirUrl), + QQmlAbstractUrlInterceptor::QmldirFile).toString(); +@@ -1640,8 +1640,8 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix + return false; + } + +- // Transforms the (possible relative) uri into our best guess relative to the +- // import paths. ++ // Transforms the (possible relative) uri into our best guess relative to the ++ // import paths. + importUri = resolvedUri(dir, database); + if (importUri.endsWith(Slash)) + importUri.chop(1); +@@ -1662,15 +1662,15 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix + + } + +- // The url for the path containing files for this import ++ // The url for the path containing files for this import + QString url = resolveLocalUrl(base, uri); + if (!url.endsWith(Slash) && !url.endsWith(Backslash)) + url += Slash; + +- // ### For enum support, we are now adding the implicit import always (and earlier). Bail early +- // if the implicit import has already been explicitly added, otherwise we can run into issues +- // with duplicate imports. However remember that we attempted to add this as implicit import, to +- // allow for the loading of internal types. ++ // ### For enum support, we are now adding the implicit import always (and earlier). Bail early ++ // if the implicit import has already been explicitly added, otherwise we can run into issues ++ // with duplicate imports. However remember that we attempted to add this as implicit import, to ++ // allow for the loading of internal types. + if (isImplicitImport) { + for (QList::const_iterator it = nameSpace->imports.constBegin(); + it != nameSpace->imports.constEnd(); ++it) { +@@ -1753,10 +1753,10 @@ bool QQmlImportsPrivate::updateQmldirContent(const QString &uri, const QString & + /*! + \internal + +- Adds an implicit "." file import. This is equivalent to calling addFileImport(), but error +- messages related to the path or qmldir file not existing are suppressed. ++Adds an implicit "." file import. This is equivalent to calling addFileImport(), but error ++messages related to the path or qmldir file not existing are suppressed. + +- Additionally, this will add the import with lowest instead of highest precedence. ++Additionally, this will add the import with lowest instead of highest precedence. + */ + bool QQmlImports::addImplicitImport(QQmlImportDatabase *importDb, QList *errors) + { +@@ -1789,23 +1789,23 @@ bool QQmlImports::addInlineComponentImport(QQmlImportInstance *const importInsta + /*! + \internal + +- Adds information to \a imports such that subsequent calls to resolveType() +- will resolve types qualified by \a prefix by considering types found at the given \a uri. ++Adds information to \a imports such that subsequent calls to resolveType() ++will resolve types qualified by \a prefix by considering types found at the given \a uri. + +- The uri is either a directory (if importType is FileImport), or a URI resolved using paths +- added via addImportPath() (if importType is LibraryImport). ++The uri is either a directory (if importType is FileImport), or a URI resolved using paths ++added via addImportPath() (if importType is LibraryImport). + +- The \a prefix may be empty, in which case the import location is considered for +- unqualified types. ++The \a prefix may be empty, in which case the import location is considered for ++unqualified types. + +- The base URL must already have been set with Import::setBaseUrl(). ++The base URL must already have been set with Import::setBaseUrl(). + +- Optionally, the url the import resolved to can be returned by providing the url parameter. +- Not all imports will result in an output url being generated, in which case the url will +- be set to an empty string. ++Optionally, the url the import resolved to can be returned by providing the url parameter. ++Not all imports will result in an output url being generated, in which case the url will ++be set to an empty string. + +- Returns true on success, and false on failure. In case of failure, the errors array will +- filled appropriately. ++Returns true on success, and false on failure. In case of failure, the errors array will ++filled appropriately. + */ + bool QQmlImports::addFileImport(QQmlImportDatabase *importDb, + const QString& uri, const QString& prefix, int vmaj, int vmin, +@@ -1870,7 +1870,7 @@ QUrl QQmlImports::urlFromLocalFileOrQrcOrUrl(const QString &file) + { + QUrl url(QLatin1String(file.at(0) == Colon ? "qrc" : "") + file); + +- // We don't support single character schemes as those conflict with windows drive letters. ++ // We don't support single character schemes as those conflict with windows drive letters. + if (url.scheme().length() < 2) + return QUrl::fromLocalFile(file); + return url; +@@ -1888,7 +1888,7 @@ void QQmlImports::setDesignerSupportRequired(bool b) + \internal + */ + QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e) +-: engine(e) ++ : engine(e) + { + filePluginPath << QLatin1String("."); + // Search order is applicationDirPath(), qrc:/qt-project.org/imports, $QML2_IMPORT_PATH, QLibraryInfo::Qml2ImportsPath +@@ -1896,7 +1896,7 @@ QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e) + QString installImportsPath = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); + addImportPath(installImportsPath); + +- // env import paths ++ // env import paths + if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QML2_IMPORT_PATH"))) { + const QString envImportPath = qEnvironmentVariable("QML2_IMPORT_PATH"); + #if defined(Q_OS_WIN) +@@ -1921,6 +1921,19 @@ QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e) + addPluginPath(paths.at(ii)); + } + #endif ++/* FIXME 因为鸿蒙权限限制 ++ * 将QML插件的加载和qml脚本的加载进行了区分 ++ */ ++#if defined(Q_OS_OPENHARMONY) ++ addImportPath(QStringLiteral("qrc:/harmony_rcc_bundle/qml")); ++ if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QT_HARMONY_BUNDLED_LIBS_PATH"))) { ++ const QString envImportPath = qEnvironmentVariable("QT_HARMONY_BUNDLED_LIBS_PATH"); ++ QLatin1Char pathSep(':'); ++ QStringList paths = envImportPath.split(pathSep, Qt::SkipEmptyParts); ++ for (int ii = paths.count() - 1; ii >= 0; --ii) ++ addPluginPath(paths.at(ii)); ++ } ++#endif + } + + QQmlImportDatabase::~QQmlImportDatabase() +@@ -1931,11 +1944,11 @@ QQmlImportDatabase::~QQmlImportDatabase() + /*! + \internal + +- Returns the result of the merge of \a baseName with \a path, \a suffixes, and \a prefix. +- The \a prefix must contain the dot. ++Returns the result of the merge of \a baseName with \a path, \a suffixes, and \a prefix. ++The \a prefix must contain the dot. + +- \a qmldirPath is the location of the qmldir file. +- */ ++\a qmldirPath is the location of the qmldir file. ++*/ + QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, + const QString &qmldirPath, + const QString &qmldirPluginPath, +@@ -1948,7 +1961,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, + searchPaths.prepend(qmldirPluginPath); + + for (const QString &pluginPath : qAsConst(searchPaths)) { +- QString resolvedPath; ++ QString resolvedPath; + if (pluginPath == QLatin1String(".")) { + if (qmldirPluginPathIsRelative && !qmldirPluginPath.isEmpty() && qmldirPluginPath != QLatin1String(".")) + resolvedPath = QDir::cleanPath(qmldirPath + Slash + qmldirPluginPath); +@@ -1959,9 +1972,19 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, + resolvedPath = QDir::cleanPath(qmldirPath + Slash + pluginPath); + else + resolvedPath = pluginPath; +- } + +- // hack for resources, should probably go away ++ } ++/* FIXME 因为鸿蒙安全限制,QML脚本和扩展插件加载路径有区别 ++ * 使用环境变量QT_HARMONY_BUNDLED_LIBS_PATH的值替换鸿蒙rawfile资源文件的路径 ++ * 用以qml扩展插件的加载 ++ */ ++#if defined(Q_OS_OPENHARMONY) ++ if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QT_HARMONY_CACHE_DIR"))) { ++ QString cacheQmlStr = qEnvironmentVariable("QT_HARMONY_CACHE_DIR"); ++ resolvedPath = QString(qmldirPath).replace(cacheQmlStr, pluginPath); ++ } ++#endif ++ // hack for resources, should probably go away + if (resolvedPath.startsWith(Colon)) + resolvedPath = QCoreApplication::applicationDirPath(); + +@@ -1970,7 +1993,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, + + #if defined(Q_OS_ANDROID) + if (qmldirPath.size() > 25 && qmldirPath.at(0) == QLatin1Char(':') && qmldirPath.at(1) == QLatin1Char('/') && +- qmldirPath.startsWith(QStringLiteral(":/android_rcc_bundle/qml/"), Qt::CaseInsensitive)) { ++ qmldirPath.startsWith(QStringLiteral(":/android_rcc_bundle/qml/"), Qt::CaseInsensitive)) { + QString pluginName = qmldirPath.mid(21) + Slash + baseName; + pluginName.replace(QLatin1Char('/'), QLatin1Char('_')); + QString bundledPath = resolvedPath + QLatin1String("lib") + pluginName; +@@ -1999,20 +2022,20 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, + /*! + \internal + +- Returns the result of the merge of \a baseName with \a dir and the platform suffix. ++Returns the result of the merge of \a baseName with \a dir and the platform suffix. + +- \table +- \header \li Platform \li Valid suffixes +- \row \li Windows \li \c .dll +- \row \li Unix/Linux \li \c .so +- \row \li \macos \li \c .dylib, \c .bundle, \c .so +- \endtable ++\table ++\header \li Platform \li Valid suffixes ++\row \li Windows \li \c .dll ++\row \li Unix/Linux \li \c .so ++\row \li \macos \li \c .dylib, \c .bundle, \c .so ++\endtable + +- Version number on unix are ignored. ++Version number on unix are ignored. + */ + QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, +- const QString &qmldirPath, const QString &qmldirPluginPath, +- const QString &baseName) ++ const QString &qmldirPath, const QString &qmldirPluginPath, ++ const QString &baseName) + { + #if defined(Q_OS_WIN) + static const QString prefix; +@@ -2081,7 +2104,7 @@ void QQmlImportDatabase::addPluginPath(const QString& path) + + QUrl url = QUrl(path); + if (url.isRelative() || url.scheme() == QLatin1String("file") +- || (url.scheme().length() == 1 && QFile::exists(path)) ) { // windows path ++ || (url.scheme().length() == 1 && QFile::exists(path)) ) { // windows path + QDir dir = QDir(path); + filePluginPath.prepend(dir.canonicalPath()); + } else { +@@ -2154,7 +2177,7 @@ void QQmlImportDatabase::setImportPathList(const QStringList &paths) + for (auto it = paths.crbegin(); it != paths.crend(); ++it) + addImportPath(*it); + +- // Our existing cached paths may have been invalidated ++ // Our existing cached paths may have been invalidated + clearDirCache(); + } + +@@ -2173,8 +2196,8 @@ static bool registerPluginTypes(QObject *instance, const QString &basePath, cons + if (vmaj >= 0 && !typeNamespace.isEmpty() && !QQmlMetaType::protectModule(uri, vmaj)) { + QQmlError error; + error.setDescription( +- QString::fromLatin1("Cannot protect module %1 %2 as it was never registered") +- .arg(uri).arg(vmaj)); ++ QString::fromLatin1("Cannot protect module %1 %2 as it was never registered") ++ .arg(uri).arg(vmaj)); + errors->append(error); + return false; + } +@@ -2186,7 +2209,7 @@ static bool registerPluginTypes(QObject *instance, const QString &basePath, cons + \internal + */ + bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &basePath, +- const QString &uri, const QString &typeNamespace, int vmaj, QList *errors) ++ const QString &uri, const QString &typeNamespace, int vmaj, QList *errors) + { + // Dynamic plugins are differentiated by their filepath. For static plugins we + // don't have that information so we use their address as key instead. +@@ -2195,8 +2218,8 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba + StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes(); + QMutexLocker lock(&plugins->mutex); + +- // Plugin types are global across all engines and should only be +- // registered once. But each engine still needs to be initialized. ++ // Plugin types are global across all engines and should only be ++ // registered once. But each engine still needs to be initialized. + bool typesRegistered = plugins->contains(uniquePluginID); + + if (typesRegistered) { +@@ -2213,10 +2236,10 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba + return false; + } + +- // Release the lock on plugins early as we're done with the global part. Releasing the lock +- // also allows other QML loader threads to acquire the lock while this thread is blocking +- // in the initializeEngine call to the gui thread (which in turn may be busy waiting for +- // other QML loader threads and thus not process the initializeEngine call). ++ // Release the lock on plugins early as we're done with the global part. Releasing the lock ++ // also allows other QML loader threads to acquire the lock while this thread is blocking ++ // in the initializeEngine call to the gui thread (which in turn may be busy waiting for ++ // other QML loader threads and thus not process the initializeEngine call). + } + + if (!initializedPlugins.contains(uniquePluginID)) +@@ -2283,16 +2306,16 @@ bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QStr + plugin.loader = loader; + plugins->insert(absoluteFilePath, plugin); + +- // Continue with shared code path for dynamic and static plugins: ++ // Continue with shared code path for dynamic and static plugins: + if (!registerPluginTypes(instance, fileInfo.absolutePath(), uri, typeNamespace, vmaj, errors)) + return false; + } + } + +- // Release the lock on plugins early as we're done with the global part. Releasing the lock +- // also allows other QML loader threads to acquire the lock while this thread is blocking +- // in the initializeEngine call to the gui thread (which in turn may be busy waiting for +- // other QML loader threads and thus not process the initializeEngine call). ++ // Release the lock on plugins early as we're done with the global part. Releasing the lock ++ // also allows other QML loader threads to acquire the lock while this thread is blocking ++ // in the initializeEngine call to the gui thread (which in turn may be busy waiting for ++ // other QML loader threads and thus not process the initializeEngine call). + } + + if (!engineInitialized) +@@ -2362,10 +2385,10 @@ void QQmlImportDatabase::finalizePlugin(QObject *instance, const QString &path, + initializedPlugins.insert(path); + if (auto *extensionIface = qobject_cast(instance)) { + QQmlEnginePrivate::get(engine)->typeLoader.initializeEngine( +- extensionIface, uri.toUtf8().constData()); ++ extensionIface, uri.toUtf8().constData()); + } else if (auto *engineIface = qobject_cast(instance)) { + QQmlEnginePrivate::get(engine)->typeLoader.initializeEngine( +- engineIface, uri.toUtf8().constData()); ++ engineIface, uri.toUtf8().constData()); + } + } + +diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp +index 40300b1fe3..4aff260ac3 100644 +--- a/src/qml/qml/qqmlmetatype.cpp ++++ b/src/qml/qml/qqmlmetatype.cpp +@@ -466,7 +466,7 @@ void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data) + QQmlTypeModule *module = getTypeModule(mod, type->version_maj, data); + Q_ASSERT(module); + module->add(type); +- } ++ } + } + + QQmlType QQmlMetaType::registerType(const QQmlPrivate::RegisterType &type) +@@ -527,8 +527,7 @@ QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::Registe + QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterCompositeType &type) + { + // Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type. +- QQmlMetaTypeDataPtr data; +- ++ QQmlMetaTypeDataPtr data; + QString typeName = QString::fromUtf8(type.typeName); + bool fileImport = false; + if (*(type.uri) == '\0') diff --git a/src/qml/qml/qqmlplatform.cpp b/src/qml/qml/qqmlplatform.cpp index dcd7ca2d46..a03b569641 100644 --- a/src/qml/qml/qqmlplatform.cpp @@ -109,9 +952,43 @@ index dcd7ca2d46..a03b569641 100644 return QStringLiteral("ios"); #elif defined(Q_OS_TVOS) diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp -index 01aba47a9a..c415d69f78 100644 +index 01aba47a9a..96bce3548a 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp +@@ -806,7 +806,6 @@ QQmlRefPointer QQmlTypeLoader::getType(const QUrl &unNormalizedUrl + const QUrl url = normalize(unNormalizedUrl); + + LockHolder holder(this); +- + QQmlTypeData *typeData = m_typeCache.value(url); + + if (!typeData) { +@@ -819,7 +818,7 @@ QQmlRefPointer QQmlTypeLoader::getType(const QUrl &unNormalizedUrl + m_typeCache.insert(url, typeData); + QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError; + if (const QV4::CompiledData::Unit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(typeData->url(), &error)) { +- QQmlTypeLoader::loadWithCachedUnit(typeData, cachedUnit, mode); ++ QQmlTypeLoader::loadWithCachedUnit(typeData, cachedUnit, mode); + } else { + typeData->setCachedUnitStatus(error); + QQmlTypeLoader::load(typeData, mode); +@@ -893,6 +892,7 @@ Returns a QQmlQmldirData for \a url. The QQmlQmldirData may be cached. + */ + QQmlRefPointer QQmlTypeLoader::getQmldir(const QUrl &url) + { ++ qWarning() << Q_FUNC_INFO << url; + Q_ASSERT(!url.isRelative() && + (QQmlFile::urlToLocalFileOrQrc(url).isEmpty() || + !QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(url)))); +@@ -919,7 +919,7 @@ we avoid many stats. We also cache the files' existence in the + directory, for the same reason. + */ + QString QQmlTypeLoader::absoluteFilePath(const QString &path) +-{ ++{ + if (path.isEmpty()) + return QString(); + if (path.at(0) == QLatin1Char(':')) { @@ -945,7 +945,14 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path) return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString(); } diff --git a/patch/v5.15.12/qtmultimedia.patch b/patch/v5.15.12/qtmultimedia.patch index e18d10094b..acb598eb28 100644 --- a/patch/v5.15.12/qtmultimedia.patch +++ b/patch/v5.15.12/qtmultimedia.patch @@ -255,11 +255,11 @@ index 000000000..7a3fc0e63 + diff --git a/src/openharmony/native/QtMultiMedia/JsMultiMediaModule.ts b/src/openharmony/native/QtMultiMedia/JsMultiMediaModule.ts new file mode 100644 -index 000000000..851ab4432 +index 000000000..cd08a2070 --- /dev/null +++ b/src/openharmony/native/QtMultiMedia/JsMultiMediaModule.ts -@@ -0,0 +1,38 @@ -+import { JsQtModule } from '../QtCore/JsQtModule'; +@@ -0,0 +1,44 @@ ++import { JsQtModule, ObjectBuilder } from '../QtCore/JsQtModule'; +import JsDataStore from '../QtCore/JsDataStore'; +import JsLogger from '../QtCore/JsLogger'; +import { JsAudioManager } from './JsAudioManager' @@ -271,12 +271,18 @@ index 000000000..851ab4432 + + public constructor() { + super() -+ this.moduleJsObjects = { -+ JsAudioManager, -+ JsMediaRecorder, -+ JsMultimediaUtils, -+ JsCameraManager -+ }; ++ this.moduleJsObjects.set("JsAudioManager", new ObjectBuilder<[]>(() =>{ ++ return new JsAudioManager(); ++ })); ++ this.moduleJsObjects.set("JsMediaRecorder", new ObjectBuilder<[]>(() =>{ ++ return new JsMediaRecorder(); ++ })); ++ this.moduleJsObjects.set("JsMultimediaUtils", new ObjectBuilder<[]>(() =>{ ++ return new JsMultimediaUtils(); ++ })); ++ this.moduleJsObjects.set("JsCameraManager", new ObjectBuilder<[]>(() =>{ ++ return new JsCameraManager(); ++ })); + this.loadQtModule(); + } + @@ -326,7 +332,7 @@ index 000000000..3adf5fe55 +} diff --git a/src/openharmony/openharmony.pro b/src/openharmony/openharmony.pro new file mode 100644 -index 000000000..966d9dcf0 +index 000000000..6f97b7df9 --- /dev/null +++ b/src/openharmony/openharmony.pro @@ -0,0 +1,9 @@ @@ -334,7 +340,7 @@ index 000000000..966d9dcf0 + +CONFIG -= qt + -+templates.files += $$files($$PWD/native/QtMultiMedia/*.ts, true) ++templates.files += $$files($$PWD/native/QtMultiMedia/*, true) +templates.path = $$[QT_INSTALL_PREFIX]/openharmony/qtmultimedia +templates.base = $$PWD + diff --git a/patch/v5.15.12/qtsensors.patch b/patch/v5.15.12/qtsensors.patch index 6a1ea061b5..3c6c96f30b 100644 --- a/patch/v5.15.12/qtsensors.patch +++ b/patch/v5.15.12/qtsensors.patch @@ -137,11 +137,11 @@ index 00000000..51919095 \ No newline at end of file diff --git a/src/openharmony/native/QtSensors/JsSensorsModule.ts b/src/openharmony/native/QtSensors/JsSensorsModule.ts new file mode 100644 -index 00000000..1d426bcf +index 00000000..8e328f10 --- /dev/null +++ b/src/openharmony/native/QtSensors/JsSensorsModule.ts -@@ -0,0 +1,24 @@ -+import { JsQtModule } from '../QtCore/JsQtModule'; +@@ -0,0 +1,26 @@ ++import { JsQtModule, ObjectBuilder } from '../QtCore/JsQtModule'; +import JsDataStore from '../QtCore/JsDataStore'; +import JsSensor from './JsSensor'; +import JsSensorManager from './JsSensorManager'; @@ -150,10 +150,12 @@ index 00000000..1d426bcf + + public constructor() { + super() -+ this.moduleJsObjects = { -+ JsSensor, -+ JsSensorManager -+ }; ++ this.moduleJsObjects.set("JsSensor", new ObjectBuilder<[number]>((id: number) =>{ ++ return new JsSensor(id); ++ })); ++ this.moduleJsObjects.set("JsSensorManager", new ObjectBuilder<[]>(() =>{ ++ return new JsSensorManager(); ++ })); + this.loadQtModule(); + } + @@ -1132,7 +1134,7 @@ index 00000000..aa0907df +#endif // SENSORBACKEND_H diff --git a/src/plugins/sensors/openharmony/sensormanager.cpp b/src/plugins/sensors/openharmony/sensormanager.cpp new file mode 100644 -index 00000000..cfa50cb0 +index 00000000..b368d556 --- /dev/null +++ b/src/plugins/sensors/openharmony/sensormanager.cpp @@ -0,0 +1,114 @@ @@ -1209,12 +1211,12 @@ index 00000000..cfa50cb0 + +void JsSensor::stop(int id) +{ -+ m_jsSensor->call("stop", id); ++ m_jsSensor->callWithoutReturn("stop", id); +} + +void JsSensor::start(int id, int rate) +{ -+ m_jsSensor->call("start", id, rate); ++ m_jsSensor->callWithoutReturn("start", id, rate); +} + +QString JsSensor::hardwareVersion(int id) const -- Gitee