diff --git a/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp b/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp index d13516051..65ddac56f 100644 --- a/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp @@ -127,13 +127,14 @@ using Type = ::FileDialog::internal::Type; bool NativeSupported(Type type = Type::ReadFile) { // use gtk file dialog on gtk-based desktop environments // or if QT_QPA_PLATFORMTHEME=(gtk2|gtk3) - // or if portals is used and operation is not to open folder - // (it isn't supported by portals yet) + // or if portals is used and operation is to open folder + // and portal doesn't support folder choosing return Platform::UseGtkFileDialog() && (Platform::DesktopEnvironment::IsGtkBased() || Platform::IsGtkIntegrationForced() || Platform::UseXDGDesktopPortal()) - && (!Platform::UseXDGDesktopPortal() || type == Type::ReadFolder) + && (!Platform::UseXDGDesktopPortal() + || (type == Type::ReadFolder && !Platform::CanOpenDirectoryWithPortal())) && Platform::internal::GdkHelperLoaded() && (Libs::gtk_widget_hide_on_delete != nullptr) && (Libs::gtk_clipboard_store != nullptr) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 60c352e18..43c8c684d 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -51,6 +51,10 @@ constexpr auto kDesktopFile = ":/misc/telegramdesktop.desktop"_cs; constexpr auto kSnapLauncherDir = "/var/lib/snapd/desktop/applications/"_cs; constexpr auto kIconName = "telegram"_cs; +constexpr auto kXDGDesktopPortalService = "org.freedesktop.portal.Desktop"_cs; +constexpr auto kXDGDesktopPortalObjectPath = "/org/freedesktop/portal/desktop"_cs; +constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs; + #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION void PortalAutostart(bool autostart, bool silent = false) { QVariantMap options; @@ -63,8 +67,8 @@ void PortalAutostart(bool autostart, bool silent = false) { options["dbus-activatable"] = false; auto message = QDBusMessage::createMethodCall( - qsl("org.freedesktop.portal.Desktop"), - qsl("/org/freedesktop/portal/desktop"), + kXDGDesktopPortalService.utf16(), + kXDGDesktopPortalObjectPath.utf16(), qsl("org.freedesktop.portal.Background"), qsl("RequestBackground")); @@ -84,6 +88,34 @@ void PortalAutostart(bool autostart, bool silent = false) { } } } + +uint FileChooserPortalVersion() { + static const auto Result = [&]() -> uint { + auto message = QDBusMessage::createMethodCall( + kXDGDesktopPortalService.utf16(), + kXDGDesktopPortalObjectPath.utf16(), + kPropertiesInterface.utf16(), + qsl("Get")); + + message.setArguments({ + qsl("org.freedesktop.portal.FileChooser"), + qsl("version") + }); + + const QDBusReply reply = QDBusConnection::sessionBus().call(message); + + if (reply.isValid()) { + return reply.value(); + } else { + LOG(("Error getting FileChooser portal version: %1") + .arg(reply.error().message())); + } + + return 0; + }(); + + return Result; +} #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION bool RunShellCommand(const QByteArray &command) { @@ -296,8 +328,8 @@ bool IsQtPluginsBundled() { bool IsXDGDesktopPortalPresent() { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION static const auto Result = QDBusInterface( - "org.freedesktop.portal.Desktop", - "/org/freedesktop/portal/desktop").isValid(); + kXDGDesktopPortalService.utf16(), + kXDGDesktopPortalObjectPath.utf16()).isValid(); return Result; #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION @@ -320,6 +352,14 @@ bool UseXDGDesktopPortal() { return Result; } +bool CanOpenDirectoryWithPortal() { +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED) && !defined TDESKTOP_DISABLE_DBUS_INTEGRATION + return FileChooserPortalVersion() >= 3; +#else // (Qt >= 5.15 || DESKTOP_APP_QT_PATCHED) && !TDESKTOP_DISABLE_DBUS_INTEGRATION + return false; +#endif // (Qt < 5.15 && !DESKTOP_APP_QT_PATCHED) || TDESKTOP_DISABLE_DBUS_INTEGRATION +} + QString ProcessNameByPID(const QString &pid) { constexpr auto kMaxPath = 1024; char result[kMaxPath] = { 0 }; @@ -682,10 +722,10 @@ void start() { if (IsXDGDesktopPortalPresent()) { LOG(("XDG Desktop Portal is present!")); if (UseXDGDesktopPortal()) { - LOG(("Usage of XDG Desktop Portal is enabled.")); + LOG(("Using XDG Desktop Portal.")); qputenv("QT_QPA_PLATFORMTHEME", "xdgdesktopportal"); } else { - LOG(("Usage of XDG Desktop Portal is disabled.")); + LOG(("Not using XDG Desktop Portal.")); } } else { LOG(("XDG Desktop Portal is not present :(")); diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.h b/Telegram/SourceFiles/platform/linux/specific_linux.h index 5242a94e2..041d6f795 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.h +++ b/Telegram/SourceFiles/platform/linux/specific_linux.h @@ -30,6 +30,7 @@ bool IsQtPluginsBundled(); bool IsXDGDesktopPortalPresent(); bool UseXDGDesktopPortal(); +bool CanOpenDirectoryWithPortal(); QString ProcessNameByPID(const QString &pid); QString RealExecutablePath(int argc, char *argv[]);