summaryrefslogtreecommitdiffstats
path: root/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp
diff options
context:
space:
mode:
authorIlya Fedin <fedin-ilja2010@ya.ru>2021-08-25 10:03:05 +0400
committerJohn Preston <johnprestonmail@gmail.com>2021-08-25 12:52:43 +0300
commit51df4825718914019e2c59bd07ecc4dc91634806 (patch)
treef8bb7adefa753d93fb182298ca3d7954ef7f3227 /Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp
parent2694cb76a761232f88c0ac97cd4abb4636e8754f (diff)
Get rid of gtk open with dialog
Portal open with dialog works just fine and is a more universal solution... That allows to get rid of an additional process.
Diffstat (limited to 'Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp')
-rw-r--r--Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp389
1 files changed, 8 insertions, 381 deletions
diff --git a/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp b/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp
index 4cac96d1d1..f771d8c425 100644
--- a/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp
+++ b/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp
@@ -12,16 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#endif // DESKTOP_APP_DISABLE_DBUS_INTEGRATION
#include "base/platform/linux/base_linux_gtk_integration.h"
-#include "base/platform/linux/base_linux_gtk_integration_p.h"
-#include "base/platform/linux/base_linux_glibmm_helper.h"
#include "base/platform/linux/base_linux_dbus_utilities.h"
#include "base/platform/base_platform_info.h"
-#include "platform/linux/linux_gtk_integration_p.h"
-#include "platform/linux/linux_gdk_helper.h"
-#include "platform/linux/linux_gtk_open_with_dialog.h"
-#include "platform/linux/linux_wayland_integration.h"
-#include "window/window_controller.h"
-#include "core/application.h"
#ifndef DESKTOP_APP_DISABLE_WEBKITGTK
#include "webview/platform/linux/webview_linux_webkit2gtk.h"
@@ -29,362 +21,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QProcess>
-#include <private/qguiapplication_p.h>
#include <giomm.h>
namespace Platform {
namespace internal {
-
-using namespace Platform::Gtk;
-using BaseGtkIntegration = base::Platform::GtkIntegration;
-
namespace {
-constexpr auto kService = "org.telegram.desktop.GtkIntegration-%1"_cs;
constexpr auto kBaseService = "org.telegram.desktop.BaseGtkIntegration-%1"_cs;
constexpr auto kWebviewService = "org.telegram.desktop.GtkIntegration.WebviewHelper-%1-%2"_cs;
-constexpr auto kObjectPath = "/org/telegram/desktop/GtkIntegration"_cs;
-constexpr auto kInterface = "org.telegram.desktop.GtkIntegration"_cs;
-
-constexpr auto kIntrospectionXML = R"INTROSPECTION(<node>
- <interface name='org.telegram.desktop.GtkIntegration'>
- <method name='Load'>
- <arg type='s' name='allowed-backends' direction='in'/>
- </method>
- <method name='ShowOpenWithDialog'>
- <arg type='s' name='parent' direction='in'/>
- <arg type='s' name='filepath' direction='in'/>
- </method>
- <signal name='OpenWithDialogResponse'>
- <arg type='b' name='result' direction='out'/>
- </signal>
- </interface>
-</node>)INTROSPECTION"_cs;
-Glib::ustring ServiceName;
+using BaseGtkIntegration = base::Platform::GtkIntegration;
} // namespace
-class GtkIntegration::Private {
-public:
- Private()
- : dbusConnection([] {
- try {
- return Gio::DBus::Connection::get_sync(
- Gio::DBus::BusType::BUS_TYPE_SESSION);
- } catch (...) {
- return Glib::RefPtr<Gio::DBus::Connection>();
- }
- }())
- , interfaceVTable(sigc::mem_fun(this, &Private::handleMethodCall)) {
- }
-
- void handleMethodCall(
- const Glib::RefPtr<Gio::DBus::Connection> &connection,
- const Glib::ustring &sender,
- const Glib::ustring &object_path,
- const Glib::ustring &interface_name,
- const Glib::ustring &method_name,
- const Glib::VariantContainerBase &parameters,
- const Glib::RefPtr<Gio::DBus::MethodInvocation> &invocation);
-
- const Glib::RefPtr<Gio::DBus::Connection> dbusConnection;
- const Gio::DBus::InterfaceVTable interfaceVTable;
- Glib::RefPtr<Gio::DBus::NodeInfo> introspectionData;
- Glib::ustring parentDBusName;
- bool remoting = true;
- uint registerId = 0;
- uint parentServiceWatcherId = 0;
-};
-
-void GtkIntegration::Private::handleMethodCall(
- const Glib::RefPtr<Gio::DBus::Connection> &connection,
- const Glib::ustring &sender,
- const Glib::ustring &object_path,
- const Glib::ustring &interface_name,
- const Glib::ustring &method_name,
- const Glib::VariantContainerBase &parameters,
- const Glib::RefPtr<Gio::DBus::MethodInvocation> &invocation) {
- if (sender != parentDBusName) {
- Gio::DBus::Error error(
- Gio::DBus::Error::ACCESS_DENIED,
- "Access denied.");
-
- invocation->return_error(error);
- return;
- }
-
- try {
- const auto integration = Instance();
- if (!integration) {
- throw std::exception();
- }
-
- auto parametersCopy = parameters;
-
- if (method_name == "Load") {
- const auto allowedBackends = base::Platform::GlibVariantCast<
- Glib::ustring>(parametersCopy.get_child(0));
-
- integration->load(QString::fromStdString(allowedBackends));
- invocation->return_value({});
- return;
- } else if (method_name == "ShowOpenWithDialog") {
- const auto parent = base::Platform::GlibVariantCast<
- Glib::ustring>(parametersCopy.get_child(0));
-
- const auto filepath = base::Platform::GlibVariantCast<
- Glib::ustring>(parametersCopy.get_child(1));
-
- const auto dialog = File::internal::CreateGtkOpenWithDialog(
- QString::fromStdString(parent),
- QString::fromStdString(filepath)).release();
-
- if (dialog) {
- dialog->response(
- ) | rpl::start_with_next([=](bool response) {
- try {
- connection->emit_signal(
- std::string(kObjectPath),
- std::string(kInterface),
- "OpenWithDialogResponse",
- parentDBusName,
- base::Platform::MakeGlibVariant(std::tuple{
- response,
- }));
- } catch (...) {
- }
-
- delete dialog;
- }, dialog->lifetime());
-
- invocation->return_value({});
- return;
- }
- }
- } catch (...) {
- }
-
- Gio::DBus::Error error(
- Gio::DBus::Error::UNKNOWN_METHOD,
- "Method does not exist.");
-
- invocation->return_error(error);
-}
-
-GtkIntegration::GtkIntegration()
-: _private(std::make_unique<Private>()) {
-}
-
-GtkIntegration::~GtkIntegration() {
- if (_private->dbusConnection) {
- if (_private->parentServiceWatcherId != 0) {
- _private->dbusConnection->signal_unsubscribe(
- _private->parentServiceWatcherId);
- }
-
- if (_private->registerId != 0) {
- _private->dbusConnection->unregister_object(
- _private->registerId);
- }
- }
-}
-
-GtkIntegration *GtkIntegration::Instance() {
- if (!BaseGtkIntegration::Instance()) {
- return nullptr;
- }
-
- static GtkIntegration instance;
- return &instance;
-}
-
-void GtkIntegration::load(const QString &allowedBackends) {
- static bool Loaded = false;
- Expects(!Loaded);
-
- if (_private->remoting) {
- if (!_private->dbusConnection) {
- return;
- }
-
- try {
- auto reply = _private->dbusConnection->call_sync(
- std::string(kObjectPath),
- std::string(kInterface),
- "Load",
- base::Platform::MakeGlibVariant(std::tuple{
- Glib::ustring(allowedBackends.toStdString()),
- }),
- ServiceName);
- } catch (...) {
- }
-
- return;
- }
-
- BaseGtkIntegration::Instance()->load(allowedBackends, true);
- if (!BaseGtkIntegration::Instance()->loaded()) {
- return;
- }
-
- auto &lib = BaseGtkIntegration::Instance()->library();
-
- LOAD_GTK_SYMBOL(lib, gtk_widget_show);
- LOAD_GTK_SYMBOL(lib, gtk_widget_get_window);
- LOAD_GTK_SYMBOL(lib, gtk_widget_realize);
- LOAD_GTK_SYMBOL(lib, gtk_widget_destroy);
-
- LOAD_GTK_SYMBOL(lib, gtk_app_chooser_dialog_new);
- LOAD_GTK_SYMBOL(lib, gtk_app_chooser_get_app_info);
- LOAD_GTK_SYMBOL(lib, gtk_app_chooser_get_type);
-
- GdkHelperLoad(lib);
- Loaded = true;
-}
-
-int GtkIntegration::exec(const QString &parentDBusName) {
- _private->remoting = false;
- _private->parentDBusName = parentDBusName.toStdString();
-
- _private->introspectionData = Gio::DBus::NodeInfo::create_for_xml(
- std::string(kIntrospectionXML));
-
- _private->registerId = _private->dbusConnection->register_object(
- std::string(kObjectPath),
- _private->introspectionData->lookup_interface(),
- _private->interfaceVTable);
-
- const auto app = Gio::Application::create(ServiceName);
- app->hold();
- _private->parentServiceWatcherId = base::Platform::DBus::RegisterServiceWatcher(
- _private->dbusConnection,
- parentDBusName.toStdString(),
- [=](
- const Glib::ustring &service,
- const Glib::ustring &oldOwner,
- const Glib::ustring &newOwner) {
- if (!newOwner.empty()) {
- return;
- }
- app->quit();
- });
- return app->run(0, nullptr);
-}
-
-bool GtkIntegration::showOpenWithDialog(const QString &filepath) const {
- const auto parent = [&] {
- if (const auto activeWindow = Core::App().activeWindow()) {
- if (const auto integration = WaylandIntegration::Instance()) {
- if (const auto handle = integration->nativeHandle(
- activeWindow->widget()->windowHandle())
- ; !handle.isEmpty()) {
- return qsl("wayland:") + handle;
- }
- } else if (Platform::IsX11()) {
- return qsl("x11:") + QString::number(
- activeWindow->widget()->winId(),
- 16);
- }
- }
- return QString();
- }();
-
- if (_private->remoting) {
- if (!_private->dbusConnection) {
- return false;
- }
-
- try {
- _private->dbusConnection->call_sync(
- std::string(kObjectPath),
- std::string(kInterface),
- "ShowOpenWithDialog",
- base::Platform::MakeGlibVariant(std::tuple{
- Glib::ustring(parent.toStdString()),
- Glib::ustring(filepath.toStdString()),
- }),
- ServiceName);
-
- const auto context = Glib::MainContext::create();
- const auto loop = Glib::MainLoop::create(context);
- g_main_context_push_thread_default(context->gobj());
- const auto contextGuard = gsl::finally([&] {
- g_main_context_pop_thread_default(context->gobj());
- });
- bool result = false;
-
- const auto signalId = _private->dbusConnection->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,
- Glib::VariantContainerBase parameters) {
- try {
- auto parametersCopy = parameters;
-
- result = base::Platform::GlibVariantCast<bool>(
- parametersCopy.get_child(0));
-
- loop->quit();
- } catch (...) {
- }
- },
- ServiceName,
- std::string(kInterface),
- "OpenWithDialogResponse",
- std::string(kObjectPath));
-
- const auto signalGuard = gsl::finally([&] {
- if (signalId != 0) {
- _private->dbusConnection->signal_unsubscribe(signalId);
- }
- });
-
- if (signalId != 0) {
- QWindow window;
- QGuiApplicationPrivate::showModalWindow(&window);
- loop->run();
- QGuiApplicationPrivate::hideModalWindow(&window);
- }
-
- return result;
- } catch (...) {
- }
-
- return false;
- }
-
- const auto dialog = File::internal::CreateGtkOpenWithDialog(
- parent,
- filepath);
-
- if (!dialog) {
- return false;
- }
-
- const auto context = Glib::MainContext::create();
- const auto loop = Glib::MainLoop::create(context);
- g_main_context_push_thread_default(context->gobj());
- bool result = false;
-
- dialog->response(
- ) | rpl::start_with_next([&](bool response) {
- result = response;
- loop->quit();
- }, dialog->lifetime());
-
- QWindow window;
- QGuiApplicationPrivate::showModalWindow(&window);
- loop->run();
- g_main_context_pop_thread_default(context->gobj());
- QGuiApplicationPrivate::hideModalWindow(&window);
-
- return result;
-}
-
QString GtkIntegration::AllowedBackends() {
return Platform::IsWayland()
? qsl("wayland,x11")
@@ -410,11 +59,6 @@ int GtkIntegration::Exec(
Webview::WebKit2Gtk::SetServiceName(serviceName.toStdString());
return Webview::WebKit2Gtk::Exec(parentDBusName.toStdString());
#endif // !DESKTOP_APP_DISABLE_WEBKITGTK
- } else if (type == Type::TDesktop) {
- ServiceName = serviceName.toStdString();
- if (const auto integration = Instance()) {
- return integration->exec(parentDBusName);
- }
}
return 1;
@@ -422,8 +66,7 @@ int GtkIntegration::Exec(
void GtkIntegration::Start(Type type) {
if (type != Type::Base
- && type != Type::Webview
- && type != Type::TDesktop) {
+ && type != Type::Webview) {
return;
}
@@ -440,8 +83,6 @@ void GtkIntegration::Start(Type type) {
#endif // !DESKTOP_APP_DISABLE_WEBKITGTK
return;
- } else {
- ServiceName = kService.utf16().arg(h).toStdString();
}
const auto dbusName = [] {
@@ -460,18 +101,14 @@ void GtkIntegration::Start(Type type) {
}
QProcess::startDetached(cExeDir() + cExeName(), {
- (type == Type::Base)
- ? qsl("-basegtkintegration")
- : qsl("-gtkintegration"),
+ qsl("-basegtkintegration"),
dbusName,
- (type == Type::Base)
- ? kBaseService.utf16().arg(h)
- : kService.utf16().arg(h),
+ kBaseService.utf16().arg(h),
});
}
void GtkIntegration::Autorestart(Type type) {
- if (type != Type::Base && type != Type::TDesktop) {
+ if (type != Type::Base) {
return;
}
@@ -481,25 +118,15 @@ void GtkIntegration::Autorestart(Type type) {
base::Platform::DBus::RegisterServiceWatcher(
connection,
- (type == Type::Base)
- ? Glib::ustring(BaseGtkIntegration::ServiceName().toStdString())
- : ServiceName,
+ Glib::ustring(BaseGtkIntegration::ServiceName().toStdString()),
[=](
const Glib::ustring &service,
const Glib::ustring &oldOwner,
const Glib::ustring &newOwner) {
if (newOwner.empty()) {
Start(type);
- } else {
- if (type == Type::Base) {
- if (const auto integration = BaseGtkIntegration::Instance()) {
- integration->load(AllowedBackends());
- }
- } else if (type == Type::TDesktop) {
- if (const auto integration = Instance()) {
- integration->load(AllowedBackends());
- }
- }
+ } else if (const auto integration = BaseGtkIntegration::Instance()) {
+ integration->load(AllowedBackends());
}
});
} catch (...) {