mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Port GApplication to cppgir
This commit is contained in:
parent
bda3bae712
commit
8669e6a891
2 changed files with 156 additions and 168 deletions
|
@ -17,79 +17,177 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include <QtCore/QAbstractEventDispatcher>
|
#include <QtCore/QAbstractEventDispatcher>
|
||||||
|
|
||||||
|
#include <glibmm.h>
|
||||||
|
#include <gio/gio.hpp>
|
||||||
#include <xdpinhibit/xdpinhibit.hpp>
|
#include <xdpinhibit/xdpinhibit.hpp>
|
||||||
#include <giomm.h>
|
|
||||||
|
|
||||||
typedef GApplication TDesktopApplication;
|
namespace Platform {
|
||||||
typedef GApplicationClass TDesktopApplicationClass;
|
namespace {
|
||||||
|
|
||||||
G_DEFINE_TYPE(
|
using namespace gi::repository;
|
||||||
TDesktopApplication,
|
|
||||||
t_desktop_application,
|
|
||||||
G_TYPE_APPLICATION)
|
|
||||||
|
|
||||||
static void t_desktop_application_class_init(
|
class Application : public Gio::impl::ApplicationImpl {
|
||||||
TDesktopApplicationClass *klass) {
|
public:
|
||||||
const auto application_class = G_APPLICATION_CLASS(klass);
|
Application();
|
||||||
|
|
||||||
application_class->local_command_line = [](
|
void before_emit_(GLib::Variant platformData) noexcept override {
|
||||||
GApplication *application,
|
|
||||||
char ***arguments,
|
|
||||||
int *exit_status) -> gboolean {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
application_class->command_line = [](
|
|
||||||
GApplication *application,
|
|
||||||
GApplicationCommandLine *cmdline) {
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
application_class->before_emit = [](
|
|
||||||
GApplication *application,
|
|
||||||
GVariant *platformData) {
|
|
||||||
if (Platform::IsWayland()) {
|
if (Platform::IsWayland()) {
|
||||||
static const auto keys = {
|
static const auto keys = {
|
||||||
"activation-token",
|
"activation-token",
|
||||||
"desktop-startup-id",
|
"desktop-startup-id",
|
||||||
};
|
};
|
||||||
for (const auto &key : keys) {
|
for (const auto &key : keys) {
|
||||||
const char *token = nullptr;
|
if (auto token = platformData.lookup_value(key)) {
|
||||||
g_variant_lookup(platformData, key, "&s", &token);
|
qputenv(
|
||||||
if (token) {
|
"XDG_ACTIVATION_TOKEN",
|
||||||
qputenv("XDG_ACTIVATION_TOKEN", token);
|
token.get_string(nullptr).c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
application_class->add_platform_data = [](
|
void startup_() noexcept override {
|
||||||
GApplication *application,
|
// GNotification
|
||||||
GVariantBuilder *builder) {
|
InvokeQueued(qApp, [] {
|
||||||
|
Core::App().notifications().createManager();
|
||||||
|
});
|
||||||
|
|
||||||
|
Gio::impl::ApplicationImpl::startup_();
|
||||||
|
QEventLoop().exec();
|
||||||
|
quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void activate_() noexcept override {
|
||||||
|
Core::Sandbox::Instance().customEnterFromEventLoop([] {
|
||||||
|
Core::App().activate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_(GFile **files, int n_files, const char*) noexcept override {
|
||||||
|
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
|
for (int i = 0; i < n_files; ++i) {
|
||||||
|
QFileOpenEvent e(
|
||||||
|
QUrl(QString::fromUtf8(g_file_get_uri(files[i]))));
|
||||||
|
QGuiApplication::sendEvent(qApp, &e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int command_line_(Gio::ApplicationCommandLine) noexcept override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean local_command_line_(char***, int*) noexcept override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_platform_data_(GLib::VariantBuilder builder) noexcept override {
|
||||||
if (Platform::IsWayland()) {
|
if (Platform::IsWayland()) {
|
||||||
const auto token = qgetenv("XDG_ACTIVATION_TOKEN");
|
const auto token = qgetenv("XDG_ACTIVATION_TOKEN");
|
||||||
if (!token.isEmpty()) {
|
if (!token.isEmpty()) {
|
||||||
g_variant_builder_add(
|
builder.add_value(
|
||||||
builder,
|
GLib::Variant::new_dict_entry(
|
||||||
"{sv}",
|
GLib::Variant::new_string("activation-token"),
|
||||||
"activation-token",
|
GLib::Variant::new_variant(
|
||||||
g_variant_new_string(token.constData()));
|
GLib::Variant::new_string(token.toStdString()))));
|
||||||
qunsetenv("XDG_ACTIVATION_TOKEN");
|
qunsetenv("XDG_ACTIVATION_TOKEN");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Application::Application()
|
||||||
|
: Gio::impl::ApplicationImpl(this) {
|
||||||
|
const auto appId = QGuiApplication::desktopFileName().toStdString();
|
||||||
|
if (Gio::Application::id_is_valid(appId)) {
|
||||||
|
set_application_id(appId);
|
||||||
|
}
|
||||||
|
set_flags(Gio::ApplicationFlags::HANDLES_OPEN_);
|
||||||
|
|
||||||
|
auto actionMap = Gio::ActionMap(*this);
|
||||||
|
|
||||||
|
auto quitAction = Gio::SimpleAction::new_("quit");
|
||||||
|
quitAction.signal_activate().connect([](
|
||||||
|
Gio::SimpleAction,
|
||||||
|
GLib::Variant parameter) {
|
||||||
|
Core::Sandbox::Instance().customEnterFromEventLoop([] {
|
||||||
|
Core::Quit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
actionMap.add_action(quitAction);
|
||||||
|
|
||||||
|
using Window::Notifications::Manager;
|
||||||
|
using NotificationId = Manager::NotificationId;
|
||||||
|
using NotificationIdTuple = std::invoke_result_t<
|
||||||
|
decltype(&NotificationId::toTuple),
|
||||||
|
NotificationId*
|
||||||
|
>;
|
||||||
|
|
||||||
|
const auto notificationIdVariantType = [] {
|
||||||
|
try {
|
||||||
|
return gi::wrap(
|
||||||
|
Glib::create_variant(
|
||||||
|
NotificationId().toTuple()
|
||||||
|
).get_type().gobj_copy(),
|
||||||
|
gi::transfer_full,
|
||||||
|
gi::direction_out
|
||||||
|
);
|
||||||
|
} catch (...) {
|
||||||
|
return GLib::VariantType();
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
auto notificationActivateAction = Gio::SimpleAction::new_(
|
||||||
|
"notification-activate",
|
||||||
|
notificationIdVariantType);
|
||||||
|
|
||||||
|
notificationActivateAction.signal_activate().connect([](
|
||||||
|
Gio::SimpleAction,
|
||||||
|
GLib::Variant parameter) {
|
||||||
|
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
|
try {
|
||||||
|
const auto &app = Core::App();
|
||||||
|
app.notifications().manager().notificationActivated(
|
||||||
|
NotificationId::FromTuple(
|
||||||
|
Glib::wrap(
|
||||||
|
parameter.gobj_copy_()
|
||||||
|
).get_dynamic<NotificationIdTuple>()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
actionMap.add_action(notificationActivateAction);
|
||||||
|
|
||||||
|
auto notificationMarkAsReadAction = Gio::SimpleAction::new_(
|
||||||
|
"notification-mark-as-read",
|
||||||
|
notificationIdVariantType);
|
||||||
|
|
||||||
|
notificationMarkAsReadAction.signal_activate().connect([](
|
||||||
|
Gio::SimpleAction,
|
||||||
|
GLib::Variant parameter) {
|
||||||
|
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
|
try {
|
||||||
|
const auto &app = Core::App();
|
||||||
|
app.notifications().manager().notificationReplied(
|
||||||
|
NotificationId::FromTuple(
|
||||||
|
Glib::wrap(
|
||||||
|
parameter.gobj_copy_()
|
||||||
|
).get_dynamic<NotificationIdTuple>()
|
||||||
|
),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
actionMap.add_action(notificationMarkAsReadAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void t_desktop_application_init(TDesktopApplication *application) {
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Platform {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
using namespace gi::repository;
|
|
||||||
namespace Gio = gi::repository::Gio;
|
|
||||||
|
|
||||||
class LinuxIntegration final : public Integration {
|
class LinuxIntegration final : public Integration {
|
||||||
public:
|
public:
|
||||||
LinuxIntegration();
|
LinuxIntegration();
|
||||||
|
@ -103,8 +201,6 @@ private:
|
||||||
|
|
||||||
void initInhibit();
|
void initInhibit();
|
||||||
|
|
||||||
static void LaunchNativeApplication();
|
|
||||||
|
|
||||||
XdpInhibit::InhibitProxy _inhibitProxy;
|
XdpInhibit::InhibitProxy _inhibitProxy;
|
||||||
base::Platform::XDP::SettingWatcher _darkModeWatcher;
|
base::Platform::XDP::SettingWatcher _darkModeWatcher;
|
||||||
};
|
};
|
||||||
|
@ -146,8 +242,8 @@ LinuxIntegration::LinuxIntegration()
|
||||||
void LinuxIntegration::init() {
|
void LinuxIntegration::init() {
|
||||||
initInhibit();
|
initInhibit();
|
||||||
|
|
||||||
Glib::signal_idle().connect_once([] {
|
GLib::idle_add_once([] {
|
||||||
LaunchNativeApplication();
|
gi::make_ref<Application>()->run(0, nullptr);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,115 +303,6 @@ void LinuxIntegration::initInhibit() {
|
||||||
nullptr);
|
nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinuxIntegration::LaunchNativeApplication() {
|
|
||||||
const auto appId = QGuiApplication::desktopFileName().toStdString();
|
|
||||||
|
|
||||||
const auto app = Glib::wrap(
|
|
||||||
G_APPLICATION(
|
|
||||||
g_object_new(
|
|
||||||
t_desktop_application_get_type(),
|
|
||||||
"application-id",
|
|
||||||
::Gio::Application::id_is_valid(appId)
|
|
||||||
? appId.c_str()
|
|
||||||
: nullptr,
|
|
||||||
"flags",
|
|
||||||
G_APPLICATION_HANDLES_OPEN,
|
|
||||||
nullptr)));
|
|
||||||
|
|
||||||
app->signal_startup().connect([weak = std::weak_ptr(app)] {
|
|
||||||
const auto app = weak.lock();
|
|
||||||
if (!app) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GNotification
|
|
||||||
InvokeQueued(qApp, [] {
|
|
||||||
Core::App().notifications().createManager();
|
|
||||||
});
|
|
||||||
|
|
||||||
QEventLoop().exec();
|
|
||||||
app->quit();
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
app->signal_activate().connect([] {
|
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([] {
|
|
||||||
Core::App().activate();
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
app->signal_open().connect([](
|
|
||||||
const ::Gio::Application::type_vec_files &files,
|
|
||||||
const Glib::ustring &hint) {
|
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
|
||||||
for (const auto &file : files) {
|
|
||||||
QFileOpenEvent e(
|
|
||||||
QUrl(QString::fromStdString(file->get_uri())));
|
|
||||||
QGuiApplication::sendEvent(qApp, &e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
app->add_action("quit", [] {
|
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([] {
|
|
||||||
Core::Quit();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
using Window::Notifications::Manager;
|
|
||||||
using NotificationId = Manager::NotificationId;
|
|
||||||
using NotificationIdTuple = std::invoke_result_t<
|
|
||||||
decltype(&NotificationId::toTuple),
|
|
||||||
NotificationId*
|
|
||||||
>;
|
|
||||||
|
|
||||||
const auto notificationIdVariantType = [] {
|
|
||||||
try {
|
|
||||||
return Glib::create_variant(
|
|
||||||
NotificationId().toTuple()
|
|
||||||
).get_type();
|
|
||||||
} catch (...) {
|
|
||||||
return Glib::VariantType();
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
|
|
||||||
app->add_action_with_parameter(
|
|
||||||
"notification-activate",
|
|
||||||
notificationIdVariantType,
|
|
||||||
[](const Glib::VariantBase ¶meter) {
|
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
|
||||||
try {
|
|
||||||
const auto &app = Core::App();
|
|
||||||
app.notifications().manager().notificationActivated(
|
|
||||||
NotificationId::FromTuple(
|
|
||||||
parameter.get_dynamic<NotificationIdTuple>()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app->add_action_with_parameter(
|
|
||||||
"notification-mark-as-read",
|
|
||||||
notificationIdVariantType,
|
|
||||||
[](const Glib::VariantBase ¶meter) {
|
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
|
||||||
try {
|
|
||||||
const auto &app = Core::App();
|
|
||||||
app.notifications().manager().notificationReplied(
|
|
||||||
NotificationId::FromTuple(
|
|
||||||
parameter.get_dynamic<NotificationIdTuple>()
|
|
||||||
),
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app->run(0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::unique_ptr<Integration> CreateIntegration() {
|
std::unique_ptr<Integration> CreateIntegration() {
|
||||||
|
|
|
@ -40,9 +40,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
|
|
||||||
#if __has_include(<giomm.h>)
|
#if __has_include(<gio/gio.hpp>)
|
||||||
#include <giomm.h>
|
#include <gio/gio.hpp>
|
||||||
#endif // __has_include(<giomm.h>)
|
#endif // __has_include(<gio/gio.hpp>)
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace Notifications {
|
namespace Notifications {
|
||||||
|
@ -90,11 +90,12 @@ base::options::toggle OptionGNotification({
|
||||||
.description = "Force enable GLib's GNotification."
|
.description = "Force enable GLib's GNotification."
|
||||||
" When disabled, autodetect is used.",
|
" When disabled, autodetect is used.",
|
||||||
.scope = [] {
|
.scope = [] {
|
||||||
#if __has_include(<giomm.h>)
|
#if __has_include(<gio/gio.hpp>)
|
||||||
|
using namespace gi::repository;
|
||||||
return bool(Gio::Application::get_default());
|
return bool(Gio::Application::get_default());
|
||||||
#else // __has_include(<giomm.h>)
|
#else // __has_include(<gio/gio.hpp>)
|
||||||
return false;
|
return false;
|
||||||
#endif // __has_include(<giomm.h>)
|
#endif // __has_include(<gio/gio.hpp>)
|
||||||
},
|
},
|
||||||
.restartRequired = true,
|
.restartRequired = true,
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue