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>
This commit is contained in:
parent
f3cd571687
commit
c142fd8f68
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "qgenericunixservices_p.h"
|
#include "qgenericunixservices_p.h"
|
||||||
#include <QtGui/private/qtguiglobal_p.h>
|
#include <QtGui/private/qtguiglobal_p.h>
|
||||||
|
#include "qguiapplication.h"
|
||||||
|
#include "qwindow.h"
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QFile>
|
#include <QtCore/QFile>
|
||||||
@ -152,7 +154,7 @@ static inline bool checkNeedPortalSupport()
|
|||||||
return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, "flatpak-info"_L1).isEmpty() || qEnvironmentVariableIsSet("SNAP");
|
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:
|
// DBus signature:
|
||||||
// OpenFile (IN s parent_window,
|
// OpenFile (IN s parent_window,
|
||||||
@ -176,19 +178,19 @@ static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url)
|
|||||||
|
|
||||||
const QVariantMap options = {{"writable"_L1, true}};
|
const QVariantMap options = {{"writable"_L1, true}};
|
||||||
|
|
||||||
// FIXME parent_window_id
|
message << parentWindow << QVariant::fromValue(descriptor) << options;
|
||||||
message << QString() << QVariant::fromValue(descriptor) << options;
|
|
||||||
|
|
||||||
return QDBusConnection::sessionBus().call(message);
|
return QDBusConnection::sessionBus().call(message);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(url);
|
Q_UNUSED(url);
|
||||||
|
Q_UNUSED(parentWindow)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return QDBusMessage::createError(QDBusError::InternalError, qt_error_string());
|
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:
|
// DBus signature:
|
||||||
// OpenURI (IN s parent_window,
|
// OpenURI (IN s parent_window,
|
||||||
@ -206,12 +208,12 @@ static inline QDBusMessage xdgDesktopPortalOpenUrl(const QUrl &url)
|
|||||||
"org.freedesktop.portal.OpenURI"_L1,
|
"org.freedesktop.portal.OpenURI"_L1,
|
||||||
"OpenURI"_L1);
|
"OpenURI"_L1);
|
||||||
// FIXME parent_window_id and handle writable option
|
// FIXME parent_window_id and handle writable option
|
||||||
message << QString() << url.toString() << QVariantMap();
|
message << parentWindow << url.toString() << QVariantMap();
|
||||||
|
|
||||||
return QDBusConnection::sessionBus().call(message);
|
return QDBusConnection::sessionBus().call(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url)
|
static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url, const QString &parentWindow)
|
||||||
{
|
{
|
||||||
// DBus signature:
|
// DBus signature:
|
||||||
// ComposeEmail (IN s parent_window,
|
// ComposeEmail (IN s parent_window,
|
||||||
@ -251,8 +253,7 @@ static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url)
|
|||||||
"org.freedesktop.portal.Email"_L1,
|
"org.freedesktop.portal.Email"_L1,
|
||||||
"ComposeEmail"_L1);
|
"ComposeEmail"_L1);
|
||||||
|
|
||||||
// FIXME parent_window_id
|
message << parentWindow << options;
|
||||||
message << QString() << options;
|
|
||||||
|
|
||||||
return QDBusConnection::sessionBus().call(message);
|
return QDBusConnection::sessionBus().call(message);
|
||||||
}
|
}
|
||||||
@ -269,7 +270,10 @@ bool QGenericUnixServices::openUrl(const QUrl &url)
|
|||||||
if (url.scheme() == "mailto"_L1) {
|
if (url.scheme() == "mailto"_L1) {
|
||||||
#if QT_CONFIG(dbus)
|
#if QT_CONFIG(dbus)
|
||||||
if (checkNeedPortalSupport()) {
|
if (checkNeedPortalSupport()) {
|
||||||
QDBusError error = xdgDesktopPortalSendEmail(url);
|
const QString parentWindow = QGuiApplication::focusWindow()
|
||||||
|
? portalWindowIdentifier(QGuiApplication::focusWindow())
|
||||||
|
: QString();
|
||||||
|
QDBusError error = xdgDesktopPortalSendEmail(url, parentWindow);
|
||||||
if (!error.isValid())
|
if (!error.isValid())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -281,7 +285,10 @@ bool QGenericUnixServices::openUrl(const QUrl &url)
|
|||||||
|
|
||||||
#if QT_CONFIG(dbus)
|
#if QT_CONFIG(dbus)
|
||||||
if (checkNeedPortalSupport()) {
|
if (checkNeedPortalSupport()) {
|
||||||
QDBusError error = xdgDesktopPortalOpenUrl(url);
|
const QString parentWindow = QGuiApplication::focusWindow()
|
||||||
|
? portalWindowIdentifier(QGuiApplication::focusWindow())
|
||||||
|
: QString();
|
||||||
|
QDBusError error = xdgDesktopPortalOpenUrl(url, parentWindow);
|
||||||
if (!error.isValid())
|
if (!error.isValid())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -298,7 +305,10 @@ bool QGenericUnixServices::openDocument(const QUrl &url)
|
|||||||
{
|
{
|
||||||
#if QT_CONFIG(dbus)
|
#if QT_CONFIG(dbus)
|
||||||
if (checkNeedPortalSupport()) {
|
if (checkNeedPortalSupport()) {
|
||||||
QDBusError error = xdgDesktopPortalOpenFile(url);
|
const QString parentWindow = QGuiApplication::focusWindow()
|
||||||
|
? portalWindowIdentifier(QGuiApplication::focusWindow())
|
||||||
|
: QString();
|
||||||
|
QDBusError error = xdgDesktopPortalOpenFile(url, parentWindow);
|
||||||
if (!error.isValid())
|
if (!error.isValid())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -333,4 +343,12 @@ bool QGenericUnixServices::openDocument(const QUrl &url)
|
|||||||
|
|
||||||
#endif // QT_NO_MULTIPROCESS
|
#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
|
QT_END_NAMESPACE
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QWindow;
|
||||||
|
|
||||||
class Q_GUI_EXPORT QGenericUnixServices : public QPlatformServices
|
class Q_GUI_EXPORT QGenericUnixServices : public QPlatformServices
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -31,6 +33,8 @@ public:
|
|||||||
bool openUrl(const QUrl &url) override;
|
bool openUrl(const QUrl &url) override;
|
||||||
bool openDocument(const QUrl &url) override;
|
bool openDocument(const QUrl &url) override;
|
||||||
|
|
||||||
|
virtual QString portalWindowIdentifier(QWindow *window);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_webBrowser;
|
QString m_webBrowser;
|
||||||
QString m_documentLauncher;
|
QString m_documentLauncher;
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
#include "qxdgdesktopportalfiledialog_p.h"
|
#include "qxdgdesktopportalfiledialog_p.h"
|
||||||
|
|
||||||
|
#include <private/qgenericunixservices_p.h>
|
||||||
|
#include <private/qguiapplication_p.h>
|
||||||
|
#include <qpa/qplatformintegration.h>
|
||||||
|
|
||||||
#include <QDBusConnection>
|
#include <QDBusConnection>
|
||||||
#include <QDBusMessage>
|
#include <QDBusMessage>
|
||||||
#include <QDBusPendingCall>
|
#include <QDBusPendingCall>
|
||||||
@ -157,8 +161,6 @@ void QXdgDesktopPortalFileDialog::openPortal(Qt::WindowFlags windowFlags, Qt::Wi
|
|||||||
"/org/freedesktop/portal/desktop"_L1,
|
"/org/freedesktop/portal/desktop"_L1,
|
||||||
"org.freedesktop.portal.FileChooser"_L1,
|
"org.freedesktop.portal.FileChooser"_L1,
|
||||||
d->saveFile ? "SaveFile"_L1 : "OpenFile"_L1);
|
d->saveFile ? "SaveFile"_L1 : "OpenFile"_L1);
|
||||||
QString parentWindowId = "x11:"_L1 + QString::number(parent ? parent->winId() : 0, 16);
|
|
||||||
|
|
||||||
QVariantMap options;
|
QVariantMap options;
|
||||||
if (!d->acceptLabel.isEmpty())
|
if (!d->acceptLabel.isEmpty())
|
||||||
options.insert("accept_label"_L1, d->acceptLabel);
|
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)
|
// TODO choices a(ssa(ss)s)
|
||||||
// List of serialized combo boxes to add to the file chooser.
|
// 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);
|
QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
|
||||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
|
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user