Wait for response in PortalAutostart

This commit is contained in:
Ilya Fedin 2021-03-02 00:27:02 +04:00 committed by John Preston
parent d77df9905f
commit 580a12ad7f

View file

@ -7,7 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "platform/linux/specific_linux.h" #include "platform/linux/specific_linux.h"
#include "base/openssl_help.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "base/platform/linux/base_linux_glibmm_helper.h"
#include "base/platform/linux/base_linux_gtk_integration.h" #include "base/platform/linux/base_linux_gtk_integration.h"
#include "ui/platform/ui_platform_utility.h" #include "ui/platform/ui_platform_utility.h"
#include "platform/linux/linux_desktop_environment.h" #include "platform/linux/linux_desktop_environment.h"
@ -47,14 +49,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtDBus/QDBusConnection> #include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMessage> #include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusReply> #include <QtDBus/QDBusReply>
#include <QtDBus/QDBusError>
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
#include <private/qguiapplication_p.h>
#include <glib.h> #include <glib.h>
#include <gio/gio.h> #include <gio/gio.h>
#include <glibmm.h> #include <glibmm.h>
#include <giomm.h> #include <giomm.h>
// must be after undefs
#include "base/platform/linux/base_linux_glibmm_helper.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <cstdlib> #include <cstdlib>
@ -83,54 +88,120 @@ constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs;
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
std::unique_ptr<internal::NotificationServiceWatcher> NSWInstance; std::unique_ptr<internal::NotificationServiceWatcher> NSWInstance;
void PortalAutostart(bool start, bool silent = false) { class PortalAutostart : public QWindow {
public:
PortalAutostart(bool start, bool silent = false);
};
PortalAutostart::PortalAutostart(bool start, bool silent) {
if (cExeName().isEmpty()) { if (cExeName().isEmpty()) {
return; return;
} }
QVariantMap options; try {
options["reason"] = tr::lng_settings_auto_start(tr::now); const auto connection = Gio::DBus::Connection::get_sync(
options["autostart"] = start; Gio::DBus::BusType::BUS_TYPE_SESSION);
options["commandline"] = QStringList{
cExeName(),
qsl("-workdir"),
cWorkingDir(),
qsl("-autostart")
};
options["dbus-activatable"] = false;
auto message = QDBusMessage::createMethodCall( const auto parentWindowId = [&]() -> Glib::ustring {
kXDGDesktopPortalService.utf16(), std::stringstream result;
kXDGDesktopPortalObjectPath.utf16(),
qsl("org.freedesktop.portal.Background"),
qsl("RequestBackground"));
const auto parentWindowId = [&] {
if (const auto activeWindow = Core::App().activeWindow()) { if (const auto activeWindow = Core::App().activeWindow()) {
if (IsX11()) { if (IsX11()) {
return qsl("x11:%1").arg(QString::number( result
activeWindow->widget().get()->windowHandle()->winId(), << "x11:"
16)); << std::hex
<< activeWindow
->widget()
.get()
->windowHandle()
->winId();
} }
} }
return QString(); return result.str();
}(); }();
message.setArguments({ const auto handleToken = Glib::ustring("tdesktop")
parentWindowId, + std::to_string(openssl::RandomValue<uint>());
options
});
if (silent) { std::map<Glib::ustring, Glib::VariantBase> options;
QDBusConnection::sessionBus().send(message); options["handle_token"] = Glib::Variant<Glib::ustring>::create(
return; handleToken);
options["reason"] = Glib::Variant<Glib::ustring>::create(
tr::lng_settings_auto_start(tr::now).toStdString());
options["autostart"] = Glib::Variant<bool>::create(start);
options["commandline"] = Glib::Variant<std::vector<
Glib::ustring
>>::create({
cExeName().toStdString(),
"-workdir",
cWorkingDir().toStdString(),
"-autostart",
});
options["dbus-activatable"] = Glib::Variant<bool>::create(false);
auto uniqueName = connection->get_unique_name();
uniqueName.erase(0, 1);
uniqueName.replace(uniqueName.find('.'), 1, 1, '_');
const auto requestPath = Glib::ustring(
"/org/freedesktop/portal/desktop/request/")
+ uniqueName
+ '/'
+ handleToken;
QEventLoop loop;
const auto signalId = connection->signal_subscribe(
[&](
const Glib::RefPtr<Gio::DBus::Connection> &connection,
const Glib::ustring &sender_name,
const Glib::ustring &object_path,
const Glib::ustring &interface_name,
const Glib::ustring &signal_name,
const Glib::VariantContainerBase &parameters) {
try {
auto parametersCopy = parameters;
const auto response = base::Platform::GlibVariantCast<
uint>(parametersCopy.get_child(0));
if (response && !silent) {
LOG(("Portal Autostart Error: Request denied"));
}
} catch (const std::exception &e) {
if (!silent) {
LOG(("Portal Autostart Error: %1").arg(
QString::fromStdString(e.what())));
}
} }
const QDBusError error = QDBusConnection::sessionBus().call(message); loop.quit();
if (error.isValid()) { },
LOG(("Flatpak Autostart Error: %1: %2") std::string(kXDGDesktopPortalService),
.arg(error.name()) "org.freedesktop.portal.Request",
.arg(error.message())); "Response",
requestPath);
connection->call_sync(
std::string(kXDGDesktopPortalObjectPath),
"org.freedesktop.portal.Background",
"RequestBackground",
base::Platform::MakeGlibVariant(std::tuple{
parentWindowId,
options,
}),
std::string(kXDGDesktopPortalService));
if (signalId != 0) {
QGuiApplicationPrivate::showModalWindow(this);
loop.exec();
QGuiApplicationPrivate::hideModalWindow(this);
connection->signal_unsubscribe(signalId);
}
} catch (const Glib::Error &e) {
if (!silent) {
LOG(("Portal Autostart Error: %1").arg(
QString::fromStdString(e.what())));
}
} }
} }