Get GApplication out of experimental settings

GApplication will always be used on Linux now. GNotification gets a toggle instead.
This commit is contained in:
Ilya Fedin 2023-01-12 21:06:32 +04:00 committed by John Preston
parent 241be89e5c
commit 9b7826ea0d
8 changed files with 161 additions and 232 deletions

View file

@ -1137,7 +1137,6 @@ PRIVATE
platform/platform_integration.h
platform/platform_main_window.h
platform/platform_notifications_manager.h
platform/platform_specific.cpp
platform/platform_specific.h
platform/platform_tray.h
platform/platform_window_title.h

View file

@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#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"
#include "platform/platform_specific.h"
#include "core/application.h"
#include "core/sandbox.h"
#include "core/core_settings.h"
@ -319,6 +318,18 @@ Glib::ustring GetImageKey(const QVersionNumber &specificationVersion) {
return "icon_data";
}
bool UseGNotification() {
if (!Gio::Application::get_default()) {
return false;
}
if (Window::Notifications::OptionGNotification.value()) {
return true;
}
return KSandbox::isFlatpak() && !ServiceRegistered;
}
class NotificationData final : public base::has_weak_ptr {
public:
using NotificationId = Window::Notifications::Manager::NotificationId;
@ -378,7 +389,7 @@ NotificationData::NotificationData(
NotificationId id)
: _manager(manager)
, _id(id)
, _application(Gio::Application::get_default()) {
, _application(UseGNotification() ? Gio::Application::get_default() : {}) {
}
bool NotificationData::init(
@ -811,13 +822,13 @@ bool WaitForInputForCustom() {
}
bool Supported() {
return ServiceRegistered || Gio::Application::get_default();
return ServiceRegistered || UseGNotification();
}
bool Enforced() {
// Wayland doesn't support positioning
// and custom notifications don't work here
return IsWayland() || OptionGApplication.value();
return IsWayland() || Window::Notifications::OptionGNotification.value();
}
bool ByDefault() {
@ -841,7 +852,7 @@ bool ByDefault() {
}
void Create(Window::Notifications::System *system) {
static auto ServiceWatcher = CreateServiceWatcher();
static const auto ServiceWatcher = CreateServiceWatcher();
const auto managerSetter = [=] {
using ManagerType = Window::Notifications::ManagerType;
@ -860,35 +871,15 @@ void Create(Window::Notifications::System *system) {
}
};
if (Gio::Application::get_default()) {
ServiceWatcher = nullptr;
ServiceRegistered = false;
CurrentServerInformation = std::nullopt;
CurrentCapabilities = QStringList{};
managerSetter();
return;
}
const auto counter = std::make_shared<int>(2);
const auto oneReady = [=] {
if (!--*counter) {
// GApplication may be created while the reply is received
if (Gio::Application::get_default()) {
Core::App().notifications().createManager();
return;
}
managerSetter();
}
};
// snap doesn't allow access when the daemon is not running :(
StartServiceAsync([=] {
// GApplication may be created while the reply is received
if (Gio::Application::get_default()) {
Core::App().notifications().createManager();
return;
}
ServiceRegistered = GetServiceRegistered();
if (!ServiceRegistered) {

View file

@ -240,187 +240,140 @@ bool PortalAutostart(bool start, bool silent) {
}
void LaunchGApplication() {
const auto connection = [] {
try {
return Gio::DBus::Connection::get_sync(
Gio::DBus::BusType::SESSION);
} catch (...) {
return Glib::RefPtr<Gio::DBus::Connection>();
}
}();
Glib::signal_idle().connect_once([] {
const auto appId = QGuiApplication::desktopFileName()
.chopped(8)
.toStdString();
using namespace base::Platform::DBus;
const auto activatableNames = [&] {
try {
if (connection) {
return ListActivatableNames(connection);
}
} catch (...) {
}
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)));
return std::vector<Glib::ustring>();
}();
app->signal_startup().connect([=] {
// GNotification
InvokeQueued(qApp, [] {
Core::App().notifications().createManager();
});
const auto freedesktopNotifications = [&] {
try {
if (connection && NameHasOwner(
connection,
"org.freedesktop.Notifications")) {
return true;
}
} catch (...) {
}
QEventLoop().exec();
app->quit();
}, true);
if (ranges::contains(
activatableNames,
"org.freedesktop.Notifications",
&Glib::ustring::raw)) {
return true;
}
app->signal_activate().connect([] {
Core::Sandbox::Instance().customEnterFromEventLoop([] {
const auto window = Core::IsAppLaunched()
? Core::App().primaryWindow()
: nullptr;
if (window) {
window->activate();
}
});
}, true);
return false;
};
if (OptionGApplication.value()
|| (KSandbox::isFlatpak() && !freedesktopNotifications())) {
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([] {
const auto window = Core::IsAppLaunched()
? Core::App().primaryWindow()
: nullptr;
if (window) {
window->activate();
app->signal_open().connect([](
const Gio::Application::type_vec_files &files,
const Glib::ustring &hint) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
for (const auto &file : files) {
if (file->get_uri_scheme() == "file") {
gSendPaths.append(
QString::fromStdString(file->get_path()));
continue;
}
});
}, true);
const auto url = QString::fromStdString(file->get_uri());
if (url.isEmpty()) {
continue;
}
if (url.startsWith(qstr("interpret://"))) {
gSendPaths.append(url);
continue;
}
if (Core::StartUrlRequiresActivate(url)) {
const auto window = Core::IsAppLaunched()
? Core::App().primaryWindow()
: nullptr;
if (window) {
window->activate();
}
}
cSetStartUrl(url);
Core::App().checkStartUrl();
}
app->signal_open().connect([](
const Gio::Application::type_vec_files &files,
const Glib::ustring &hint) {
if (!cSendPaths().isEmpty()) {
Core::App().checkSendPaths();
}
});
}, 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-reply",
notificationIdVariantType,
[](const Glib::VariantBase &parameter) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
for (const auto &file : files) {
if (file->get_uri_scheme() == "file") {
gSendPaths.append(
QString::fromStdString(file->get_path()));
continue;
}
const auto url = QString::fromStdString(
file->get_uri());
if (url.isEmpty()) {
continue;
}
if (url.startsWith(qstr("interpret://"))) {
gSendPaths.append(url);
continue;
}
if (Core::StartUrlRequiresActivate(url)) {
const auto window = Core::IsAppLaunched()
? Core::App().primaryWindow()
: nullptr;
if (window) {
window->activate();
}
}
cSetStartUrl(url);
Core::App().checkStartUrl();
try {
const auto &app = Core::App();
app.notifications().manager().notificationActivated(
NotificationId::FromTuple(
base::Platform::GlibVariantCast<
NotificationIdTuple
>(parameter)));
} catch (...) {
}
if (!cSendPaths().isEmpty()) {
Core::App().checkSendPaths();
}
});
}, 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-reply",
notificationIdVariantType,
[](const Glib::VariantBase &parameter) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
try {
const auto &app = Core::App();
const auto &notifications = app.notifications();
notifications.manager().notificationActivated(
NotificationId::FromTuple(
base::Platform::GlibVariantCast<
NotificationIdTuple
>(parameter)));
} catch (...) {
}
});
app->add_action_with_parameter(
"notification-mark-as-read",
notificationIdVariantType,
[](const Glib::VariantBase &parameter) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
try {
const auto &app = Core::App();
app.notifications().manager().notificationReplied(
NotificationId::FromTuple(
base::Platform::GlibVariantCast<
NotificationIdTuple
>(parameter)),
{});
} catch (...) {
}
});
});
app->add_action_with_parameter(
"notification-mark-as-read",
notificationIdVariantType,
[](const Glib::VariantBase &parameter) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
try {
const auto &app = Core::App();
const auto &notifications = app.notifications();
notifications.manager().notificationReplied(
NotificationId::FromTuple(
base::Platform::GlibVariantCast<
NotificationIdTuple
>(parameter)),
{});
} catch (...) {
}
});
});
app->hold();
app->run(0, nullptr);
});
}
app->hold();
app->run(0, nullptr);
});
}
bool GenerateDesktopFile(

View file

@ -1,25 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "platform/platform_specific.h"
#include "base/options.h"
namespace Platform {
const char kOptionGApplication[] = "gapplication";
base::options::toggle OptionGApplication({
.id = kOptionGApplication,
.name = "GApplication",
.description = "Force enable GLib's GApplication and GNotification."
" When disabled, autodetect is used.",
.scope = base::options::linux,
.restartRequired = true,
});
} // namespace Platform

View file

@ -7,20 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace base::options {
template <typename Type>
class option;
using toggle = option<bool>;
} // namespace base::options
namespace Platform {
extern const char kOptionGApplication[];
extern base::options::toggle OptionGApplication;
void start();
void finish();

View file

@ -17,7 +17,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/options.h"
#include "core/application.h"
#include "core/launcher.h"
#include "platform/platform_specific.h"
#include "chat_helpers/tabbed_panel.h"
#include "dialogs/dialogs_inner_widget.h"
#include "lang/lang_keys.h"
@ -27,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_peer_menu.h"
#include "window/window_session_controller.h"
#include "window/window_controller.h"
#include "window/notifications_manager.h"
#include "settings/settings_common.h"
#include "storage/localimageloader.h"
#include "styles/style_settings.h"
@ -148,7 +148,7 @@ void SetupExperimental(
addToggle(Settings::kOptionMonoSettingsIcons);
addToggle(Webview::kOptionWebviewDebugEnabled);
addToggle(kOptionAutoScrollInactiveChat);
addToggle(Platform::kOptionGApplication);
addToggle(Windows::Notifications::kOptionGNotification);
}
} // namespace

View file

@ -77,6 +77,17 @@ QString TextWithPermanentSpoiler(const TextWithEntities &textWithEntities) {
} // namespace
const char kOptionGNotification[] = "gnotification";
base::options::toggle OptionGNotification({
.id = kOptionGNotification,
.name = "GNotification",
.description = "Force enable GLib's GNotification."
" When disabled, autodetect is used.",
.scope = base::options::linux,
.restartRequired = true,
});
struct System::Waiter {
NotificationInHistoryKey key;
UserData *reactionSender = nullptr;

View file

@ -74,8 +74,20 @@ struct custom_is_fast_copy_type<Window::Notifications::ChangeType> : std::true_t
} // namespace base
namespace base::options {
template <typename Type>
class option;
using toggle = option<bool>;
} // namespace base::options
namespace Window::Notifications {
extern const char kOptionGNotification[];
extern base::options::toggle OptionGNotification;
class Manager;
class System final {