mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Port specific_linux to cppgir
This commit is contained in:
parent
7c002cf8be
commit
0df8864ae0
2 changed files with 224 additions and 186 deletions
|
@ -1679,6 +1679,9 @@ else()
|
|||
desktop-app::external_glibmm
|
||||
)
|
||||
|
||||
include(${cmake_helpers_loc}/external/glib/generate_dbus.cmake)
|
||||
generate_dbus(Telegram org.freedesktop.portal. XdpBackground ${third_party_loc}/xdg-desktop-portal/data/org.freedesktop.portal.Background.xml)
|
||||
|
||||
if (NOT DESKTOP_APP_DISABLE_X11_INTEGRATION)
|
||||
target_link_libraries(Telegram
|
||||
PRIVATE
|
||||
|
|
|
@ -38,6 +38,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <glibmm.h>
|
||||
#include <giomm.h>
|
||||
|
||||
#include <xdgdbus/xdgdbus.hpp>
|
||||
#include <xdpbackground/xdpbackground.hpp>
|
||||
#include <xdprequest/xdprequest.hpp>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
|
@ -48,12 +52,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace gi::repository;
|
||||
namespace Gio = gi::repository::Gio;
|
||||
using namespace Platform;
|
||||
using Platform::internal::WaylandIntegration;
|
||||
|
||||
namespace Platform {
|
||||
namespace {
|
||||
|
||||
void PortalAutostart(bool enabled, Fn<void(bool)> done) {
|
||||
if (cExeName().isEmpty()) {
|
||||
if (done) {
|
||||
|
@ -62,127 +67,141 @@ void PortalAutostart(bool enabled, Fn<void(bool)> done) {
|
|||
return;
|
||||
}
|
||||
|
||||
const auto connection = [&] {
|
||||
try {
|
||||
return Gio::DBus::Connection::get_sync(
|
||||
Gio::DBus::BusType::SESSION);
|
||||
} catch (const std::exception &e) {
|
||||
if (done) {
|
||||
LOG(("Portal Autostart Error: %1").arg(e.what()));
|
||||
XdpBackground::BackgroundProxy::new_for_bus(
|
||||
Gio::BusType::SESSION_,
|
||||
Gio::DBusProxyFlags::NONE_,
|
||||
base::Platform::XDP::kService,
|
||||
base::Platform::XDP::kObjectPath,
|
||||
[=](GObject::Object, Gio::AsyncResult res) {
|
||||
auto proxy = XdpBackground::BackgroundProxy::new_for_bus_finish(
|
||||
res);
|
||||
|
||||
if (!proxy) {
|
||||
if (done) {
|
||||
LOG(("Portal Autostart Error: %1").arg(
|
||||
proxy.error().what()));
|
||||
done(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return Glib::RefPtr<Gio::DBus::Connection>();
|
||||
}
|
||||
}();
|
||||
|
||||
if (!connection) {
|
||||
if (done) {
|
||||
done(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto interface = XdpBackground::Background(*proxy);
|
||||
|
||||
const auto handleToken = Glib::ustring("tdesktop")
|
||||
+ std::to_string(base::RandomValue<uint>());
|
||||
const auto handleToken = "tdesktop"
|
||||
+ std::to_string(base::RandomValue<uint>());
|
||||
|
||||
std::vector<Glib::ustring> commandline;
|
||||
commandline.push_back(cExeName().toStdString());
|
||||
if (Core::Launcher::Instance().customWorkingDir()) {
|
||||
commandline.push_back("-workdir");
|
||||
commandline.push_back(cWorkingDir().toStdString());
|
||||
}
|
||||
commandline.push_back("-autostart");
|
||||
auto uniqueName = std::string(
|
||||
proxy->get_connection().get_unique_name());
|
||||
uniqueName.erase(0, 1);
|
||||
uniqueName.replace(uniqueName.find('.'), 1, 1, '_');
|
||||
|
||||
std::map<Glib::ustring, Glib::VariantBase> options;
|
||||
options["handle_token"] = Glib::create_variant(handleToken);
|
||||
options["reason"] = Glib::create_variant(
|
||||
Glib::ustring(
|
||||
tr::lng_settings_auto_start(tr::now).toStdString()));
|
||||
options["autostart"] = Glib::create_variant(enabled);
|
||||
options["commandline"] = Glib::create_variant(commandline);
|
||||
options["dbus-activatable"] = Glib::create_variant(false);
|
||||
const auto window = std::make_shared<QWidget>();
|
||||
window->setAttribute(Qt::WA_DontShowOnScreen);
|
||||
window->setWindowModality(Qt::ApplicationModal);
|
||||
window->show();
|
||||
|
||||
auto uniqueName = connection->get_unique_name();
|
||||
uniqueName.erase(0, 1);
|
||||
uniqueName.replace(uniqueName.find('.'), 1, 1, '_');
|
||||
XdpRequest::RequestProxy::new_(
|
||||
proxy->get_connection(),
|
||||
Gio::DBusProxyFlags::NONE_,
|
||||
base::Platform::XDP::kService,
|
||||
base::Platform::XDP::kObjectPath
|
||||
+ std::string("/request/")
|
||||
+ uniqueName
|
||||
+ '/'
|
||||
+ handleToken,
|
||||
nullptr,
|
||||
[=](GObject::Object, Gio::AsyncResult res) mutable {
|
||||
auto requestProxy = XdpRequest::RequestProxy::new_finish(
|
||||
res);
|
||||
|
||||
const auto requestPath = base::Platform::XDP::kObjectPath
|
||||
+ Glib::ustring("/request/")
|
||||
+ uniqueName
|
||||
+ '/'
|
||||
+ handleToken;
|
||||
|
||||
const auto window = std::make_shared<QWidget>();
|
||||
window->setAttribute(Qt::WA_DontShowOnScreen);
|
||||
window->setWindowModality(Qt::ApplicationModal);
|
||||
window->show();
|
||||
|
||||
const auto signalId = std::make_shared<uint>();
|
||||
*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) {
|
||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||
(void)window; // don't destroy until finish
|
||||
|
||||
try {
|
||||
const auto response = parameters.get_child(
|
||||
0
|
||||
).get_dynamic<uint>();
|
||||
|
||||
if (response) {
|
||||
if (!requestProxy) {
|
||||
if (done) {
|
||||
LOG(("Portal Autostart Error: Request denied"));
|
||||
LOG(("Portal Autostart Error: %1").arg(
|
||||
requestProxy.error().what()));
|
||||
done(false);
|
||||
}
|
||||
} else if (done) {
|
||||
done(enabled);
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
if (done) {
|
||||
LOG(("Portal Autostart Error: %1").arg(e.what()));
|
||||
done(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (*signalId) {
|
||||
connection->signal_unsubscribe(*signalId);
|
||||
}
|
||||
});
|
||||
},
|
||||
base::Platform::XDP::kService,
|
||||
base::Platform::XDP::kRequestInterface,
|
||||
"Response",
|
||||
requestPath);
|
||||
|
||||
connection->call(
|
||||
base::Platform::XDP::kObjectPath,
|
||||
"org.freedesktop.portal.Background",
|
||||
"RequestBackground",
|
||||
Glib::create_variant(std::tuple{
|
||||
base::Platform::XDP::ParentWindowID(),
|
||||
options,
|
||||
}),
|
||||
[=](const Glib::RefPtr<Gio::AsyncResult> &result) {
|
||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||
try {
|
||||
connection->call_finish(result);
|
||||
} catch (const std::exception &e) {
|
||||
if (done) {
|
||||
LOG(("Portal Autostart Error: %1").arg(e.what()));
|
||||
done(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (*signalId) {
|
||||
connection->signal_unsubscribe(*signalId);
|
||||
auto request = XdpRequest::Request(*requestProxy);
|
||||
const auto signalId = std::make_shared<ulong>();
|
||||
*signalId = request.signal_response().connect([=](
|
||||
XdpRequest::Request,
|
||||
guint response,
|
||||
GLib::Variant) mutable {
|
||||
auto &sandbox = Core::Sandbox::Instance();
|
||||
sandbox.customEnterFromEventLoop([&] {
|
||||
(void)window; // don't destroy until finish
|
||||
|
||||
if (response) {
|
||||
if (done) {
|
||||
LOG(("Portal Autostart Error: "
|
||||
"Request denied"));
|
||||
done(false);
|
||||
}
|
||||
} else if (done) {
|
||||
done(enabled);
|
||||
}
|
||||
|
||||
request.disconnect(*signalId);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
std::vector<std::string> commandline;
|
||||
commandline.push_back(cExeName().toStdString());
|
||||
if (Core::Launcher::Instance().customWorkingDir()) {
|
||||
commandline.push_back("-workdir");
|
||||
commandline.push_back(cWorkingDir().toStdString());
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
base::Platform::XDP::kService);
|
||||
commandline.push_back("-autostart");
|
||||
|
||||
interface.call_request_background(
|
||||
std::string(base::Platform::XDP::ParentWindowID()),
|
||||
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("reason"),
|
||||
GLib::Variant::new_variant(
|
||||
GLib::Variant::new_string(
|
||||
tr::lng_settings_auto_start(tr::now)
|
||||
.toStdString()))),
|
||||
GLib::Variant::new_dict_entry(
|
||||
GLib::Variant::new_string("autostart"),
|
||||
GLib::Variant::new_variant(
|
||||
GLib::Variant::new_boolean(enabled))),
|
||||
GLib::Variant::new_dict_entry(
|
||||
GLib::Variant::new_string("commandline"),
|
||||
GLib::Variant::new_variant(
|
||||
GLib::Variant::new_strv(commandline))),
|
||||
GLib::Variant::new_dict_entry(
|
||||
GLib::Variant::new_string("dbus-activatable"),
|
||||
GLib::Variant::new_variant(
|
||||
GLib::Variant::new_boolean(false))),
|
||||
}),
|
||||
[=](GObject::Object, Gio::AsyncResult res) mutable {
|
||||
auto &sandbox = Core::Sandbox::Instance();
|
||||
sandbox.customEnterFromEventLoop([&] {
|
||||
const auto result =
|
||||
interface.call_request_background_finish(
|
||||
res);
|
||||
|
||||
if (!result) {
|
||||
if (done) {
|
||||
LOG(("Portal Autostart Error: %1")
|
||||
.arg(result.error().what()));
|
||||
done(false);
|
||||
}
|
||||
|
||||
request.disconnect(*signalId);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
bool GenerateDesktopFile(
|
||||
|
@ -218,77 +237,89 @@ bool GenerateDesktopFile(
|
|||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const auto target = Glib::KeyFile::create();
|
||||
target->load_from_data(
|
||||
sourceText,
|
||||
Glib::KeyFile::Flags::KEEP_COMMENTS
|
||||
| Glib::KeyFile::Flags::KEEP_TRANSLATIONS);
|
||||
auto target = GLib::KeyFile::new_();
|
||||
const auto loaded = target.load_from_data(
|
||||
sourceText,
|
||||
-1,
|
||||
GLib::KeyFileFlags::KEEP_COMMENTS_
|
||||
| GLib::KeyFileFlags::KEEP_TRANSLATIONS_);
|
||||
|
||||
if (!loaded) {
|
||||
if (!silent) {
|
||||
LOG(("App Error: %1").arg(loaded.error().what()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto &group : target->get_groups()) {
|
||||
if (onlyMainGroup && group != "Desktop Entry") {
|
||||
target->remove_group(group);
|
||||
continue;
|
||||
for (const auto &group : target.get_groups(nullptr)) {
|
||||
if (onlyMainGroup && group != "Desktop Entry") {
|
||||
const auto removed = target.remove_group(group);
|
||||
if (!removed) {
|
||||
if (!silent) {
|
||||
LOG(("App Error: %1").arg(removed.error().what()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (target->has_key(group, "TryExec")) {
|
||||
target->set_string(
|
||||
if (target.has_key(group, "TryExec", nullptr)) {
|
||||
target.set_string(
|
||||
group,
|
||||
"TryExec",
|
||||
KShell::joinArgs({ executable }).replace(
|
||||
'\\',
|
||||
qstr("\\\\")).toStdString());
|
||||
}
|
||||
|
||||
if (target.has_key(group, "Exec", nullptr)) {
|
||||
if (group == "Desktop Entry" && !args.isEmpty()) {
|
||||
QStringList exec;
|
||||
exec.append(executable);
|
||||
if (Core::Launcher::Instance().customWorkingDir()) {
|
||||
exec.append(u"-workdir"_q);
|
||||
exec.append(cWorkingDir());
|
||||
}
|
||||
exec.append(args);
|
||||
target.set_string(
|
||||
group,
|
||||
"TryExec",
|
||||
KShell::joinArgs({ executable }).replace(
|
||||
"Exec",
|
||||
KShell::joinArgs(exec).replace(
|
||||
'\\',
|
||||
qstr("\\\\")).toStdString());
|
||||
}
|
||||
} else {
|
||||
auto exec = KShell::splitArgs(
|
||||
QString::fromStdString(
|
||||
target.get_string(group, "Exec", nullptr)
|
||||
).replace(
|
||||
qstr("\\\\"),
|
||||
qstr("\\")));
|
||||
|
||||
if (target->has_key(group, "Exec")) {
|
||||
if (group == "Desktop Entry" && !args.isEmpty()) {
|
||||
QStringList exec;
|
||||
exec.append(executable);
|
||||
if (!exec.isEmpty()) {
|
||||
exec[0] = executable;
|
||||
if (Core::Launcher::Instance().customWorkingDir()) {
|
||||
exec.append(u"-workdir"_q);
|
||||
exec.append(cWorkingDir());
|
||||
exec.insert(1, u"-workdir"_q);
|
||||
exec.insert(2, cWorkingDir());
|
||||
}
|
||||
exec.append(args);
|
||||
target->set_string(
|
||||
target.set_string(
|
||||
group,
|
||||
"Exec",
|
||||
KShell::joinArgs(exec).replace(
|
||||
'\\',
|
||||
qstr("\\\\")).toStdString());
|
||||
} else {
|
||||
auto exec = KShell::splitArgs(
|
||||
QString::fromStdString(
|
||||
target->get_string(group, "Exec")
|
||||
).replace(
|
||||
qstr("\\\\"),
|
||||
qstr("\\")));
|
||||
|
||||
if (!exec.isEmpty()) {
|
||||
exec[0] = executable;
|
||||
if (Core::Launcher::Instance().customWorkingDir()) {
|
||||
exec.insert(1, u"-workdir"_q);
|
||||
exec.insert(2, cWorkingDir());
|
||||
}
|
||||
target->set_string(
|
||||
group,
|
||||
"Exec",
|
||||
KShell::joinArgs(exec).replace(
|
||||
'\\',
|
||||
qstr("\\\\")).toStdString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!args.isEmpty()
|
||||
&& target->has_key("Desktop Entry", "DBusActivatable")) {
|
||||
target->remove_key("Desktop Entry", "DBusActivatable");
|
||||
}
|
||||
if (!args.isEmpty()) {
|
||||
target.remove_key("Desktop Entry", "DBusActivatable");
|
||||
}
|
||||
|
||||
target->save_to_file(targetFile.toStdString());
|
||||
} catch (const std::exception &e) {
|
||||
const auto saved = target.save_to_file(targetFile.toStdString());
|
||||
if (!saved) {
|
||||
if (!silent) {
|
||||
LOG(("App Error: %1").arg(e.what()));
|
||||
LOG(("App Error: %1").arg(saved.error().what()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -357,10 +388,10 @@ bool GenerateServiceFile(bool silent = false) {
|
|||
DEBUG_LOG(("App Info: placing D-Bus service file to %1").arg(targetPath));
|
||||
if (!QDir(targetPath).exists()) QDir().mkpath(targetPath);
|
||||
|
||||
const auto target = Glib::KeyFile::create();
|
||||
auto target = GLib::KeyFile::new_();
|
||||
constexpr auto group = "D-BUS Service";
|
||||
|
||||
target->set_string(
|
||||
target.set_string(
|
||||
group,
|
||||
"Name",
|
||||
QGuiApplication::desktopFileName().toStdString());
|
||||
|
@ -371,21 +402,21 @@ bool GenerateServiceFile(bool silent = false) {
|
|||
exec.append(u"-workdir"_q);
|
||||
exec.append(cWorkingDir());
|
||||
}
|
||||
target->set_string(
|
||||
target.set_string(
|
||||
group,
|
||||
"Exec",
|
||||
KShell::joinArgs(exec).toStdString());
|
||||
|
||||
try {
|
||||
target->save_to_file(targetFile.toStdString());
|
||||
} catch (const std::exception &e) {
|
||||
const auto saved = target.save_to_file(targetFile.toStdString());
|
||||
if (!saved) {
|
||||
if (!silent) {
|
||||
LOG(("App Error: %1").arg(e.what()));
|
||||
LOG(("App Error: %1").arg(saved.error().what()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Core::UpdaterDisabled() && !Core::Launcher::Instance().customWorkingDir()) {
|
||||
if (!Core::UpdaterDisabled()
|
||||
&& !Core::Launcher::Instance().customWorkingDir()) {
|
||||
DEBUG_LOG(("App Info: removing old D-Bus service files"));
|
||||
|
||||
char md5Hash[33] = { 0 };
|
||||
|
@ -397,19 +428,21 @@ bool GenerateServiceFile(bool silent = false) {
|
|||
md5Hash));
|
||||
}
|
||||
|
||||
try {
|
||||
Gio::DBus::Connection::get_sync(
|
||||
Gio::DBus::BusType::SESSION
|
||||
)->call(
|
||||
base::Platform::DBus::kObjectPath,
|
||||
base::Platform::DBus::kInterface,
|
||||
"ReloadConfig",
|
||||
{},
|
||||
{},
|
||||
base::Platform::DBus::kService
|
||||
);
|
||||
} catch (...) {
|
||||
}
|
||||
XdgDBus::DBusProxy::new_for_bus(
|
||||
Gio::BusType::SESSION_,
|
||||
Gio::DBusProxyFlags::NONE_,
|
||||
base::Platform::DBus::kService,
|
||||
base::Platform::DBus::kObjectPath,
|
||||
[=](GObject::Object, Gio::AsyncResult res) {
|
||||
auto interface = XdgDBus::DBus(
|
||||
XdgDBus::DBusProxy::new_for_bus_finish(res, nullptr));
|
||||
|
||||
if (!interface) {
|
||||
return;
|
||||
}
|
||||
|
||||
interface.call_reload_config(nullptr);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -447,6 +480,8 @@ void InstallLauncher() {
|
|||
|
||||
} // namespace
|
||||
|
||||
namespace Platform {
|
||||
|
||||
void SetApplicationIcon(const QIcon &icon) {
|
||||
QApplication::setWindowIcon(icon);
|
||||
}
|
||||
|
@ -648,11 +683,11 @@ void start() {
|
|||
qputenv("PULSE_PROP_application.name", AppName.utf8());
|
||||
qputenv("PULSE_PROP_application.icon_name", base::IconName().toLatin1());
|
||||
|
||||
Glib::set_prgname(cExeName().toStdString());
|
||||
Glib::set_application_name(AppName.data());
|
||||
GLib::set_prgname(cExeName().toStdString());
|
||||
GLib::set_application_name(AppName.data());
|
||||
|
||||
Glib::init();
|
||||
Gio::init();
|
||||
::Gio::init();
|
||||
|
||||
Webview::WebKitGTK::SetSocketPath(u"%1/%2-%3-webview-%4"_q.arg(
|
||||
QDir::tempPath(),
|
||||
|
|
Loading…
Add table
Reference in a new issue