5#include <QtGui/private/qtguiglobal_p.h>
8#include <QtGui/qpa/qplatformwindow_p.h>
9#include <QtGui/qpa/qplatformwindow.h>
10#include <QtGui/qpa/qplatformnativeinterface.h>
12#include <QtCore/QDebug>
13#include <QtCore/QFile>
15# include <QtCore/QProcess>
17#if QT_CONFIG(settings)
18#include <QtCore/QSettings>
20#include <QtCore/QStandardPaths>
25#include <QtCore/private/qcore_unix_p.h>
27#include <QtCore/QFileInfo>
28#include <QtCore/QUrlQuery>
30#include <QtDBus/QDBusConnection>
31#include <QtDBus/QDBusMessage>
32#include <QtDBus/QDBusPendingCall>
33#include <QtDBus/QDBusPendingCallWatcher>
34#include <QtDBus/QDBusPendingReply>
35#include <QtDBus/QDBusUnixFileDescriptor>
47#if QT_CONFIG(multiprocess)
51static inline QByteArray detectDesktopEnvironment()
54 if (!xdgCurrentDesktop.isEmpty())
55 return xdgCurrentDesktop.toUpper();
67 int slash = desktopSession.lastIndexOf(
'/');
69#if QT_CONFIG(settings)
73 if (!desktopName.isEmpty())
78 desktopSession = desktopSession.
mid(slash + 1);
81 if (desktopSession ==
"gnome")
83 else if (desktopSession ==
"xfce")
85 else if (desktopSession ==
"kde")
97static inline bool detectWebBrowser(
const QByteArray &desktop,
98 bool checkBrowserVariable,
101 const char *browsers[] = {
"google-chrome",
"firefox",
"mozilla",
"opera"};
107 if (checkBrowserVariable) {
109 if (browserVariable.isEmpty())
110 browserVariable =
qgetenv(
"BROWSER");
120 browser->append(
" exec"_L1);
128 for (
size_t i = 0;
i <
sizeof(browsers)/
sizeof(
char *); ++
i)
134static inline bool launch(
const QString &launcher,
const QUrl &
url,
135 const QString &xdgActivationToken)
137 if (!xdgActivationToken.isEmpty()) {
138 qputenv(
"XDG_ACTIVATION_TOKEN", xdgActivationToken.toUtf8());
144#if !QT_CONFIG(process)
145 const bool ok = ::system(
qPrintable(command +
" &"_L1));
169 const QString &xdgActivationToken)
183 "/org/freedesktop/portal/desktop"_L1,
184 "org.freedesktop.portal.OpenURI"_L1,
192 if (!xdgActivationToken.isEmpty()) {
193 options.
insert(
"activation_token"_L1, xdgActivationToken);
205 const QString &xdgActivationToken)
219 "/org/freedesktop/portal/desktop"_L1,
220 "org.freedesktop.portal.OpenURI"_L1,
225 if (!xdgActivationToken.isEmpty()) {
226 options.
insert(
"activation_token"_L1, xdgActivationToken);
235 const QString &xdgActivationToken)
250 options.
insert(
"subject"_L1, urlQuery.queryItemValue(
"subject"_L1));
251 options.
insert(
"body"_L1, urlQuery.queryItemValue(
"body"_L1));
256 const QStringList attachmentUris = urlQuery.allQueryItemValues(
"attachment"_L1);
258 for (
const QString &attachmentUri : attachmentUris) {
270 if (!xdgActivationToken.isEmpty()) {
271 options.
insert(
"activation_token"_L1, xdgActivationToken);
275 "/org/freedesktop/portal/desktop"_L1,
276 "org.freedesktop.portal.Email"_L1,
279 message << parentWindow << options;
285struct XDGDesktopColor
293 constexpr auto rgbMax = 255;
294 return {
static_cast<int>(
r * rgbMax),
static_cast<int>(
g * rgbMax),
295 static_cast<int>(
b * rgbMax) };
302 argument >> myStruct.r >> myStruct.g >> myStruct.b;
311 XdgDesktopPortalColorPicker(
const QString &parentWindowId,
QWindow *parent)
316 void pickColor()
override
326 "org.freedesktop.portal.Desktop"_L1,
"/org/freedesktop/portal/desktop"_L1,
327 "org.freedesktop.portal.Screenshot"_L1,
"PickColor"_L1);
336 if (
reply.isError()) {
337 qWarning(
"DBus call to pick color failed: %s",
338 qPrintable(reply.error().message()));
339 Q_EMIT colorPicked({});
342 "org.freedesktop.portal.Desktop"_L1,
reply.value().path(),
343 "org.freedesktop.portal.Request"_L1,
"Response"_L1,
this,
358 XDGDesktopColor
color{};
368 const QString m_parentWindowId;
381 "org.freedesktop.portal.Desktop"_L1,
"/org/freedesktop/portal/desktop"_L1,
382 "org.freedesktop.DBus.Properties"_L1,
"Get"_L1);
383 message <<
"org.freedesktop.portal.Screenshot"_L1
392 if (!
reply.isError() &&
reply.value().toUInt() >= 2)
393 m_hasScreenshotPortalWithColorPicking =
true;
423void runWithXdgActivationToken(F &&functionToCall)
425#if QT_CONFIG(wayland)
433 auto waylandApp =
dynamic_cast<QNativeInterface::QWaylandApplication *
>(
434 qGuiApp->platformNativeInterface());
436 dynamic_cast<QNativeInterface::Private::QWaylandWindow *
>(
window->handle());
438 if (!waylandWindow || !waylandApp) {
444 &QNativeInterface::Private::QWaylandWindow::xdgActivationTokenCreated,
446 waylandWindow->requestXdgActivationToken(waylandApp->lastInputSerial());
454 auto openUrlInternal = [
this](
const QUrl &
url,
const QString &xdgActivationToken) {
462 if (!
error.isValid())
477 if (!
error.isValid())
487 return launch(m_webBrowser,
url, xdgActivationToken);
491 runWithXdgActivationToken(
503 auto openDocumentInternal = [
this](
const QUrl &
url,
const QString &xdgActivationToken) {
511 if (!
error.isValid())
516 if (m_documentLauncher.
isEmpty()
521 return launch(m_documentLauncher,
url, xdgActivationToken);
525 runWithXdgActivationToken([openDocumentInternal,
url](
const QString &
token) {
546 qWarning(
"openUrl() not supported on this platform");
553 qWarning(
"openDocument() not supported on this platform");
573 switch (capability) {
575 return m_hasScreenshotPortalWithColorPicking;
583 if (
qGuiApp->desktopFileName().isEmpty()) {
584 qWarning(
"QGuiApplication::desktopFileName() is empty");
603 signal.setArguments({launcherUrl, dbusUnityProperties});
613#include "qgenericunixservices.moc"
QByteArray mid(qsizetype index, qsizetype len=-1) const &
The QColor class provides colors based on RGB, HSV or CMYK values.
void beginStructure()
Opens a new D-Bus structure suitable for appending new arguments.
void endStructure()
Closes a D-Bus structure opened with beginStructure().
static QDBusConnection sessionBus()
Returns a QDBusConnection object opened with the session bus.
static QDBusMessage createSignal(const QString &path, const QString &interface, const QString &name)
Constructs a new DBus message with the given path, interface and name, representing a signal emission...
static QDBusMessage createError(const QString &name, const QString &msg)
Constructs a new DBus message representing an error, with the given name and msg.
static QDBusMessage createMethodCall(const QString &destination, const QString &path, const QString &interface, const QString &method)
Constructs a new DBus message representing a method call.
void finished(QDBusPendingCallWatcher *self=nullptr)
This signal is emitted when the pending call has finished and its reply is available.
void giveFileDescriptor(int fileDescriptor)
bool exists() const
Returns true if the file system entry this QFileInfo refers to exists; otherwise returns false.
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
bool openDocument(const QUrl &url) override
bool hasCapability(Capability capability) const override
virtual QString portalWindowIdentifier(QWindow *window)
void setApplicationBadge(qint64 number)
QPlatformServiceColorPicker * colorPicker(QWindow *parent=nullptr) override
bool openUrl(const QUrl &url) override
QByteArray desktopEnvironment() const override
QPlatformServices::desktopEnvironment returns the active desktop environment.
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
QString platformName
The name of the underlying platform plugin.
bool isEmpty() const noexcept
iterator insert(const Key &key, const T &value)
T value(const Key &key, const T &defaultValue=T()) const
bool contains(const Key &key) const
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static QString findExecutable(const QString &executableName, const QStringList &paths=QStringList())
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
QByteArray toEncoded(FormattingOptions options=FullyEncoded) const
Returns the encoded representation of the URL if it's valid; otherwise an empty QByteArray is returne...
QString scheme() const
Returns the scheme of the URL.
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
QMap< QString, QString > map
[6]
Combined button and popup list for selecting options.
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QByteArrayView haystack, QByteArrayView needle) noexcept
#define QByteArrayLiteral(str)
QMap< QString, QVariant > QVariantMap
static int qt_safe_open(const char *pathname, int flags, mode_t mode=0777)
static int qt_safe_close(int fd)
DBusConnection const char DBusError * error
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
static bool checkNeedPortalSupport()
Q_DECL_COLD_FUNCTION Q_CORE_EXPORT QString qt_error_string(int errorCode=-1)
constexpr const T & qBound(const T &min, const T &val, const T &max)
GLboolean GLboolean GLboolean b
GLenum GLenum GLsizei count
GLsizei const GLenum * attachments
GLuint GLsizei const GLchar * message
static QString checkExecutable(const QString &path)
#define qPrintable(string)
#define QStringLiteral(str)
bool qputenv(const char *varName, QByteArrayView raw)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
Q_CORE_EXPORT bool qunsetenv(const char *varName)
QFutureWatcher< int > watcher
QUrl url("example.com")
[constructor-url-reference]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)