From 7b8cdb43c49d6d91e406c459f004fbf9a8658981 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 7 Mar 2024 02:21:09 +0400 Subject: [PATCH] Port linux_xdp_open_with_dialog to cppgir --- .../linux/linux_xdp_open_with_dialog.cpp | 205 ++++++++---------- 1 file changed, 95 insertions(+), 110 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/linux_xdp_open_with_dialog.cpp b/Telegram/SourceFiles/platform/linux/linux_xdp_open_with_dialog.cpp index b01d5abbe..bd82cb17f 100644 --- a/Telegram/SourceFiles/platform/linux/linux_xdp_open_with_dialog.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_xdp_open_with_dialog.cpp @@ -13,130 +13,115 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/random.h" #include -#include -#include +#include +#include namespace Platform { namespace File { namespace internal { namespace { -constexpr auto kXDPOpenURIInterface = "org.freedesktop.portal.OpenURI"; -constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"; +using namespace gi::repository; using base::Platform::XdgActivationToken; } // namespace bool ShowXDPOpenWithDialog(const QString &filepath) { - try { - const auto connection = Gio::DBus::Connection::get_sync( - Gio::DBus::BusType::SESSION); + auto proxy = XdpOpenURI::OpenURIProxy::new_for_bus_sync( + Gio::BusType::SESSION_, + Gio::DBusProxyFlags::NONE_, + base::Platform::XDP::kService, + base::Platform::XDP::kObjectPath, + nullptr); - const auto version = connection->call_sync( - base::Platform::XDP::kObjectPath, - kPropertiesInterface, - "Get", - Glib::create_variant(std::tuple{ - Glib::ustring(kXDPOpenURIInterface), - Glib::ustring("version"), - }), - base::Platform::XDP::kService - ).get_child(0).get_dynamic>().get(); - - if (version < 3) { - return false; - } - - const auto filepathUtf8 = filepath.toUtf8(); - - const auto fd = open( - filepathUtf8.constData(), - O_RDONLY); - - if (fd == -1) { - return false; - } - - const auto fdGuard = gsl::finally([&] { ::close(fd); }); - - const auto handleToken = Glib::ustring("tdesktop") - + std::to_string(base::RandomValue()); - - auto uniqueName = connection->get_unique_name(); - uniqueName.erase(0, 1); - uniqueName.replace(uniqueName.find('.'), 1, 1, '_'); - - const auto requestPath = base::Platform::XDP::kObjectPath - + Glib::ustring("/request/") - + uniqueName - + '/' - + handleToken; - - const auto loop = Glib::MainLoop::create(); - - const auto signalId = connection->signal_subscribe( - [&]( - const Glib::RefPtr &connection, - const Glib::ustring &sender_name, - const Glib::ustring &object_path, - const Glib::ustring &interface_name, - const Glib::ustring &signal_name, - const Glib::VariantContainerBase ¶meters) { - loop->quit(); - }, - base::Platform::XDP::kService, - base::Platform::XDP::kRequestInterface, - "Response", - requestPath); - - const auto signalGuard = gsl::finally([&] { - if (signalId != 0) { - connection->signal_unsubscribe(signalId); - } - }); - - auto outFdList = Glib::RefPtr(); - - connection->call_sync( - base::Platform::XDP::kObjectPath, - kXDPOpenURIInterface, - "OpenFile", - Glib::create_variant(std::tuple{ - base::Platform::XDP::ParentWindowID(), - Glib::DBusHandle(), - std::map{ - { - "handle_token", - Glib::create_variant(handleToken) - }, - { - "activation_token", - Glib::create_variant( - Glib::ustring(XdgActivationToken().toStdString())) - }, - { - "ask", - Glib::create_variant(true) - }, - }, - }), - Gio::UnixFDList::create(std::vector{ fd }), - outFdList, - base::Platform::XDP::kService); - - if (signalId != 0) { - QWidget window; - window.setAttribute(Qt::WA_DontShowOnScreen); - window.setWindowModality(Qt::ApplicationModal); - window.show(); - loop->run(); - } - - return true; - } catch (...) { + if (!proxy) { + return false; } - return false; + auto interface = XdpOpenURI::OpenURI(proxy); + if (interface.get_version() < 3) { + return false; + } + + const auto fd = open( + QFile::encodeName(filepath).constData(), + O_RDONLY); + + if (fd == -1) { + return false; + } + + const auto fdGuard = gsl::finally([&] { close(fd); }); + + const auto handleToken = "tdesktop" + + std::to_string(base::RandomValue()); + + std::string uniqueName = proxy.get_connection().get_unique_name(); + uniqueName.erase(0, 1); + uniqueName.replace(uniqueName.find('.'), 1, 1, '_'); + + auto request = XdpRequest::Request( + XdpRequest::RequestProxy::new_sync( + proxy.get_connection(), + Gio::DBusProxyFlags::NONE_, + base::Platform::XDP::kService, + base::Platform::XDP::kObjectPath + + std::string("/request/") + + uniqueName + + '/' + + handleToken, + nullptr, + nullptr)); + + if (!request) { + return false; + } + + auto loop = GLib::MainLoop::new_(); + + const auto signalId = request.signal_response().connect([=]( + XdpRequest::Request, + guint, + GLib::Variant) mutable { + loop.quit(); + }); + + const auto signalGuard = gsl::finally([&] { + request.disconnect(signalId); + }); + + auto result = interface.call_open_file_sync( + std::string(base::Platform::XDP::ParentWindowID()), + GLib::Variant::new_handle(0), + GLib::Variant::new_array({ + GLib::Variant::new_dict_entry( + GLib::Variant::new_string("handle_token"), + GLib::Variant::new_variant( + GLib::Variant::new_string(handleToken))), + GLib::Variant::new_dict_entry( + GLib::Variant::new_string("activation_token"), + GLib::Variant::new_variant( + GLib::Variant::new_string( + XdgActivationToken().toStdString()))), + GLib::Variant::new_dict_entry( + GLib::Variant::new_string("ask"), + GLib::Variant::new_variant( + GLib::Variant::new_boolean(true))), + }), + Gio::UnixFDList::new_from_array((std::array{ fd }).data(), 1), + nullptr); + + if (!result) { + return false; + } + + QWidget window; + window.setAttribute(Qt::WA_DontShowOnScreen); + window.setWindowModality(Qt::ApplicationModal); + window.show(); + loop.run(); + + return true; } } // namespace internal