fix(wayland): stop reprompting for portal permission on every restore

some backends never report clipboard as enabled even when granted, so the retry looped forever; now it only retries once per role, then keeps the session.
This commit is contained in:
ElCruncharino 2026-07-25 10:57:36 -04:00 committed by Nick Bolton
parent 0baecf3fa7
commit 0ab18b86b3
3 changed files with 45 additions and 32 deletions

View file

@ -43,6 +43,7 @@ public:
inline static const auto XScrollScale = QStringLiteral("client/xScrollScale"); inline static const auto XScrollScale = QStringLiteral("client/xScrollScale");
inline static const auto LanguageSync = QStringLiteral("client/languageSync"); inline static const auto LanguageSync = QStringLiteral("client/languageSync");
inline static const auto RemoteHost = QStringLiteral("client/remoteHost"); inline static const auto RemoteHost = QStringLiteral("client/remoteHost");
inline static const auto XdpClipboardRetried = QStringLiteral("client/xdpClipboardRetried");
inline static const auto XdpRestoreToken = QStringLiteral("client/xdpRestoreToken"); inline static const auto XdpRestoreToken = QStringLiteral("client/xdpRestoreToken");
}; };
struct Core struct Core
@ -121,6 +122,7 @@ public:
inline static const auto SwitchDelay = QStringLiteral("server/switchDelay"); inline static const auto SwitchDelay = QStringLiteral("server/switchDelay");
inline static const auto SwitchDoubleTap = QStringLiteral("server/switchDoubleTap"); inline static const auto SwitchDoubleTap = QStringLiteral("server/switchDoubleTap");
inline static const auto Win32KeepForeground = QStringLiteral("server/win32KeepForeground"); inline static const auto Win32KeepForeground = QStringLiteral("server/win32KeepForeground");
inline static const auto XdpClipboardRetried = QStringLiteral("server/xdpClipboardRetried");
inline static const auto XdpRestoreToken = QStringLiteral("server/xdpRestoreToken"); inline static const auto XdpRestoreToken = QStringLiteral("server/xdpRestoreToken");
}; };
@ -334,6 +336,7 @@ private:
, Client::DynamicConnectionRetry , Client::DynamicConnectionRetry
, Client::InvertYScroll , Client::InvertYScroll
, Client::InvertXScroll , Client::InvertXScroll
, Client::XdpClipboardRetried
, Log::ToFile , Log::ToFile
, Log::GuiDebug , Log::GuiDebug
, Server::DefaultLockToComputerState , Server::DefaultLockToComputerState
@ -343,6 +346,7 @@ private:
, Server::EnableSwitchDoubleTap , Server::EnableSwitchDoubleTap
, Server::ExternalConfig , Server::ExternalConfig
, Server::RelativeMouseMoves , Server::RelativeMouseMoves
, Server::XdpClipboardRetried
}; };
// When checking the default values this list contains the ones that default to true. // When checking the default values this list contains the ones that default to true.
@ -362,7 +366,9 @@ private:
// Settings saved in our State file // Settings saved in our State file
inline static const QStringList m_stateKeys = { inline static const QStringList m_stateKeys = {
Gui::WindowGeometry Gui::WindowGeometry
, Client::XdpClipboardRetried
, Client::XdpRestoreToken , Client::XdpRestoreToken
, Server::XdpClipboardRetried
, Server::XdpRestoreToken , Server::XdpRestoreToken
}; };

View file

@ -11,6 +11,7 @@
#include "base/Event.h" #include "base/Event.h"
#include "base/Log.h" #include "base/Log.h"
#include "base/TMethodJob.h" #include "base/TMethodJob.h"
#include "common/Settings.h"
#include "deskflow/ClipboardTypes.h" #include "deskflow/ClipboardTypes.h"
#include "platform/EiClipboard.h" #include "platform/EiClipboard.h"
@ -18,10 +19,6 @@
#include "platform/PortalClipboard.h" #include "platform/PortalClipboard.h"
#endif #endif
#ifdef HAVE_LIBPORTAL_INPUTCAPTURE_RESTORE
#include "common/Settings.h"
#endif
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <limits> #include <limits>
@ -298,17 +295,20 @@ void PortalInputCapture::setupSession(XdpInputCaptureSession *session)
#ifdef HAVE_LIBPORTAL_CLIPBOARD #ifdef HAVE_LIBPORTAL_CLIPBOARD
if (!xdp_session_is_clipboard_enabled(parentSession) && m_portalVersion > 1) { if (!xdp_session_is_clipboard_enabled(parentSession) && m_portalVersion > 1) {
// Restored sessions can pre-date clipboard support, leaving the channel if (Settings::value(Settings::Server::XdpClipboardRetried).toBool()) {
// disabled even though we requested it. Drop the saved token and recreate // some backends never report clipboard enabled even when granted; don't loop forever
// the session from scratch so the user gets a fresh permission dialog. LOG_DEBUG("clipboard still not enabled on session after one retry, continuing without it");
LOG_WARN("clipboard not enabled on session, discarding restore token to force a fresh session"); } else {
LOG_WARN("clipboard not enabled on session, discarding restore token to force a fresh session");
#ifdef HAVE_LIBPORTAL_INPUTCAPTURE_RESTORE #ifdef HAVE_LIBPORTAL_INPUTCAPTURE_RESTORE
Settings::setValue(Settings::Server::XdpRestoreToken, QString()); Settings::setValue(Settings::Server::XdpRestoreToken, QString());
#endif #endif
g_object_unref(m_session); Settings::setValue(Settings::Server::XdpClipboardRetried, true);
m_session = nullptr; g_object_unref(m_session);
g_idle_add([](gpointer data) { return static_cast<PortalInputCapture *>(data)->initSession(); }, this); m_session = nullptr;
return; g_idle_add([](gpointer data) { return static_cast<PortalInputCapture *>(data)->initSession(); }, this);
return;
}
} }
#endif #endif

View file

@ -100,28 +100,35 @@ void PortalRemoteDesktop::handleSessionStarted(GObject *object, GAsyncResult *re
#ifdef HAVE_LIBPORTAL_CLIPBOARD #ifdef HAVE_LIBPORTAL_CLIPBOARD
if (!xdp_session_is_clipboard_enabled(session)) { if (!xdp_session_is_clipboard_enabled(session)) {
LOG_WARN("clipboard not enabled on remote desktop session, discarding restore token to force a fresh session"); if (Settings::value(Settings::Client::XdpClipboardRetried).toBool()) {
Settings::setValue(Settings::Client::XdpRestoreToken, QString()); // some backends never report clipboard enabled even when granted; don't loop forever
free(m_sessionRestoreToken); LOG_DEBUG("clipboard still not enabled on remote desktop session after one retry, continuing without it");
m_sessionRestoreToken = nullptr; } else {
if (m_selectionTransferSignalId) { LOG_WARN("clipboard not enabled on remote desktop session, discarding restore token to force a fresh session");
g_signal_handler_disconnect(session, m_selectionTransferSignalId); Settings::setValue(Settings::Client::XdpRestoreToken, QString());
m_selectionTransferSignalId = 0; Settings::setValue(Settings::Client::XdpClipboardRetried, true);
free(m_sessionRestoreToken);
m_sessionRestoreToken = nullptr;
if (m_selectionTransferSignalId) {
g_signal_handler_disconnect(session, m_selectionTransferSignalId);
m_selectionTransferSignalId = 0;
}
if (m_selectionOwnerChangedSignalId) {
g_signal_handler_disconnect(session, m_selectionOwnerChangedSignalId);
m_selectionOwnerChangedSignalId = 0;
}
if (m_sessionSignalId) {
g_signal_handler_disconnect(session, m_sessionSignalId);
m_sessionSignalId = 0;
}
g_clear_object(&m_session);
reconnect(0);
return;
} }
if (m_selectionOwnerChangedSignalId) {
g_signal_handler_disconnect(session, m_selectionOwnerChangedSignalId);
m_selectionOwnerChangedSignalId = 0;
}
if (m_sessionSignalId) {
g_signal_handler_disconnect(session, m_sessionSignalId);
m_sessionSignalId = 0;
}
g_clear_object(&m_session);
reconnect(0);
return;
} }
#endif #endif
free(m_sessionRestoreToken);
m_sessionRestoreToken = xdp_session_get_restore_token(session); m_sessionRestoreToken = xdp_session_get_restore_token(session);
if (m_sessionRestoreToken) { if (m_sessionRestoreToken) {
Settings::setValue(Settings::Client::XdpRestoreToken, QString(m_sessionRestoreToken)); Settings::setValue(Settings::Client::XdpRestoreToken, QString(m_sessionRestoreToken));
@ -227,7 +234,7 @@ void PortalRemoteDesktop::claimClipboard() const
return; return;
} }
if (!xdp_session_is_clipboard_enabled(m_session)) { if (!xdp_session_is_clipboard_enabled(m_session)) {
LOG_WARN("portal remote desktop clipboard not enabled on session, cannot claim"); LOG_DEBUG("portal remote desktop clipboard not enabled on session, cannot claim");
return; return;
} }
PortalClipboard::claimOwnership(m_screen->getClipboardCache(), m_session); PortalClipboard::claimOwnership(m_screen->getClipboardCache(), m_session);