diff --git a/Telegram/SourceFiles/platform/linux/integration_linux.cpp b/Telegram/SourceFiles/platform/linux/integration_linux.cpp index e501ce93b..d69e06030 100644 --- a/Telegram/SourceFiles/platform/linux/integration_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/integration_linux.cpp @@ -8,20 +8,89 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/linux/integration_linux.h" #include "platform/platform_integration.h" +#include "base/platform/base_platform_info.h" #include "base/platform/linux/base_linux_glibmm_helper.h" #include "base/platform/linux/base_linux_xdp_utilities.h" +#include "core/sandbox.h" #include "core/application.h" #include "core/core_settings.h" #include "base/random.h" -#include -#include +#include -using namespace gi::repository; +#include +#include + +typedef GApplication TDesktopApplication; +typedef GApplicationClass TDesktopApplicationClass; + +G_DEFINE_TYPE( + TDesktopApplication, + t_desktop_application, + G_TYPE_APPLICATION) + +static void t_desktop_application_class_init( + TDesktopApplicationClass *klass) { + const auto application_class = G_APPLICATION_CLASS(klass); + + application_class->local_command_line = []( + 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()) { + static const auto keys = { + "activation-token", + "desktop-startup-id", + }; + for (const auto &key : keys) { + const char *token = nullptr; + g_variant_lookup(platformData, key, "&s", &token); + if (token) { + qputenv("XDG_ACTIVATION_TOKEN", token); + break; + } + } + } + }; + + application_class->add_platform_data = []( + GApplication *application, + GVariantBuilder *builder) { + if (Platform::IsWayland()) { + const auto token = qgetenv("XDG_ACTIVATION_TOKEN"); + if (!token.isEmpty()) { + g_variant_builder_add( + builder, + "{sv}", + "activation-token", + g_variant_new_string(token.constData())); + qunsetenv("XDG_ACTIVATION_TOKEN"); + } + } + }; +} + +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 { public: LinuxIntegration(); @@ -33,6 +102,10 @@ private: return _inhibitProxy; } + void initInhibit(); + + static void LaunchNativeApplication(); + XdpInhibit::InhibitProxy _inhibitProxy; base::Platform::XDP::SettingWatcher _darkModeWatcher; }; @@ -61,9 +134,25 @@ LinuxIntegration::LinuxIntegration() } } }) { + LOG(("Icon theme: %1").arg(QIcon::themeName())); + LOG(("Fallback icon theme: %1").arg(QIcon::fallbackThemeName())); + + if (!QCoreApplication::eventDispatcher()->inherits( + "QEventDispatcherGlib")) { + g_warning("Qt is running without GLib event loop integration, " + "except various functionality to not to work."); + } } void LinuxIntegration::init() { + initInhibit(); + + Glib::signal_idle().connect_once([] { + LaunchNativeApplication(); + }); +} + +void LinuxIntegration::initInhibit() { if (!_inhibitProxy) { return; } @@ -119,6 +208,111 @@ void LinuxIntegration::init() { nullptr); } +void LinuxIntegration::LaunchNativeApplication() { + const auto appId = QGuiApplication::desktopFileName() + .chopped(8) + .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([=] { + // 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 base::Platform::MakeGlibVariant( + 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( + base::Platform::GlibVariantCast< + NotificationIdTuple + >(parameter))); + } 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( + base::Platform::GlibVariantCast< + NotificationIdTuple + >(parameter)), + {}); + } catch (...) { + } + }); + }); + + app->run(0, nullptr); +} + } // namespace std::unique_ptr CreateIntegration() { diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 1ab7a8d54..5ecf4229a 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/linux/specific_linux.h" #include "base/random.h" -#include "base/options.h" #include "base/platform/base_platform_info.h" #include "base/platform/linux/base_linux_glibmm_helper.h" #include "base/platform/linux/base_linux_dbus_utilities.h" @@ -19,9 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwindow.h" #include "storage/localstorage.h" #include "core/launcher.h" -#include "core/sandbox.h" #include "core/application.h" -#include "core/local_url_handlers.h" #include "core/core_settings.h" #include "core/update_checker.h" #include "window/window_controller.h" @@ -35,7 +32,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include -#include #include #include @@ -56,57 +52,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL using namespace Platform; using Platform::internal::WaylandIntegration; -typedef GApplication TDesktopApplication; -typedef GApplicationClass TDesktopApplicationClass; - -G_DEFINE_TYPE( - TDesktopApplication, - t_desktop_application, - G_TYPE_APPLICATION) - -static void t_desktop_application_class_init( - TDesktopApplicationClass *klass) { - const auto application_class = G_APPLICATION_CLASS(klass); - - application_class->before_emit = []( - GApplication *application, - GVariant *platformData) { - if (Platform::IsWayland()) { - static const auto keys = { - "activation-token", - "desktop-startup-id", - }; - for (const auto &key : keys) { - const char *token = nullptr; - g_variant_lookup(platformData, key, "&s", &token); - if (token) { - qputenv("XDG_ACTIVATION_TOKEN", token); - break; - } - } - } - }; - - application_class->add_platform_data = []( - GApplication *application, - GVariantBuilder *builder) { - if (Platform::IsWayland()) { - const auto token = qgetenv("XDG_ACTIVATION_TOKEN"); - if (!token.isEmpty()) { - g_variant_builder_add( - builder, - "{sv}", - "activation-token", - g_variant_new_string(token.constData())); - qunsetenv("XDG_ACTIVATION_TOKEN"); - } - } - }; -} - -static void t_desktop_application_init(TDesktopApplication *application) { -} - namespace Platform { namespace { @@ -232,115 +177,6 @@ bool PortalAutostart(bool start, bool silent) { return !error; } -void LaunchGApplication() { - Glib::signal_idle().connect_once([] { - const auto appId = QGuiApplication::desktopFileName() - .chopped(8) - .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([=] { - // GNotification - InvokeQueued(qApp, [] { - Core::App().notifications().createManager(); - }); - - QEventLoop().exec(); - app->quit(); - }, true); - - app->signal_activate().connect([] { - Core::Sandbox::Instance().customEnterFromEventLoop([] { - if (Core::IsAppLaunched()) { - 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 base::Platform::MakeGlibVariant( - 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( - base::Platform::GlibVariantCast< - NotificationIdTuple - >(parameter))); - } 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( - base::Platform::GlibVariantCast< - NotificationIdTuple - >(parameter)), - {}); - } catch (...) { - } - }); - }); - - app->run(0, nullptr); - }); -} - bool GenerateDesktopFile( const QString &targetPath, const QStringList &args = {}, @@ -798,16 +634,6 @@ QImage DefaultApplicationIcon() { namespace ThirdParty { void start() { - LOG(("Icon theme: %1").arg(QIcon::themeName())); - LOG(("Fallback icon theme: %1").arg(QIcon::fallbackThemeName())); - - if (!QCoreApplication::eventDispatcher()->inherits( - "QEventDispatcherGlib")) { - g_warning("Qt is running without GLib event loop integration, " - "except various functionality to not to work."); - } - - LaunchGApplication(); } void finish() {