[OpenDocString] kdeconnect-kde (cpp)
waylandremoteinput.cpp
moteDesktopSession::RemoteDesktopSession()
    : iface(new OrgFreedesktopPortalRemoteDesktopInterface(QLatin1String("org.freedesktop.portal.Desktop"),
                                                           QLatin1String("/org/freedesktop/portal/desktop"),
                                                           QDBusConnection::sessionBus(),
                                                           this))
{
}
This constructor builds a remote desktop session object. It takes the org.freedesktop.portal.Desktop object from the input, and creates a QDBusConnection object and adds it to the session bus.
id RemoteDesktopSession::createSession()
{
    if (isValid()) {
        qCDebug(KDECONNECT_PLUGIN_MOUSEPAD) << "pass, already created";
        return;
    }

    m_connecting = true;

    // create session
    const auto handleToken = QStringLiteral("kdeconnect%1").arg(QRandomGenerator::global()->generate());
    const auto sessionParameters = QVariantMap{{QLatin1String("session_handle_token"), handleToken}, {QLatin1String("handle_token"), handleToken}};
    auto sessionReply = iface->CreateSession(sessionParameters);
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(sessionReply);
    connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, sessionReply](QDBusPendingCallWatcher *self) {
        self->deleteLater();
        if (sessionReply.isError()) {
            qCWarning(KDECONNECT_PLUGIN_MOUSEPAD) << "Could not create the remote control session" << sessionReply.error();
            m_connecting = false;
            return;
        }

        bool b = QDBusConnection::sessionBus().connect(QString(),
                                                       sessionReply.value().path(),
                                                       QLatin1String("org.freedesktop.portal.Request"),
                                                       QLatin1String("Response"),
                                                       this,
                                                       SLOT(handleXdpSessionCreated(uint, QVariantMap)));
        Q_ASSERT(b);

        qCDebug(KDECONNECT_PLUGIN_MOUSEPAD) << "authenticating" << sessionReply.value().path();
    });
}
This creates a remote control session using a token. It creates a session_handle_token and connects it to the sessionReply.
id RemoteDesktopSession::handleXdpSessionCreated(uint code, const QVariantMap &results)
{
    if (code != 0) {
        qCWarning(KDECONNECT_PLUGIN_MOUSEPAD) << "Failed to create session with code" << code << results;
        return;
    }
    m_connecting = false;
    m_xdpPath = QDBusObjectPath(results.value(QLatin1String("session_handle")).toString());
    const QVariantMap startParameters = {
        {QLatin1String("handle_token"), QStringLiteral("kdeconnect%1").arg(QRandomGenerator::global()->generate())},
        {QStringLiteral("types"), QVariant::fromValue(7)}, // request all (KeyBoard, Pointer, TouchScreen)
    };

    QDBusConnection::sessionBus().connect(QString(),
                                          m_xdpPath.path(),
                                          QLatin1String("org.freedesktop.portal.Session"),
                                          QLatin1String("Closed"),
                                          this,
                                          SLOT(handleXdpSessionFinished(uint, QVariantMap)));

    auto reply = iface->SelectDevices(m_xdpPath, startParameters);
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply);
    connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, reply](QDBusPendingCallWatcher *self) {
        self->deleteLater();
        if (reply.isError()) {
            qCWarning(KDECONNECT_PLUGIN_MOUSEPAD) << "Could not start the remote control session" << reply.error();
            m_connecting = false;
            return;
        }

        bool b = QDBusConnection::sessionBus().connect(QString(),
                                                       reply.value().path(),
                                                       QLatin1String("org.freedesktop.portal.Request"),
                                                       QLatin1String("Response"),
                                                       this,
                                                       SLOT(handleXdpSessionConfigured(uint, QVariantMap)));
        Q_ASSERT(b);
        qCDebug(KDECONNECT_PLUGIN_MOUSEPAD) << "configuring" << reply.value().path();
    });
}
This creates a remote control session by first connecting to the xdp session path, and then requesting all devices. It also connects the session to the remote device bus, and sets m_connecting to true.
id RemoteDesktopSession::handleXdpSessionConfigured(uint code, const QVariantMap &results)
{
    if (code != 0) {
        qCWarning(KDECONNECT_PLUGIN_MOUSEPAD) << "Failed to configure session with code" << code << results;
        m_connecting = false;
        return;
    }
    const QVariantMap startParameters = {
        {QLatin1String("handle_token"), QStringLiteral("kdeconnect%1").arg(QRandomGenerator::global()->generate())},
    };
    auto reply = iface->Start(m_xdpPath, {}, startParameters);
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply);
    connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, reply](QDBusPendingCallWatcher *self) {
        self->deleteLater();
        if (reply.isError()) {
            qCWarning(KDECONNECT_PLUGIN_MOUSEPAD) << "Could not start the remote control session" << reply.error();
            m_connecting = false;
        }
    });
}
This implements the handle_xdp_session_configured function, which sets m_connecting to true and sets the xdp session to active. It takes the code of the program and creates a QDBusInterface object and sets the start parameter to start the remote control session. It also connects the callback to the finished signal.
id RemoteDesktopSession::handleXdpSessionFinished(uint /*code*/, const QVariantMap & /*results*/)
{
    m_xdpPath = {};
}
This implements the finishing sequence of a XDP session.
ylandRemoteInput::WaylandRemoteInput(QObject *parent)
    : AbstractRemoteInput(parent)
{
}
This constructor builds a WaylandRemoteInput object from an existing parent object.
ylandRemoteInput::~WaylandRemoteInput()
{
}
This implements the wayland remote input feature of the application and returns a pointer to a WaylandRemoteInput object.
ol WaylandRemoteInput::handlePacket(const NetworkPacket &np)
{
    if (!s_session->isValid()) {
        qCWarning(KDECONNECT_PLUGIN_MOUSEPAD) << "Unable to handle remote input. RemoteDesktop portal not authenticated";
        s_session->createSession();
        return false;
    }

    const float dx = np.get(QStringLiteral("dx"), 0);
    const float dy = np.get(QStringLiteral("dy"), 0);

    const bool isSingleClick = np.get(QStringLiteral("singleclick"), false);
    const bool isDoubleClick = np.get(QStringLiteral("doubleclick"), false);
    const bool isMiddleClick = np.get(QStringLiteral("middleclick"), false);
    const bool isRightClick = np.get(QStringLiteral("rightclick"), false);
    const bool isSingleHold = np.get(QStringLiteral("singlehold"), false);
    const bool isSingleRelease = np.get(QStringLiteral("singlerelease"), false);
    const bool isScroll = np.get(QStringLiteral("scroll"), false);
    const QString key = np.get(QStringLiteral("key"), QLatin1String(""));
    const int specialKey = np.get(QStringLiteral("specialKey"), 0);

    if (isSingleClick || isDoubleClick || isMiddleClick || isRightClick || isSingleHold || isSingleRelease || isScroll || !key.isEmpty() || specialKey) {
        if (isSingleClick) {
            s_session->iface->NotifyPointerButton(s_session->m_xdpPath, {}, BTN_LEFT, 1);
            s_session->iface->NotifyPointerButton(s_session->m_xdpPath, {}, BTN_LEFT, 0);
        } else if (isDoubleClick) {
            s_session->iface->NotifyPointerButton(s_session->m_xdpPath, {}, BTN_LEFT, 1);
            s_session->iface->NotifyPointerButton(s_session->m_xdpPath, {}, BTN_LEFT, 0);
            s_session->iface->NotifyPointerButton(s_session->m_xdpPath, {}, BTN_LEFT, 1);
            s_session->iface->NotifyPointerButton(s_session->m_xdpPath, {}, BTN_LEFT, 0);
        } else if (isMiddleClick) {
            s_session->iface->NotifyPointerButton(s_session->m_xdpPath, {}, BTN_MIDDLE, 1);
            s_session->iface->NotifyPointerButton(s_session->m_xdpPath, {}, BTN_MIDDLE, 0);
        } else if (isRightClick) {
            s_session->iface->NotifyPointerButton(s_session->m_xdpPath, {}, BTN_RIGHT, 1);
            s_session->iface->NotifyPointerButton(s_session->m_xdpPath, {}, BTN_RIGHT, 0);
        } else if (isSingleHold) {
            // For drag'n drop
            s_session->iface->NotifyPointerButton(s_session->m_xdpPath, {}, BTN_LEFT, 1);
        } else if (isSingleRelease) {
            // For drag'n drop. NEVER USED (release is done by tapping, which actually triggers a isSingleClick). Kept here for future-proofness.
            s_session->iface->NotifyPointerButton(s_session->m_xdpPath, {}, BTN_LEFT, 0);
        } else if (isScroll) {
            s_session->iface->NotifyPointerAxis(s_session->m_xdpPath, {}, dx, dy);
        } else if (specialKey) {
            s_session->iface->NotifyKeyboardKeycode(s_session->m_xdpPath, {}, SpecialKeysMap[specialKey], 1);
            s_session->iface->NotifyKeyboardKeycode(s_session->m_xdpPath, {}, SpecialKeysMap[specialKey], 0);
        } else if (!key.isEmpty()) {
            for (const QChar character : key) {
                const auto keysym = xkb_utf32_to_keysym(character.unicode());
                if (keysym != XKB_KEY_NoSymbol) {
                    s_session->iface->NotifyKeyboardKeysym(s_session->m_xdpPath, {}, keysym, 1).waitForFinished();
                    s_session->iface->NotifyKeyboardKeysym(s_session->m_xdpPath, {}, keysym, 0).waitForFinished();
                } else {
                    qCDebug(KDECONNECT_PLUGIN_MOUSEPAD) << "Cannot send character" << character;
                }
            }
        }
    } else { // Is a mouse move event
        s_session->iface->NotifyPointerMotion(s_session->m_xdpPath, {}, dx, dy);
    }
    return true;
}
This retrieves information about two packets: single click doubleclick middleclick and rightclick, scroll and single hold.