On this page

Qt for HarmonyOS Window Drag Key Frame Example

Sets the key frame policy for resizing the window of a Qt application on HarmonyOS.

While the user resizes a window by dragging its edge, the platform can report the new size only at key frames instead of continuously. The key frame policy of the window enables this mode and sets when the key frames come. The example sets the policy with the setDragKeyFramePolicy() method of its window.Window.

The policy is collected on the Qt thread as a QJsonObject, with only the parameters that are set. The window gets its window.Window from QNativeInterface::QHarmonyWindow on the Qt thread, as a QHarmonyJsObjectRef handle, and hands both to the JS thread:

QJsonObject KeyFramePolicyWindow::makePolicy() const
{
    QJsonObject policy{{QStringLiteral("enable"), m_enableCheckBox->isChecked()}};
    if (!m_enableCheckBox->isChecked())
        return policy;

    for (const PolicyParameter &parameter : m_policyParameters) {
        if (parameter.setCheckBox->isChecked())
            policy.insert(parameter.key, parameter.valueSpinBox->value());
    }
    return policy;
}

void KeyFramePolicyWindow::applyPolicy()
{
    auto *harmonyWindow = windowHandle() ? windowHandle()->nativeInterface<QNativeInterface::QHarmonyWindow>() : nullptr;
    const auto jsWindowRef = harmonyWindow ? harmonyWindow->jsWindow() : QHarmonyJsObjectRef();
    const QJsonObject policy = makePolicy();
    m_log->append(QStringLiteral("requested policy: %1").arg(toCompactJson(policy)));

    QHarmonyApplication::runOnJsThread(
        [jsWindowRef, policy, log = QPointer<QTextEdit>(m_log)](QHarmonyJsContext &jsContext) {
            applyDragKeyFramePolicy(jsContext, jsWindowRef, policy, log);
        });
}

On the JS thread, the task maps the policy to a JS object with QtHarmony::mapQJsonObjectToJsObject() and calls setDragKeyFramePolicy(). The promise that it returns resolves to the policy that is in effect. The handler maps that policy back with QtHarmony::mapJsObjectToQJsonObject() and posts it to the Qt thread with QNativeInterface::QHarmonyApplication::runOnQtThread(), where the window logs it. A rejection, or an error that the calls throw, is logged in the same way:

void showStatusInLog(QPointer<QTextEdit> log, QString text)
{
    QHarmonyApplication::runOnQtThread(
        [log, text]() {
            if (log)
                log->append(text);
        });
}

void showFailureInLog(QPointer<QTextEdit> log, const QString &asyncCallName, const QString &errorText)
{
    showStatusInLog(log, QStringLiteral("%1 failed: %2").arg(asyncCallName, errorText));
}

void applyDragKeyFramePolicy(
    QHarmonyJsContext &jsContext, const QHarmonyJsObjectRef &jsWindowRef, const QJsonObject &policy,
    QPointer<QTextEdit> log)
{
    const QString asyncCallName = QStringLiteral("setDragKeyFramePolicy()");
    Napi::Env env(jsContext.env());
    Napi::Object jsWindow(env, jsWindowRef.value(jsContext));
    if (jsWindow.IsEmpty()) {
        showFailureInLog(log, asyncCallName, QStringLiteral("the window is not shown in a window.Window"));
        return;
    }

    try {
        Napi::Object jsPolicy(env, QtHarmony::mapQJsonObjectToJsObject(env, policy));
        auto setDragKeyFramePolicyFunc = jsWindow.Get("setDragKeyFramePolicy").As<Napi::Function>();
        auto setDragKeyFramePolicyPromise = setDragKeyFramePolicyFunc.Call(jsWindow, {jsPolicy}).As<Napi::Object>();
        setDragKeyFramePolicyPromise.Get("then").As<Napi::Function>().Call(
            setDragKeyFramePolicyPromise,
            {
                Napi::Function::New(
                    env,
                    [log, asyncCallName](const Napi::CallbackInfo &info) {
                        const QJsonObject effectivePolicy = QtHarmony::mapJsObjectToQJsonObject(info.Env(), info[0]);
                        showStatusInLog(log, QStringLiteral("%1 succeeded, effective policy: %2").arg(asyncCallName, toCompactJson(effectivePolicy)));
                    }),
                Napi::Function::New(
                    env,
                    [log, asyncCallName](const Napi::CallbackInfo &info) {
                        showFailureInLog(log, asyncCallName, QString::fromStdString(info[0].ToString()));
                    }),
            });
    } catch (const Napi::Error &error) {
        showFailureInLog(log, asyncCallName, QString::fromUtf8(error.what()));
    }
}

Running the Example

Select Key frame mode enabled and press Apply. Then resize the window by dragging its edge and compare it with resizing in the default mode. The log shows the policy that is in effect. Reset to defaults disables the key frame mode.

The example needs a device on which the user can resize the window by dragging its edge. On a phone, the main window fills the screen and cannot be resized in this way. On a device that does not support the key frame mode, the call fails and the window logs the error.

Example project @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.