Port linux_xdp_open_with_dialog to cppgir

This commit is contained in:
Ilya Fedin 2024-03-07 02:21:09 +04:00 committed by John Preston
parent 1e9b7e2726
commit 7b8cdb43c4

View file

@ -13,130 +13,115 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/random.h" #include "base/random.h"
#include <fcntl.h> #include <fcntl.h>
#include <glibmm.h> #include <xdpopenuri/xdpopenuri.hpp>
#include <giomm.h> #include <xdprequest/xdprequest.hpp>
namespace Platform { namespace Platform {
namespace File { namespace File {
namespace internal { namespace internal {
namespace { namespace {
constexpr auto kXDPOpenURIInterface = "org.freedesktop.portal.OpenURI"; using namespace gi::repository;
constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties";
using base::Platform::XdgActivationToken; using base::Platform::XdgActivationToken;
} // namespace } // namespace
bool ShowXDPOpenWithDialog(const QString &filepath) { bool ShowXDPOpenWithDialog(const QString &filepath) {
try { auto proxy = XdpOpenURI::OpenURIProxy::new_for_bus_sync(
const auto connection = Gio::DBus::Connection::get_sync( Gio::BusType::SESSION_,
Gio::DBus::BusType::SESSION); Gio::DBusProxyFlags::NONE_,
base::Platform::XDP::kService,
const auto version = connection->call_sync(
base::Platform::XDP::kObjectPath, base::Platform::XDP::kObjectPath,
kPropertiesInterface, nullptr);
"Get",
Glib::create_variant(std::tuple{
Glib::ustring(kXDPOpenURIInterface),
Glib::ustring("version"),
}),
base::Platform::XDP::kService
).get_child(0).get_dynamic<Glib::Variant<uint>>().get();
if (version < 3) { if (!proxy) {
return false; return false;
} }
const auto filepathUtf8 = filepath.toUtf8(); auto interface = XdpOpenURI::OpenURI(proxy);
if (interface.get_version() < 3) {
return false;
}
const auto fd = open( const auto fd = open(
filepathUtf8.constData(), QFile::encodeName(filepath).constData(),
O_RDONLY); O_RDONLY);
if (fd == -1) { if (fd == -1) {
return false; return false;
} }
const auto fdGuard = gsl::finally([&] { ::close(fd); }); const auto fdGuard = gsl::finally([&] { close(fd); });
const auto handleToken = Glib::ustring("tdesktop") const auto handleToken = "tdesktop"
+ std::to_string(base::RandomValue<uint>()); + std::to_string(base::RandomValue<uint>());
auto uniqueName = connection->get_unique_name(); std::string uniqueName = proxy.get_connection().get_unique_name();
uniqueName.erase(0, 1); uniqueName.erase(0, 1);
uniqueName.replace(uniqueName.find('.'), 1, 1, '_'); uniqueName.replace(uniqueName.find('.'), 1, 1, '_');
const auto requestPath = base::Platform::XDP::kObjectPath auto request = XdpRequest::Request(
+ Glib::ustring("/request/") XdpRequest::RequestProxy::new_sync(
proxy.get_connection(),
Gio::DBusProxyFlags::NONE_,
base::Platform::XDP::kService,
base::Platform::XDP::kObjectPath
+ std::string("/request/")
+ uniqueName + uniqueName
+ '/' + '/'
+ handleToken; + handleToken,
nullptr,
nullptr));
const auto loop = Glib::MainLoop::create(); if (!request) {
return false;
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) {
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 loop = GLib::MainLoop::new_();
const auto signalId = request.signal_response().connect([=](
XdpRequest::Request,
guint,
GLib::Variant) mutable {
loop.quit();
}); });
auto outFdList = Glib::RefPtr<Gio::UnixFDList>(); const auto signalGuard = gsl::finally([&] {
request.disconnect(signalId);
});
connection->call_sync( auto result = interface.call_open_file_sync(
base::Platform::XDP::kObjectPath, std::string(base::Platform::XDP::ParentWindowID()),
kXDPOpenURIInterface, GLib::Variant::new_handle(0),
"OpenFile", GLib::Variant::new_array({
Glib::create_variant(std::tuple{ GLib::Variant::new_dict_entry(
base::Platform::XDP::ParentWindowID(), GLib::Variant::new_string("handle_token"),
Glib::DBusHandle(), GLib::Variant::new_variant(
std::map<Glib::ustring, Glib::VariantBase>{ GLib::Variant::new_string(handleToken))),
{ GLib::Variant::new_dict_entry(
"handle_token", GLib::Variant::new_string("activation_token"),
Glib::create_variant(handleToken) GLib::Variant::new_variant(
}, GLib::Variant::new_string(
{ XdgActivationToken().toStdString()))),
"activation_token", GLib::Variant::new_dict_entry(
Glib::create_variant( GLib::Variant::new_string("ask"),
Glib::ustring(XdgActivationToken().toStdString())) GLib::Variant::new_variant(
}, GLib::Variant::new_boolean(true))),
{
"ask",
Glib::create_variant(true)
},
},
}), }),
Gio::UnixFDList::create(std::vector<int>{ fd }), Gio::UnixFDList::new_from_array((std::array{ fd }).data(), 1),
outFdList, nullptr);
base::Platform::XDP::kService);
if (!result) {
return false;
}
if (signalId != 0) {
QWidget window; QWidget window;
window.setAttribute(Qt::WA_DontShowOnScreen); window.setAttribute(Qt::WA_DontShowOnScreen);
window.setWindowModality(Qt::ApplicationModal); window.setWindowModality(Qt::ApplicationModal);
window.show(); window.show();
loop->run(); loop.run();
}
return true; return true;
} catch (...) {
}
return false;
} }
} // namespace internal } // namespace internal