mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Port linux_xdp_open_with_dialog to cppgir
This commit is contained in:
parent
1e9b7e2726
commit
7b8cdb43c4
1 changed files with 95 additions and 110 deletions
|
@ -13,130 +13,115 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/random.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <glibmm.h>
|
||||
#include <giomm.h>
|
||||
#include <xdpopenuri/xdpopenuri.hpp>
|
||||
#include <xdprequest/xdprequest.hpp>
|
||||
|
||||
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<Glib::Variant<uint>>().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<uint>());
|
||||
|
||||
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<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 ¶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<Gio::UnixFDList>();
|
||||
|
||||
connection->call_sync(
|
||||
base::Platform::XDP::kObjectPath,
|
||||
kXDPOpenURIInterface,
|
||||
"OpenFile",
|
||||
Glib::create_variant(std::tuple{
|
||||
base::Platform::XDP::ParentWindowID(),
|
||||
Glib::DBusHandle(),
|
||||
std::map<Glib::ustring, Glib::VariantBase>{
|
||||
{
|
||||
"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<int>{ 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<uint>());
|
||||
|
||||
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
|
||||
|
|
Loading…
Add table
Reference in a new issue