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();
69#if QT_CONFIG(settings)
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) {
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;
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,
357 XDGDesktopColor
color{};
364 const QString m_parentWindowId;
377 "org.freedesktop.portal.Desktop"_L1,
"/org/freedesktop/portal/desktop"_L1,
378 "org.freedesktop.DBus.Properties"_L1,
"Get"_L1);
379 message <<
"org.freedesktop.portal.Screenshot"_L1
388 if (!
reply.isError() &&
reply.value().toUInt() >= 2)
389 m_hasScreenshotPortalWithColorPicking =
true;
419void runWithXdgActivationToken(F &&functionToCall)
427 auto waylandApp =
dynamic_cast<QNativeInterface::QWaylandApplication *
>(
428 qGuiApp->platformNativeInterface());
430 dynamic_cast<QNativeInterface::Private::QWaylandWindow *
>(
window->handle());
432 if (!waylandWindow || !waylandApp) {
436 waylandWindow->requestXdgActivationToken(waylandApp->lastInputSerial());
438 &QNativeInterface::Private::QWaylandWindow::xdgActivationTokenCreated,
444 auto openUrlInternal = [
this](
const QUrl &
url,
const QString &xdgActivationToken) {
452 if (!
error.isValid())
467 if (!
error.isValid())
477 return launch(m_webBrowser,
url, xdgActivationToken);
481 runWithXdgActivationToken(
493 auto openDocumentInternal = [
this](
const QUrl &
url,
const QString &xdgActivationToken) {
501 if (!
error.isValid())
506 if (m_documentLauncher.
isEmpty()
511 return launch(m_documentLauncher,
url, xdgActivationToken);
515 runWithXdgActivationToken([openDocumentInternal,
url](
const QString &
token) {
536 qWarning(
"openUrl() not supported on this platform");
543 qWarning(
"openDocument() not supported on this platform");
563 switch (capability) {
565 return m_hasScreenshotPortalWithColorPicking;
573 if (
qGuiApp->desktopFileName().isEmpty()) {
574 qWarning(
"QGuiApplication::desktopFileName() is empty");
593 signal.setArguments({launcherUrl, dbusUnityProperties});
603#include "qgenericunixservices.moc"
QByteArray toUpper() const &
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
qsizetype lastIndexOf(char c, qsizetype from=-1) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray mid(qsizetype index, qsizetype len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos.
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().
bool send(const QDBusMessage &message) const
Sends the message over this connection, without waiting for a reply.
QDBusMessage call(const QDBusMessage &message, QDBus::CallMode mode=QDBus::Block, int timeout=-1) const
Sends the message over this connection and blocks, waiting for a reply, for at most timeout milliseco...
bool connect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
Connects the signal specified by the service, path, interface and name parameters to the slot slot in...
static QDBusConnection sessionBus()
Returns a QDBusConnection object opened with the session bus.
QDBusPendingCall asyncCall(const QDBusMessage &message, int timeout=-1) const
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 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
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...
void clear()
Clears the contents of the string and makes it null.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
QString & append(QChar c)
QByteArray toUtf8() const &
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
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]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent