Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qpipewire_portal.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtGui/private/qdesktopunixservices_p.h>
7#include <QtGui/private/qguiapplication_p.h>
8#include <QtGui/qguiapplication.h>
9#include <QtGui/qpa/qplatformintegration.h>
10#include <QtCore/qloggingcategory.h>
11#include <QtCore/quuid.h>
12#include <QtDBus/qdbusconnection.h>
13#include <QtDBus/qdbusinterface.h>
14#include <QtDBus/qdbusmessage.h>
15
16#include <atomic>
17
18QT_BEGIN_NAMESPACE
19
20namespace QtPipeWire {
21
22using namespace Qt::StringLiterals;
23
24Q_STATIC_LOGGING_CATEGORY(lcPipewirePortal, "qt.multimedia.pipewire.portal")
25
26std::optional<unsigned int> portalInterfaceVersion(QLatin1StringView interface)
27{
28 QDBusInterface properties(u"org.freedesktop.portal.Desktop"_s,
29 u"/org/freedesktop/portal/desktop"_s,
30 u"org.freedesktop.DBus.Properties"_s, QDBusConnection::sessionBus());
31
32 QDBusMessage reply = properties.call(u"Get"_s, QString{ interface }, u"version"_s);
33
34 if (reply.type() != QDBusMessage::ReplyMessage || reply.arguments().size() != 1) {
35 qCDebug(lcPipewirePortal) << interface << "not available:" << reply.errorName()
36 << reply.errorMessage();
37 return std::nullopt;
38 }
39
40 // The property is a variant, which arrives wrapped in a QDBusVariant.
41 const uint version = reply.arguments().at(0).toUInt();
42 qCDebug(lcPipewirePortal) << interface << "version" << version;
43 return version;
44}
45
47{
48 static const QString prefix =
49 u"qtmm%1_"_s.arg(QUuid::createUuid().toString(QUuid::WithoutBraces).left(8));
50 static std::atomic_int counter;
51
52 return prefix + QString::number(counter.fetch_add(1, std::memory_order_relaxed));
53}
54
55QString portalRequestPath(const QString &uniqueName, const QString &token)
56{
57 // The portal derives the path from the caller's unique name with the
58 // leading ':' dropped and every '.' turned into '_'.
59 QString sender = uniqueName;
60 if (sender.startsWith(u':'))
61 sender.remove(0, 1);
62 sender.replace(u'.', u'_');
63
64 return u"/org/freedesktop/portal/desktop/request/%1/%2"_s.arg(sender, token);
65}
66
67QString portalRequestPath(const QDBusConnection &connection, const QString &token)
68{
69 return portalRequestPath(connection.baseService(), token);
70}
71
73{
74 auto *unixServices = dynamic_cast<QDesktopUnixServices *>(
75 QGuiApplicationPrivate::platformIntegration()->services());
76 QWindow *focusWindow = QGuiApplication::focusWindow();
77 if (!unixServices || !focusWindow)
78 return {};
79
80 return unixServices->portalWindowIdentifier(focusWindow);
81}
82
83} // namespace QtPipeWire
84
85QT_END_NAMESPACE
QString portalRequestPath(const QString &uniqueName, const QString &token)
Q_STATIC_LOGGING_CATEGORY(lcPipewireAudioSink, "qt.multimedia.pipewire.audiosink")
QString allocatePortalRequestToken()
std::optional< unsigned int > portalInterfaceVersion(QLatin1StringView interface)
QString portalRequestPath(const QDBusConnection &connection, const QString &token)
QString portalParentWindowIdentifier()