diff options
author | David Redondo <qt@david-redondo.de> | 2022-02-23 11:12:17 +0100 |
---|---|---|
committer | David Redondo <qt@david-redondo.de> | 2022-07-25 18:29:49 +0200 |
commit | c142fd8f686aa86e333cb3f30a4d3802155ecae5 (patch) | |
tree | d84076fae08e3f5939995f49db259ffa27e53555 | |
parent | f3cd57168731c67afd12d8071ead96eed1177b25 (diff) |
Send parent_window handle to desktop portal
Sending parent_window to the portal allows it/the window manager to
better place portal dialogs in respect to the application window, for example
on top of it instead of a random position. For this use the focusWindow()
(if available) since the API in QDesktopServices does not take a QWindow
parameter. The file dialog has an explicit parent that can be used.
The introduced virtual is provided as a hook for the wayland platform
that already includes a class that inherits from QGenericUnixServices.
Change-Id: I5571f08d07e5a4e3ae32efd1f09e2727cec9e7c5
Reviewed-by: David Edmundson <davidedmundson@kde.org>
3 files changed, 45 insertions, 14 deletions
diff --git a/src/gui/platform/unix/qgenericunixservices.cpp b/src/gui/platform/unix/qgenericunixservices.cpp index a0e5466c58..54a0406cab 100644 --- a/src/gui/platform/unix/qgenericunixservices.cpp +++ b/src/gui/platform/unix/qgenericunixservices.cpp @@ -3,6 +3,8 @@ #include "qgenericunixservices_p.h" #include <QtGui/private/qtguiglobal_p.h> +#include "qguiapplication.h" +#include "qwindow.h" #include <QtCore/QDebug> #include <QtCore/QFile> @@ -152,7 +154,7 @@ static inline bool checkNeedPortalSupport() return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, "flatpak-info"_L1).isEmpty() || qEnvironmentVariableIsSet("SNAP"); } -static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url) +static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url, const QString &parentWindow) { // DBus signature: // OpenFile (IN s parent_window, @@ -176,19 +178,19 @@ static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url) const QVariantMap options = {{"writable"_L1, true}}; - // FIXME parent_window_id - message << QString() << QVariant::fromValue(descriptor) << options; + message << parentWindow << QVariant::fromValue(descriptor) << options; return QDBusConnection::sessionBus().call(message); } #else Q_UNUSED(url); + Q_UNUSED(parentWindow) #endif return QDBusMessage::createError(QDBusError::InternalError, qt_error_string()); } -static inline QDBusMessage xdgDesktopPortalOpenUrl(const QUrl &url) +static inline QDBusMessage xdgDesktopPortalOpenUrl(const QUrl &url, const QString &parentWindow) { // DBus signature: // OpenURI (IN s parent_window, @@ -206,12 +208,12 @@ static inline QDBusMessage xdgDesktopPortalOpenUrl(const QUrl &url) "org.freedesktop.portal.OpenURI"_L1, "OpenURI"_L1); // FIXME parent_window_id and handle writable option - message << QString() << url.toString() << QVariantMap(); + message << parentWindow << url.toString() << QVariantMap(); return QDBusConnection::sessionBus().call(message); } -static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url) +static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url, const QString &parentWindow) { // DBus signature: // ComposeEmail (IN s parent_window, @@ -251,8 +253,7 @@ static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url) "org.freedesktop.portal.Email"_L1, "ComposeEmail"_L1); - // FIXME parent_window_id - message << QString() << options; + message << parentWindow << options; return QDBusConnection::sessionBus().call(message); } @@ -269,7 +270,10 @@ bool QGenericUnixServices::openUrl(const QUrl &url) if (url.scheme() == "mailto"_L1) { #if QT_CONFIG(dbus) if (checkNeedPortalSupport()) { - QDBusError error = xdgDesktopPortalSendEmail(url); + const QString parentWindow = QGuiApplication::focusWindow() + ? portalWindowIdentifier(QGuiApplication::focusWindow()) + : QString(); + QDBusError error = xdgDesktopPortalSendEmail(url, parentWindow); if (!error.isValid()) return true; @@ -281,7 +285,10 @@ bool QGenericUnixServices::openUrl(const QUrl &url) #if QT_CONFIG(dbus) if (checkNeedPortalSupport()) { - QDBusError error = xdgDesktopPortalOpenUrl(url); + const QString parentWindow = QGuiApplication::focusWindow() + ? portalWindowIdentifier(QGuiApplication::focusWindow()) + : QString(); + QDBusError error = xdgDesktopPortalOpenUrl(url, parentWindow); if (!error.isValid()) return true; } @@ -298,7 +305,10 @@ bool QGenericUnixServices::openDocument(const QUrl &url) { #if QT_CONFIG(dbus) if (checkNeedPortalSupport()) { - QDBusError error = xdgDesktopPortalOpenFile(url); + const QString parentWindow = QGuiApplication::focusWindow() + ? portalWindowIdentifier(QGuiApplication::focusWindow()) + : QString(); + QDBusError error = xdgDesktopPortalOpenFile(url, parentWindow); if (!error.isValid()) return true; } @@ -333,4 +343,12 @@ bool QGenericUnixServices::openDocument(const QUrl &url) #endif // QT_NO_MULTIPROCESS +QString QGenericUnixServices::portalWindowIdentifier(QWindow *window) +{ + if (QGuiApplication::platformName() == QLatin1String("xcb")) + return "x11:"_L1 + QString::number(window->winId(), 16); + + return QString(); +} + QT_END_NAMESPACE diff --git a/src/gui/platform/unix/qgenericunixservices_p.h b/src/gui/platform/unix/qgenericunixservices_p.h index 8d1228375f..2ddba91a3a 100644 --- a/src/gui/platform/unix/qgenericunixservices_p.h +++ b/src/gui/platform/unix/qgenericunixservices_p.h @@ -21,6 +21,8 @@ QT_BEGIN_NAMESPACE +class QWindow; + class Q_GUI_EXPORT QGenericUnixServices : public QPlatformServices { public: @@ -31,6 +33,8 @@ public: bool openUrl(const QUrl &url) override; bool openDocument(const QUrl &url) override; + virtual QString portalWindowIdentifier(QWindow *window); + private: QString m_webBrowser; QString m_documentLauncher; diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp index ecc5545e76..2ef591a591 100644 --- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp +++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp @@ -3,6 +3,10 @@ #include "qxdgdesktopportalfiledialog_p.h" +#include <private/qgenericunixservices_p.h> +#include <private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> + #include <QDBusConnection> #include <QDBusMessage> #include <QDBusPendingCall> @@ -157,8 +161,6 @@ void QXdgDesktopPortalFileDialog::openPortal(Qt::WindowFlags windowFlags, Qt::Wi "/org/freedesktop/portal/desktop"_L1, "org.freedesktop.portal.FileChooser"_L1, d->saveFile ? "SaveFile"_L1 : "OpenFile"_L1); - QString parentWindowId = "x11:"_L1 + QString::number(parent ? parent->winId() : 0, 16); - QVariantMap options; if (!d->acceptLabel.isEmpty()) options.insert("accept_label"_L1, d->acceptLabel); @@ -262,7 +264,14 @@ void QXdgDesktopPortalFileDialog::openPortal(Qt::WindowFlags windowFlags, Qt::Wi // TODO choices a(ssa(ss)s) // List of serialized combo boxes to add to the file chooser. - message << parentWindowId << d->title << options; + auto unixServices = dynamic_cast<QGenericUnixServices *>( + QGuiApplicationPrivate::platformIntegration()->services()); + if (parent && unixServices) + message << unixServices->portalWindowIdentifier(parent); + else + message << QString(); + + message << d->title << options; QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall); |