From 9e4c03f4c9af4a64e82ce257508b512b82abbba2 Mon Sep 17 00:00:00 2001 From: David Redondo Date: Tue, 28 Jan 2025 16:53:16 +0100 Subject: QDesktopUnixServices: Register with host app registry This is useful when accessing portal APIs when not sandboxed as it allows the portal to display info which app is making the request. For example the dialog that will be shown when QScreenCapture goes through the portal can show the app name. We need to do this as it can only be set before making any call to the portal at all which are done here for color picking or by the relevant platformthemes for settings. See the paragraph at the top of https://flatpak.github.io/xdg-desktop-portal/docs/api-reference.html and https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.host.portal.Registry.html Fixes: QTBUG-133401 Pick-to: 6.10 Change-Id: Ie55c371c6a19b3197f7798ee6233c2f19b18a6f6 Reviewed-by: David Edmundson --- src/gui/platform/unix/qdesktopunixservices.cpp | 56 +++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'src/gui/platform/unix/qdesktopunixservices.cpp') diff --git a/src/gui/platform/unix/qdesktopunixservices.cpp b/src/gui/platform/unix/qdesktopunixservices.cpp index bbc6b41a2bc..d0ee636d484 100644 --- a/src/gui/platform/unix/qdesktopunixservices.cpp +++ b/src/gui/platform/unix/qdesktopunixservices.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -373,6 +374,34 @@ private Q_SLOTS: private: const QString m_parentWindowId; }; + +void registerWithHostPortal() +{ + static bool registered = false; + if (registered) { + return; + } + + auto message = QDBusMessage::createMethodCall( + "org.freedesktop.portal.Desktop"_L1, "/org/freedesktop/portal/desktop"_L1, + "org.freedesktop.host.portal.Registry"_L1, "Register"_L1); + message.setArguments({ QGuiApplication::desktopFileName(), QVariantMap() }); + auto watcher = + new QDBusPendingCallWatcher(QDBusConnection::sessionBus().asyncCall(message), qGuiApp); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, watcher, [watcher] { + watcher->deleteLater(); + if (watcher->isError()) { + // Expected error when running against an older portal + if (watcher->error().type() == QDBusError::UnknownInterface || watcher->error().type() == QDBusError::UnknownMethod) + qCInfo(lcQpaServices) << "Failed to register with host portal" << watcher->error(); + else + qCWarning(lcQpaServices) << "Failed to register with host portal" << watcher->error(); + } else { + qCDebug(lcQpaServices) << "Successfully registered with host portal as" << QGuiApplication::desktopFileName(); + registered = true; + } + }); +} } // namespace #endif // QT_CONFIG(dbus) @@ -395,7 +424,7 @@ QDesktopUnixServices::QDesktopUnixServices() QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message); auto watcher = new QDBusPendingCallWatcher(pendingCall); m_watcher = watcher; - QObject::connect(watcher, &QDBusPendingCallWatcher::finished, watcher, + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, watcher, [this](QDBusPendingCallWatcher *watcher) { watcher->deleteLater(); QDBusPendingReply reply = *watcher; @@ -403,6 +432,31 @@ QDesktopUnixServices::QDesktopUnixServices() m_hasScreenshotPortalWithColorPicking = true; }); + if (checkNeedPortalSupport()) { + return; + } + + // The program might only set the desktopfilename after creating the app + // try again when it's running + if (!QGuiApplication::desktopFileName().isEmpty()) { + registerWithHostPortal(); + } else { + QMetaObject::invokeMethod( + qGuiApp, + [] { + if (QGuiApplication::desktopFileName().isEmpty()) { + qCInfo(lcQpaServices) << "QGuiApplication::desktopFileName not set. Unable to register application with portal registry"; + return; + } + registerWithHostPortal(); + }, + Qt::QueuedConnection); + } + m_portalWatcher = std::make_unique( + "org.freedesktop.portal.Desktop"_L1, QDBusConnection::sessionBus(), + QDBusServiceWatcher::WatchForRegistration); + QObject::connect(m_portalWatcher.get(), &QDBusServiceWatcher::serviceRegistered, + m_portalWatcher.get(), ®isterWithHostPortal); #endif } -- cgit v1.2.3