diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 663453b109..85f82779c6 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -840,6 +840,8 @@ PRIVATE platform/linux/linux_open_with_dialog.h platform/linux/linux_wayland_integration.cpp platform/linux/linux_wayland_integration.h + platform/linux/linux_xdp_file_dialog.cpp + platform/linux/linux_xdp_file_dialog.h platform/linux/linux_xlib_helper.cpp platform/linux/linux_xlib_helper.h platform/linux/file_utilities_linux.cpp @@ -1132,6 +1134,8 @@ if (LINUX AND DESKTOP_APP_DISABLE_DBUS_INTEGRATION) platform/linux/linux_gsd_media_keys.h platform/linux/linux_notification_service_watcher.cpp platform/linux/linux_notification_service_watcher.h + platform/linux/linux_xdp_file_dialog.cpp + platform/linux/linux_xdp_file_dialog.h platform/linux/notifications_manager_linux.cpp ) diff --git a/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp b/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp index d13b804884..b9ebef8c0d 100644 --- a/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp @@ -10,6 +10,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/linux/linux_gtk_integration.h" #include "platform/linux/specific_linux.h" +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION +#include "platform/linux/linux_xdp_file_dialog.h" +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION + #include extern "C" { @@ -77,6 +81,18 @@ bool Get( if (parent) { parent = parent->window(); } +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION + if (XDP::Use(type)) { + return XDP::Get( + parent, + files, + remoteContent, + caption, + filter, + type, + startFile); + } +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION if (const auto integration = GtkIntegration::Instance()) { if (integration->fileDialogSupported() && integration->useFileDialog(type)) { diff --git a/Telegram/SourceFiles/platform/linux/linux_gtk_file_dialog.cpp b/Telegram/SourceFiles/platform/linux/linux_gtk_file_dialog.cpp index d9adb924dd..f03fcdaeaf 100644 --- a/Telegram/SourceFiles/platform/linux/linux_gtk_file_dialog.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_gtk_file_dialog.cpp @@ -640,24 +640,10 @@ bool Supported() { } bool Use(Type type) { - // use gtk file dialog on gtk-based desktop environments - // or if QT_QPA_PLATFORMTHEME=(gtk2|gtk3) - // or if portals are used and operation is to open folder - // and portal doesn't support folder choosing - const auto sandboxedOrCustomPortal = InFlatpak() - || InSnap() - || UseXDGDesktopPortal(); - - const auto neededForPortal = (type == Type::ReadFolder) - && !CanOpenDirectoryWithPortal(); - - const auto neededNonForced = DesktopEnvironment::IsGtkBased() - || (sandboxedOrCustomPortal && neededForPortal); - - const auto excludeNonForced = sandboxedOrCustomPortal && !neededForPortal; - return IsGtkIntegrationForced() - || (neededNonForced && !excludeNonForced); + || DesktopEnvironment::IsGtkBased() + // use as a fallback for portal dialog + || UseXDGDesktopPortal(); } bool Get( diff --git a/Telegram/SourceFiles/platform/linux/linux_xdp_file_dialog.cpp b/Telegram/SourceFiles/platform/linux/linux_xdp_file_dialog.cpp new file mode 100644 index 0000000000..5d53d1ab21 --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/linux_xdp_file_dialog.cpp @@ -0,0 +1,536 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "platform/linux/linux_xdp_file_dialog.h" + +#include "platform/linux/specific_linux.h" +#include "storage/localstorage.h" +#include "base/qt_adapters.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Platform { +namespace FileDialog { +namespace XDP { +namespace { + +const char *filterRegExp = +"^(.*)\\(([a-zA-Z0-9_.,*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$"; + +QStringList makeFilterList(const QString &filter) { + QString f(filter); + + if (f.isEmpty()) + return QStringList(); + + QString sep(QLatin1String(";;")); + int i = f.indexOf(sep, 0); + if (i == -1) { + if (f.indexOf(QLatin1Char('\n'), 0) != -1) { + sep = QLatin1Char('\n'); + i = f.indexOf(sep, 0); + } + } + + return f.split(sep); +} + +} // namespace + +bool Use(Type type) { + return UseXDGDesktopPortal() + && (type != Type::ReadFolder || CanOpenDirectoryWithPortal()); +} + +bool Get( + QPointer parent, + QStringList &files, + QByteArray &remoteContent, + const QString &caption, + const QString &filter, + Type type, + QString startFile) { + XDPFileDialog dialog(parent, caption, QString(), filter); + + dialog.setModal(true); + if (type == Type::ReadFile || type == Type::ReadFiles) { + dialog.setFileMode((type == Type::ReadFiles) ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile); + dialog.setAcceptMode(QFileDialog::AcceptOpen); + } else if (type == Type::ReadFolder) { + dialog.setAcceptMode(QFileDialog::AcceptOpen); + dialog.setFileMode(QFileDialog::Directory); + dialog.setOption(QFileDialog::ShowDirsOnly); + } else { + dialog.setFileMode(QFileDialog::AnyFile); + dialog.setAcceptMode(QFileDialog::AcceptSave); + } + if (startFile.isEmpty() || startFile.at(0) != '/') { + startFile = cDialogLastPath() + '/' + startFile; + } + dialog.selectFile(startFile); + + int res = dialog.exec(); + + QString path = dialog.directory().path(); + if (path != cDialogLastPath()) { + cSetDialogLastPath(path); + Local::writeSettings(); + } + + if (res == QDialog::Accepted) { + QStringList selectedFilesStrings; + ranges::transform( + dialog.selectedFiles(), + ranges::back_inserter(selectedFilesStrings), + [](const QUrl &url) { return url.path(); }); + + if (type == Type::ReadFiles) { + files = selectedFilesStrings; + } else { + files = selectedFilesStrings.mid(0, 1); + } + return true; + } + + files = QStringList(); + remoteContent = QByteArray(); + return false; +} + +QDBusArgument &operator <<(QDBusArgument &arg, const XDPFileDialog::FilterCondition &filterCondition) { + arg.beginStructure(); + arg << filterCondition.type << filterCondition.pattern; + arg.endStructure(); + return arg; +} + +const QDBusArgument &operator >>(const QDBusArgument &arg, XDPFileDialog::FilterCondition &filterCondition) { + uint type; + QString filterPattern; + arg.beginStructure(); + arg >> type >> filterPattern; + filterCondition.type = (XDPFileDialog::ConditionType)type; + filterCondition.pattern = filterPattern; + arg.endStructure(); + + return arg; +} + +QDBusArgument &operator <<(QDBusArgument &arg, const XDPFileDialog::Filter filter) { + arg.beginStructure(); + arg << filter.name << filter.filterConditions; + arg.endStructure(); + return arg; +} + +const QDBusArgument &operator >>(const QDBusArgument &arg, XDPFileDialog::Filter &filter) { + QString name; + XDPFileDialog::FilterConditionList filterConditions; + arg.beginStructure(); + arg >> name >> filterConditions; + filter.name = name; + filter.filterConditions = filterConditions; + arg.endStructure(); + + return arg; +} + +class XDPFileDialogPrivate { +public: + XDPFileDialogPrivate() { + } + + WId winId = 0; + bool directoryMode = false; + bool modal = false; + bool multipleFiles = false; + bool saveFile = false; + QString acceptLabel; + QString directory; + QString title; + QStringList nameFilters; + QStringList mimeTypesFilters; + // maps user-visible name for portal to full name filter + QMap userVisibleToNameFilter; + QString selectedMimeTypeFilter; + QString selectedNameFilter; + QStringList selectedFiles; +}; + +XDPFileDialog::XDPFileDialog(QWidget *parent, const QString &caption, const QString &directory, const QString &filter) +: QDialog(parent) +, d_ptr(new XDPFileDialogPrivate()) +, _windowTitle(caption) +, _initialDirectory(directory) { + Q_D(XDPFileDialog); + + auto filters = makeFilterList(filter); + const int numFilters = filters.count(); + _nameFilters.reserve(numFilters); + for (int i = 0; i < numFilters; ++i) { + _nameFilters << filters[i].simplified(); + } + + accepted( + ) | rpl::start_with_next([=] { + Q_EMIT accept(); + }, _lifetime); + + rejected( + ) | rpl::start_with_next([=] { + Q_EMIT reject(); + }, _lifetime); +} + +XDPFileDialog::~XDPFileDialog() { +} + +void XDPFileDialog::initializeDialog() { + Q_D(XDPFileDialog); + + if (_fileMode == QFileDialog::ExistingFiles) + d->multipleFiles = true; + + if (_fileMode == QFileDialog::Directory || _options.testFlag(QFileDialog::ShowDirsOnly)) + d->directoryMode = true; + +#if 0 // it is commented in GtkFileDialog for some reason, do the same + if (options()->isLabelExplicitlySet(QFileDialog::Accept)) + d->acceptLabel = options()->labelText(QFileDialog::Accept); +#endif + + if (!_windowTitle.isEmpty()) + d->title = _windowTitle; + + if (_acceptMode == QFileDialog::AcceptSave) + d->saveFile = true; + + if (!_nameFilters.isEmpty()) + d->nameFilters = _nameFilters; + +#if 0 // what is the right way to implement this? + if (!options()->mimeTypeFilters().isEmpty()) + d->mimeTypesFilters = options()->mimeTypeFilters(); + + if (!options()->initiallySelectedMimeTypeFilter().isEmpty()) + d->selectedMimeTypeFilter = options()->initiallySelectedMimeTypeFilter(); +#endif + + const auto initialNameFilter = _nameFilters.isEmpty() ? QString() : _nameFilters.front(); + if (!initialNameFilter.isEmpty()) + d->selectedNameFilter = initialNameFilter; + + setDirectory(_initialDirectory); +} + +void XDPFileDialog::openPortal() { + Q_D(XDPFileDialog); + + QDBusMessage message = QDBusMessage::createMethodCall( + QLatin1String("org.freedesktop.portal.Desktop"), + QLatin1String("/org/freedesktop/portal/desktop"), + QLatin1String("org.freedesktop.portal.FileChooser"), + d->saveFile ? QLatin1String("SaveFile") : QLatin1String("OpenFile")); + QString parentWindowId = QLatin1String("x11:") + QString::number(d->winId, 16); + + QVariantMap options; + if (!d->acceptLabel.isEmpty()) + options.insert(QLatin1String("accept_label"), d->acceptLabel); + + options.insert(QLatin1String("modal"), d->modal); + options.insert(QLatin1String("multiple"), d->multipleFiles); + options.insert(QLatin1String("directory"), d->directoryMode); + + if (d->saveFile) { + if (!d->directory.isEmpty()) + options.insert(QLatin1String("current_folder"), QFile::encodeName(d->directory).append('\0')); + + if (!d->selectedFiles.isEmpty()) + options.insert(QLatin1String("current_file"), QFile::encodeName(d->selectedFiles.first()).append('\0')); + } + + // Insert filters + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + + FilterList filterList; + auto selectedFilterIndex = filterList.size() - 1; + + d->userVisibleToNameFilter.clear(); + + if (!d->mimeTypesFilters.isEmpty()) { + for (const QString &mimeTypefilter : d->mimeTypesFilters) { + QMimeDatabase mimeDatabase; + QMimeType mimeType = mimeDatabase.mimeTypeForName(mimeTypefilter); + + // Creates e.g. (1, "image/png") + FilterCondition filterCondition; + filterCondition.type = MimeType; + filterCondition.pattern = mimeTypefilter; + + // Creates e.g. [((1, "image/png"))] + FilterConditionList filterConditions; + filterConditions << filterCondition; + + // Creates e.g. [("Images", [((1, "image/png"))])] + Filter filter; + filter.name = mimeType.comment(); + filter.filterConditions = filterConditions; + + filterList << filter; + + if (!d->selectedMimeTypeFilter.isEmpty() && d->selectedMimeTypeFilter == mimeTypefilter) + selectedFilterIndex = filterList.size() - 1; + } + } else if (!d->nameFilters.isEmpty()) { + for (const QString &nameFilter : d->nameFilters) { + // Do parsing: + // Supported format is ("Images (*.png *.jpg)") + QRegularExpression regexp(QString::fromLatin1(filterRegExp)); + QRegularExpressionMatch match = regexp.match(nameFilter); + if (match.hasMatch()) { + QString userVisibleName = match.captured(1); + QStringList filterStrings = match.captured(2).split(QLatin1Char(' '), base::QStringSkipEmptyParts); + + if (filterStrings.isEmpty()) { + LOG(("XDP File Dialog Error: Filter %1 is empty and will be ignored.").arg(userVisibleName)); + continue; + } + + FilterConditionList filterConditions; + for (const QString &filterString : filterStrings) { + FilterCondition filterCondition; + filterCondition.type = GlobalPattern; + filterCondition.pattern = filterString; + filterConditions << filterCondition; + } + + Filter filter; + filter.name = userVisibleName; + filter.filterConditions = filterConditions; + + filterList << filter; + + d->userVisibleToNameFilter.insert(userVisibleName, nameFilter); + + if (!d->selectedNameFilter.isEmpty() && d->selectedNameFilter == nameFilter) + selectedFilterIndex = filterList.size() - 1; + } + } + } + + if (!filterList.isEmpty()) + options.insert(QLatin1String("filters"), QVariant::fromValue(filterList)); + + if (selectedFilterIndex != -1) + options.insert(QLatin1String("current_filter"), QVariant::fromValue(filterList[selectedFilterIndex])); + + options.insert(QLatin1String("handle_token"), QStringLiteral("qt%1").arg(QRandomGenerator::global()->generate())); + + // TODO choices a(ssa(ss)s) + // List of serialized combo boxes to add to the file chooser. + + message << parentWindowId << d->title << options; + + QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall); + connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *watcher) { + QDBusPendingReply reply = *watcher; + if (reply.isError()) { + _reject.fire({}); + } else { + QDBusConnection::sessionBus().connect( + nullptr, + reply.value().path(), + QLatin1String("org.freedesktop.portal.Request"), + QLatin1String("Response"), + this, + SLOT(gotResponse(uint,QVariantMap))); + } + }); +} + +bool XDPFileDialog::defaultNameFilterDisables() const { + return false; +} + +void XDPFileDialog::setDirectory(const QUrl &directory) { + Q_D(XDPFileDialog); + + d->directory = directory.path(); +} + +QUrl XDPFileDialog::directory() const { + Q_D(const XDPFileDialog); + + return d->directory; +} + +void XDPFileDialog::selectFile(const QUrl &filename) { + Q_D(XDPFileDialog); + + d->selectedFiles << filename.path(); +} + +QList XDPFileDialog::selectedFiles() const { + Q_D(const XDPFileDialog); + + QList files; + for (const QString &file : d->selectedFiles) { + files << QUrl(file); + } + return files; +} + +void XDPFileDialog::setFilter() { + Q_D(XDPFileDialog); +} + +void XDPFileDialog::selectMimeTypeFilter(const QString &filter) { + Q_D(XDPFileDialog); +} + +QString XDPFileDialog::selectedMimeTypeFilter() const { + Q_D(const XDPFileDialog); + return d->selectedMimeTypeFilter; +} + +void XDPFileDialog::selectNameFilter(const QString &filter) { + Q_D(XDPFileDialog); +} + +QString XDPFileDialog::selectedNameFilter() const { + Q_D(const XDPFileDialog); + return d->selectedNameFilter; +} + +int XDPFileDialog::exec() { + Q_D(XDPFileDialog); + + bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose); + setAttribute(Qt::WA_DeleteOnClose, false); + + bool wasShowModal = testAttribute(Qt::WA_ShowModal); + setAttribute(Qt::WA_ShowModal, true); + setResult(0); + + show(); + + QPointer guard = this; + + // HACK we have to avoid returning until we emit that the dialog was accepted or rejected + QEventLoop loop; + rpl::lifetime lifetime; + + accepted( + ) | rpl::start_with_next([&] { + loop.quit(); + }, lifetime); + + rejected( + ) | rpl::start_with_next([&] { + loop.quit(); + }, lifetime); + + loop.exec(); + + if (guard.isNull()) + return QDialog::Rejected; + + setAttribute(Qt::WA_ShowModal, wasShowModal); + + return result(); +} + +void XDPFileDialog::setVisible(bool visible) { + if (visible) { + if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden)) { + return; + } + } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden)) { + return; + } + + if (visible) { + showHelper(windowFlags(), windowModality(), parentWidget() ? parentWidget()->windowHandle() : nullptr); + } else { + hideHelper(); + } + + // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below + // updates the state correctly, but skips showing the non-native version: + setAttribute(Qt::WA_DontShowOnScreen); + + QDialog::setVisible(visible); +} + +void XDPFileDialog::hideHelper() { + Q_D(XDPFileDialog); +} + +void XDPFileDialog::showHelper(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) { + Q_D(XDPFileDialog); + + initializeDialog(); + + d->modal = windowModality != Qt::NonModal; + d->winId = parent ? parent->winId() : 0; + + openPortal(); +} + +void XDPFileDialog::gotResponse(uint response, const QVariantMap &results) { + Q_D(XDPFileDialog); + + if (!response) { + if (results.contains(QLatin1String("uris"))) + d->selectedFiles = results.value(QLatin1String("uris")).toStringList(); + + if (results.contains(QLatin1String("current_filter"))) { + const Filter selectedFilter = qdbus_cast(results.value(QStringLiteral("current_filter"))); + if (!selectedFilter.filterConditions.empty() && selectedFilter.filterConditions[0].type == MimeType) { + // s.a. XDPFileDialog::openPortal which basically does the inverse + d->selectedMimeTypeFilter = selectedFilter.filterConditions[0].pattern; + d->selectedNameFilter.clear(); + } else { + d->selectedNameFilter = d->userVisibleToNameFilter.value(selectedFilter.name); + d->selectedMimeTypeFilter.clear(); + } + } + _accept.fire({}); + } else { + _reject.fire({}); + } +} + +rpl::producer<> XDPFileDialog::accepted() { + return _accept.events(); +} + +rpl::producer<> XDPFileDialog::rejected() { + return _reject.events(); +} + +} // namespace XDP +} // namespace FileDialog +} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_xdp_file_dialog.h b/Telegram/SourceFiles/platform/linux/linux_xdp_file_dialog.h new file mode 100644 index 0000000000..57bc43e569 --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/linux_xdp_file_dialog.h @@ -0,0 +1,136 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "core/file_utilities.h" + +#include +#include + +namespace Platform { +namespace FileDialog { +namespace XDP { + +class XDPFileDialogPrivate; +using Type = ::FileDialog::internal::Type; + +bool Use(Type type = Type::ReadFile); +bool Get( + QPointer parent, + QStringList &files, + QByteArray &remoteContent, + const QString &caption, + const QString &filter, + Type type, + QString startFile); + +// This is a patched copy of file dialog from qxdgdesktopportal theme plugin. +// It allows using XDP file dialog flexibly, +// without relying on QT_QPA_PLATFORMTHEME variable. +// +// XDP file dialog is a dialog obtained via a DBus service +// provided by the current desktop environment. +class XDPFileDialog : public QDialog { + Q_OBJECT + Q_DECLARE_PRIVATE(XDPFileDialog) +public: + enum ConditionType : uint { + GlobalPattern = 0, + MimeType = 1 + }; + // Filters a(sa(us)) + // Example: [('Images', [(0, '*.ico'), (1, 'image/png')]), ('Text', [(0, '*.txt')])] + struct FilterCondition { + ConditionType type; + QString pattern; // E.g. '*ico' or 'image/png' + }; + typedef QVector FilterConditionList; + + struct Filter { + QString name; // E.g. 'Images' or 'Text + FilterConditionList filterConditions;; // E.g. [(0, '*.ico'), (1, 'image/png')] or [(0, '*.txt')] + }; + typedef QVector FilterList; + + XDPFileDialog( + QWidget *parent = nullptr, + const QString &caption = QString(), + const QString &directory = QString(), + const QString &filter = QString()); + ~XDPFileDialog(); + + void setVisible(bool visible) override; + + void setWindowTitle(const QString &windowTitle) { + _windowTitle = windowTitle; + } + void setAcceptMode(QFileDialog::AcceptMode acceptMode) { + _acceptMode = acceptMode; + } + void setFileMode(QFileDialog::FileMode fileMode) { + _fileMode = fileMode; + } + void setOption(QFileDialog::Option option, bool on = true) { + if (on) { + _options |= option; + } else { + _options &= ~option; + } + } + + bool defaultNameFilterDisables() const; + QUrl directory() const; + void setDirectory(const QUrl &directory); + void selectFile(const QUrl &filename); + QList selectedFiles() const; + void setFilter(); + void selectNameFilter(const QString &filter); + QString selectedNameFilter() const; + void selectMimeTypeFilter(const QString &filter); + QString selectedMimeTypeFilter() const; + + int exec() override; + +private Q_SLOTS: + void gotResponse(uint response, const QVariantMap &results); + +private: + void initializeDialog(); + void openPortal(); + + void showHelper(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent); + void hideHelper(); + + rpl::producer<> accepted(); + rpl::producer<> rejected(); + + QScopedPointer d_ptr; + + // Options + QFileDialog::Options _options; + QString _windowTitle = "Choose file"; + QString _initialDirectory; + QStringList _initialFiles; + QStringList _nameFilters; + QFileDialog::AcceptMode _acceptMode = QFileDialog::AcceptOpen; + QFileDialog::FileMode _fileMode = QFileDialog::ExistingFile; + + rpl::event_stream<> _accept; + rpl::event_stream<> _reject; + rpl::lifetime _lifetime; +}; + +} // namespace XDP +} // namespace FileDialog +} // namespace Platform + +Q_DECLARE_METATYPE(Platform::FileDialog::XDP::XDPFileDialog::FilterCondition); +Q_DECLARE_METATYPE(Platform::FileDialog::XDP::XDPFileDialog::FilterConditionList); +Q_DECLARE_METATYPE(Platform::FileDialog::XDP::XDPFileDialog::Filter); +Q_DECLARE_METATYPE(Platform::FileDialog::XDP::XDPFileDialog::FilterList); + diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 6f2acd99e8..cc091af3f0 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -29,8 +29,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include -#include -#include #include #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION @@ -596,18 +594,16 @@ bool AreQtPluginsBundled() { bool UseXDGDesktopPortal() { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION static const auto Result = [&] { - const auto onlyIn = AreQtPluginsBundled() - // it is handled by Qt for flatpak and snap - && !InFlatpak() - && !InSnap(); + if (InFlatpak() || InSnap()) { + return true; + } const auto envVar = qEnvironmentVariableIsSet("TDESKTOP_USE_PORTAL"); const auto portalPresent = IsXDGDesktopPortalPresent(); const auto neededForKde = DesktopEnvironment::IsKDE() && IsXDGDesktopPortalKDEPresent(); - return onlyIn - && portalPresent + return portalPresent && (neededForKde || envVar); }(); @@ -620,12 +616,7 @@ bool UseXDGDesktopPortal() { bool CanOpenDirectoryWithPortal() { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION static const auto Result = [&] { -#ifdef DESKTOP_APP_QT_PATCHED return FileChooserPortalVersion() >= 3; -#else // DESKTOP_APP_QT_PATCHED - return QLibraryInfo::version() >= QVersionNumber(5, 15, 0) - && FileChooserPortalVersion() >= 3; -#endif // !DESKTOP_APP_QT_PATCHED }(); return Result; @@ -1037,14 +1028,12 @@ void start() { } #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION - // this can give us a chance to use - // a proper file dialog for current session + // Tell the user when XDP file dialog is used DEBUG_LOG(("Checking for XDG Desktop Portal...")); if (IsXDGDesktopPortalPresent()) { DEBUG_LOG(("XDG Desktop Portal is present!")); if (UseXDGDesktopPortal()) { LOG(("Using XDG Desktop Portal.")); - qputenv("QT_QPA_PLATFORMTHEME", "xdgdesktopportal"); } else { DEBUG_LOG(("Not using XDG Desktop Portal.")); }