deskflow/src/lib/platform/PortalRemoteDesktop.cpp
sithlord48 55a7fa3266
Some checks failed
CodeQL Analysis / Analyze (cpp) (push) Has been cancelled
Continuous Integration / reuse-lint (push) Has been cancelled
Continuous Integration / pr-comment-flags (push) Has been cancelled
Continuous Integration / ci-passed (push) Has been cancelled
Continuous Integration / test-results (push) Has been cancelled
Continuous Integration / lint-check (push) Has been cancelled
Continuous Integration / analyse-valgrind (push) Has been cancelled
Continuous Integration / analyse-sonarcloud (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-DCMAKE_OSX_ARCHITECTURES="arm64" -DCMAKE_OSX_SYSROOT=/Applications/Xcode_15.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk name:macos-14-arm64 qt-install-dir:/Users/runner runs-o… (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-DCMAKE_OSX_ARCHITECTURES="x86_64" -DCMAKE_OSX_SYSROOT=/Applications/Xcode_15.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk name:macos-13-x64 qt-install-dir:/Users/runner runs-on… (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:archlinux:latest like:arch name:archlinux-x86_84 runs-on:ubuntu-latest timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:debian:trixie-slim like:debian name:debian-13-arm64 runs-on:ubuntu-24.04-arm timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:debian:trixie-slim like:debian name:debian-13-x86_64 runs-on:ubuntu-latest timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:fedora:40 like:fedora name:fedora-40-arm64 runs-on:ubuntu-24.04-arm timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:fedora:40 like:fedora name:fedora-40-x86_84 runs-on:ubuntu-latest timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:fedora:41 like:fedora name:fedora-41-arm64 runs-on:ubuntu-24.04-arm timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:fedora:41 like:fedora name:fedora-41-x86_64 runs-on:ubuntu-latest timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:fedora:42 like:fedora name:fedora-42-arm64 runs-on:ubuntu-24.04-arm timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:fedora:42 like:fedora name:fedora-42-x86_64 runs-on:ubuntu-latest timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:opensuse/tumbleweed:latest like:suse name:opensuse-arm64 runs-on:ubuntu-24.04-arm timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:opensuse/tumbleweed:latest like:suse name:opensuse-x86_84 runs-on:ubuntu-latest timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:ubuntu:25.04 like:debian name:ubuntu-25.04-arm64 runs-on:ubuntu-24.04-arm timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja -DCMAKE_INSTALL_PREFIX=/usr container:ubuntu:25.04 like:debian name:ubuntu-25.04-x86_64 runs-on:ubuntu-latest timeout:20]) (push) Has been cancelled
Continuous Integration / ${{ matrix.target.name }} (map[config-args:-G Ninja name:windows-2022-x64 qt-install-dir:C: runs-on:windows-2022 timeout:30]) (push) Has been cancelled
Continuous Integration / unix-${{ matrix.distro.name }} (map[name:freebsd]) (push) Has been cancelled
Continuous Integration / flatpak-${{matrix.flatpak.arch}} (map[arch:aarch64 runs-on:ubuntu-24.04-arm]) (push) Has been cancelled
Continuous Integration / flatpak-${{matrix.flatpak.arch}} (map[arch:x86_64 runs-on:ubuntu-latest]) (push) Has been cancelled
Continuous Integration / release (push) Has been cancelled
Continuous Integration / winget-publish (push) Has been cancelled
Port simplified EventTypes from 8b23570379
2025-05-05 17:17:01 -04:00

176 lines
5.3 KiB
C++

/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2022 Red Hat, Inc.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "platform/PortalRemoteDesktop.h"
#include "base/Log.h"
#include "base/TMethodJob.h"
#include <sys/socket.h> // for EIS fd hack, remove
#include <sys/un.h> // for EIS fd hack, remove
namespace deskflow {
PortalRemoteDesktop::PortalRemoteDesktop(EiScreen *screen, IEventQueue *events)
: screen_(screen),
events_(events),
portal_(xdp_portal_new())
{
glib_main_loop_ = g_main_loop_new(nullptr, true);
glib_thread_ = new Thread(new TMethodJob<PortalRemoteDesktop>(this, &PortalRemoteDesktop::glib_thread));
reconnect(0);
}
PortalRemoteDesktop::~PortalRemoteDesktop()
{
if (g_main_loop_is_running(glib_main_loop_))
g_main_loop_quit(glib_main_loop_);
if (glib_thread_ != nullptr) {
glib_thread_->cancel();
glib_thread_->wait();
delete glib_thread_;
glib_thread_ = nullptr;
g_main_loop_unref(glib_main_loop_);
glib_main_loop_ = nullptr;
}
if (session_signal_id_)
g_signal_handler_disconnect(session_, session_signal_id_);
if (session_ != nullptr)
g_object_unref(session_);
g_object_unref(portal_);
free(session_restore_token_);
}
gboolean PortalRemoteDesktop::timeout_handler()
{
return true; // keep re-triggering
}
void PortalRemoteDesktop::reconnect(unsigned int timeout)
{
auto init_cb = [](gpointer data) -> gboolean {
return reinterpret_cast<PortalRemoteDesktop *>(data)->init_remote_desktop_session();
};
if (timeout > 0)
g_timeout_add(timeout, init_cb, this);
else
g_idle_add(init_cb, this);
}
void PortalRemoteDesktop::cb_session_closed(XdpSession *session)
{
LOG_ERR("portal remote desktop session was closed, reconnecting");
g_signal_handler_disconnect(session, session_signal_id_);
session_signal_id_ = 0;
events_->addEvent(Event(EventTypes::EISessionClosed, screen_->getEventTarget()));
// gcc warning "Suspicious usage of 'sizeof(A*)'" can be ignored
g_clear_object(&session_);
reconnect(1000);
}
void PortalRemoteDesktop::cb_session_started(GObject *object, GAsyncResult *res)
{
g_autoptr(GError) error = nullptr;
auto session = XDP_SESSION(object);
auto success = xdp_session_start_finish(session, res, &error);
if (!success) {
LOG_ERR("failed to start portal remote desktop session, quitting: %s", error->message);
g_main_loop_quit(glib_main_loop_);
events_->addEvent(EventTypes::Quit);
return;
}
session_restore_token_ = xdp_session_get_restore_token(session);
// ConnectToEIS requires version 2 of the xdg-desktop-portal (and the same
// version in the impl.portal), i.e. you'll need an updated compositor on
// top of everything...
auto fd = -1;
fd = xdp_session_connect_to_eis(session, &error);
if (fd < 0) {
g_main_loop_quit(glib_main_loop_);
events_->addEvent(EventTypes::Quit);
return;
}
// Socket ownership is transferred to the EiScreen
events_->addEvent(Event(EventTypes::EIConnected, screen_->getEventTarget(), EiScreen::EiConnectInfo::alloc(fd)));
}
void PortalRemoteDesktop::cb_init_remote_desktop_session(GObject *object, GAsyncResult *res)
{
LOG_DEBUG("portal remote desktop session initialized");
g_autoptr(GError) error = nullptr;
auto session = xdp_portal_create_remote_desktop_session_finish(XDP_PORTAL(object), res, &error);
if (!session) {
LOG_ERR("failed to initialize remote desktop session: %s", error->message);
// This was the first attempt to connect to the RD portal - quit if that
// fails.
if (session_iteration_ == 0) {
g_main_loop_quit(glib_main_loop_);
events_->addEvent(EventTypes::Quit);
} else {
this->reconnect(1000);
}
return;
}
session_ = session;
++session_iteration_;
// FIXME: the lambda trick doesn't work here for unknown reasons, we need
// the static function
session_signal_id_ = g_signal_connect(G_OBJECT(session), "closed", G_CALLBACK(cb_session_closed_cb), this);
LOG_DEBUG("portal remote desktop session starting");
xdp_session_start(
session,
nullptr, // parent
nullptr, // cancellable
[](GObject *obj, GAsyncResult *res, gpointer data) {
reinterpret_cast<PortalRemoteDesktop *>(data)->cb_session_started(obj, res);
},
this
);
}
gboolean PortalRemoteDesktop::init_remote_desktop_session()
{
LOG_DEBUG("setting up remote desktop session with restore token %s", session_restore_token_);
xdp_portal_create_remote_desktop_session_full(
portal_, static_cast<XdpDeviceType>(XDP_DEVICE_POINTER | XDP_DEVICE_KEYBOARD), XDP_OUTPUT_NONE,
XDP_REMOTE_DESKTOP_FLAG_NONE, XDP_CURSOR_MODE_HIDDEN, XDP_PERSIST_MODE_TRANSIENT, session_restore_token_,
nullptr, // cancellable
[](GObject *obj, GAsyncResult *res, gpointer data) {
reinterpret_cast<PortalRemoteDesktop *>(data)->cb_init_remote_desktop_session(obj, res);
},
this
);
return false; // don't reschedule
}
void PortalRemoteDesktop::glib_thread(void *)
{
auto context = g_main_loop_get_context(glib_main_loop_);
while (g_main_loop_is_running(glib_main_loop_)) {
Thread::testCancel();
g_main_context_iteration(context, true);
}
}
} // namespace deskflow