mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
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.
This commit is contained in:
parent
2694cb76a7
commit
51df482571
12 changed files with 8 additions and 838 deletions
|
@ -854,14 +854,9 @@ PRIVATE
|
|||
payments/payments_form.h
|
||||
platform/linux/linux_desktop_environment.cpp
|
||||
platform/linux/linux_desktop_environment.h
|
||||
platform/linux/linux_gdk_helper.cpp
|
||||
platform/linux/linux_gdk_helper.h
|
||||
platform/linux/linux_gtk_integration_dummy.cpp
|
||||
platform/linux/linux_gtk_integration_p.h
|
||||
platform/linux/linux_gtk_integration.cpp
|
||||
platform/linux/linux_gtk_integration.h
|
||||
platform/linux/linux_gtk_open_with_dialog.cpp
|
||||
platform/linux/linux_gtk_open_with_dialog.h
|
||||
platform/linux/linux_wayland_integration_dummy.cpp
|
||||
platform/linux/linux_wayland_integration.cpp
|
||||
platform/linux/linux_wayland_integration.h
|
||||
|
@ -1166,12 +1161,7 @@ endif()
|
|||
|
||||
if (DESKTOP_APP_DISABLE_GTK_INTEGRATION)
|
||||
remove_target_sources(Telegram ${src_loc}
|
||||
platform/linux/linux_gdk_helper.cpp
|
||||
platform/linux/linux_gdk_helper.h
|
||||
platform/linux/linux_gtk_integration_p.h
|
||||
platform/linux/linux_gtk_integration.cpp
|
||||
platform/linux/linux_gtk_open_with_dialog.cpp
|
||||
platform/linux/linux_gtk_open_with_dialog.h
|
||||
)
|
||||
else()
|
||||
remove_target_sources(Telegram ${src_loc}
|
||||
|
@ -1288,17 +1278,6 @@ else()
|
|||
desktop-app::external_kwayland
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT DESKTOP_APP_DISABLE_GTK_INTEGRATION)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_check_modules(GTK REQUIRED gtk+-3.0)
|
||||
target_include_directories(Telegram SYSTEM PRIVATE ${GTK_INCLUDE_DIRS})
|
||||
|
||||
if (NOT DESKTOP_APP_DISABLE_X11_INTEGRATION)
|
||||
target_link_libraries(Telegram PRIVATE X11)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (build_macstore)
|
||||
|
|
|
@ -7,9 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "platform/linux/file_utilities_linux.h"
|
||||
|
||||
#include "platform/linux/linux_gtk_integration.h"
|
||||
#include "platform/linux/specific_linux.h"
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
#include "platform/linux/linux_xdp_file_dialog.h"
|
||||
#include "platform/linux/linux_xdp_open_with_dialog.h"
|
||||
|
@ -21,8 +18,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <glibmm.h>
|
||||
#include <giomm.h>
|
||||
|
||||
using Platform::internal::GtkIntegration;
|
||||
|
||||
namespace Platform {
|
||||
namespace File {
|
||||
|
||||
|
@ -53,14 +48,6 @@ bool UnsafeShowOpenWith(const QString &filepath) {
|
|||
}
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
if (InFlatpak() || InSnap()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (const auto integration = GtkIntegration::Instance()) {
|
||||
return integration->showOpenWithDialog(filepath);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,11 +64,6 @@ int Launcher::exec() {
|
|||
GtkIntegration::Type::Webview,
|
||||
QString::fromStdString(*(i + 1)),
|
||||
QString::fromStdString(*(i + 2)));
|
||||
} else if (*i == "-gtkintegration" && std::distance(i, e) > 2) {
|
||||
return GtkIntegration::Exec(
|
||||
GtkIntegration::Type::TDesktop,
|
||||
QString::fromStdString(*(i + 1)),
|
||||
QString::fromStdString(*(i + 2)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,149 +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/linux/linux_gdk_helper.h"
|
||||
|
||||
#include "base/platform/linux/base_linux_gtk_integration.h"
|
||||
#include "base/platform/linux/base_linux_gtk_integration_p.h"
|
||||
#include "platform/linux/linux_gtk_integration_p.h"
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||
extern "C" {
|
||||
#include <gdk/gdkx.h>
|
||||
} // extern "C"
|
||||
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
|
||||
extern "C" {
|
||||
#include <gdk/gdkwayland.h>
|
||||
} // extern "C"
|
||||
#endif // !DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
|
||||
|
||||
namespace Platform {
|
||||
namespace internal {
|
||||
namespace {
|
||||
|
||||
using base::Platform::GtkIntegration;
|
||||
using namespace Platform::Gtk;
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||
// To be able to compile with gtk-3.0 headers
|
||||
#define GdkDrawable GdkWindow
|
||||
|
||||
// Gtk 2
|
||||
using f_gdk_x11_drawable_get_xdisplay = Display*(*)(GdkDrawable*);
|
||||
f_gdk_x11_drawable_get_xdisplay gdk_x11_drawable_get_xdisplay = nullptr;
|
||||
|
||||
using f_gdk_x11_drawable_get_xid = XID(*)(GdkDrawable*);
|
||||
f_gdk_x11_drawable_get_xid gdk_x11_drawable_get_xid = nullptr;
|
||||
|
||||
// Gtk 3
|
||||
using f_gdk_x11_window_get_type = GType (*)(void);
|
||||
f_gdk_x11_window_get_type gdk_x11_window_get_type = nullptr;
|
||||
|
||||
using f_gdk_window_get_display = GdkDisplay*(*)(GdkWindow *window);
|
||||
f_gdk_window_get_display gdk_window_get_display = nullptr;
|
||||
|
||||
using f_gdk_x11_display_get_xdisplay = Display*(*)(GdkDisplay *display);
|
||||
f_gdk_x11_display_get_xdisplay gdk_x11_display_get_xdisplay = nullptr;
|
||||
|
||||
using f_gdk_x11_window_get_xid = Window(*)(GdkWindow *window);
|
||||
f_gdk_x11_window_get_xid gdk_x11_window_get_xid = nullptr;
|
||||
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
|
||||
using f_gdk_wayland_window_get_type = GType (*)(void);
|
||||
f_gdk_wayland_window_get_type gdk_wayland_window_get_type = nullptr;
|
||||
|
||||
using f_gdk_wayland_window_set_transient_for_exported = gboolean(*)(GdkWindow *window, char *parent_handle_str);
|
||||
f_gdk_wayland_window_set_transient_for_exported gdk_wayland_window_set_transient_for_exported = nullptr;
|
||||
#endif // !DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
|
||||
|
||||
void GdkHelperLoadGtk2(QLibrary &lib) {
|
||||
#if !defined DESKTOP_APP_DISABLE_X11_INTEGRATION && !defined LINK_TO_GTK
|
||||
LOAD_GTK_SYMBOL(lib, gdk_x11_drawable_get_xdisplay);
|
||||
LOAD_GTK_SYMBOL(lib, gdk_x11_drawable_get_xid);
|
||||
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION && !LINK_TO_GTK
|
||||
}
|
||||
|
||||
void GdkHelperLoadGtk3(QLibrary &lib) {
|
||||
#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||
LOAD_GTK_SYMBOL(lib, gdk_x11_window_get_type);
|
||||
LOAD_GTK_SYMBOL(lib, gdk_window_get_display);
|
||||
LOAD_GTK_SYMBOL(lib, gdk_x11_display_get_xdisplay);
|
||||
LOAD_GTK_SYMBOL(lib, gdk_x11_window_get_xid);
|
||||
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||
#ifndef DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
|
||||
LOAD_GTK_SYMBOL(lib, gdk_wayland_window_get_type);
|
||||
LOAD_GTK_SYMBOL(lib, gdk_wayland_window_set_transient_for_exported);
|
||||
#endif // !DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void GdkHelperLoad(QLibrary &lib) {
|
||||
if (const auto integration = GtkIntegration::Instance()) {
|
||||
if (integration->checkVersion(3, 0, 0)) {
|
||||
GdkHelperLoadGtk3(lib);
|
||||
} else {
|
||||
GdkHelperLoadGtk2(lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdkSetTransientFor(GdkWindow *window, const QString &parent) {
|
||||
#ifndef DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
|
||||
if (gdk_wayland_window_get_type != nullptr
|
||||
&& gdk_wayland_window_set_transient_for_exported != nullptr
|
||||
&& GDK_IS_WAYLAND_WINDOW(window)
|
||||
&& parent.startsWith("wayland:")) {
|
||||
auto handle = parent.mid(8).toUtf8();
|
||||
gdk_wayland_window_set_transient_for_exported(
|
||||
window,
|
||||
handle.data());
|
||||
return;
|
||||
}
|
||||
#endif // !DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||
if (gdk_x11_window_get_type != nullptr
|
||||
&& gdk_x11_display_get_xdisplay != nullptr
|
||||
&& gdk_x11_window_get_xid != nullptr
|
||||
&& gdk_window_get_display != nullptr
|
||||
&& GDK_IS_X11_WINDOW(window)
|
||||
&& parent.startsWith("x11:")) {
|
||||
auto ok = false;
|
||||
const auto winId = parent.mid(4).toInt(&ok, 16);
|
||||
if (ok) {
|
||||
XSetTransientForHint(
|
||||
gdk_x11_display_get_xdisplay(gdk_window_get_display(window)),
|
||||
gdk_x11_window_get_xid(window),
|
||||
winId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||
if (gdk_x11_drawable_get_xdisplay != nullptr
|
||||
&& gdk_x11_drawable_get_xid != nullptr
|
||||
&& parent.startsWith("x11:")) {
|
||||
auto ok = false;
|
||||
const auto winId = parent.mid(4).toInt(&ok, 16);
|
||||
if (ok) {
|
||||
XSetTransientForHint(
|
||||
gdk_x11_drawable_get_xdisplay(window),
|
||||
gdk_x11_drawable_get_xid(window),
|
||||
winId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace Platform
|
|
@ -1,24 +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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
class QLibrary;
|
||||
|
||||
extern "C" {
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
} // extern "C"
|
||||
|
||||
namespace Platform {
|
||||
namespace internal {
|
||||
|
||||
void GdkHelperLoad(QLibrary &lib);
|
||||
void GdkSetTransientFor(GdkWindow *window, const QString &parent);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace Platform
|
|
@ -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 ¶meters,
|
||||
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 ¶meters,
|
||||
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 (...) {
|
||||
|
|
|
@ -15,16 +15,8 @@ public:
|
|||
enum class Type {
|
||||
Base,
|
||||
Webview,
|
||||
TDesktop,
|
||||
};
|
||||
|
||||
static GtkIntegration *Instance();
|
||||
|
||||
void load(const QString &allowedBackends);
|
||||
int exec(const QString &parentDBusName);
|
||||
|
||||
[[nodiscard]] bool showOpenWithDialog(const QString &filepath) const;
|
||||
|
||||
static QString AllowedBackends();
|
||||
|
||||
static int Exec(
|
||||
|
@ -35,13 +27,6 @@ public:
|
|||
static void Start(Type type);
|
||||
|
||||
static void Autorestart(Type type);
|
||||
|
||||
private:
|
||||
GtkIntegration();
|
||||
~GtkIntegration();
|
||||
|
||||
class Private;
|
||||
const std::unique_ptr<Private> _private;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
|
|
@ -10,29 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace Platform {
|
||||
namespace internal {
|
||||
|
||||
class GtkIntegration::Private {
|
||||
};
|
||||
|
||||
GtkIntegration::GtkIntegration() {
|
||||
}
|
||||
|
||||
GtkIntegration::~GtkIntegration() = default;
|
||||
|
||||
GtkIntegration *GtkIntegration::Instance() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GtkIntegration::load(const QString &allowedBackends) {
|
||||
}
|
||||
|
||||
int GtkIntegration::exec(const QString &parentDBusName) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool GtkIntegration::showOpenWithDialog(const QString &filepath) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
QString GtkIntegration::AllowedBackends() {
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -1,27 +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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
extern "C" {
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
} // extern "C"
|
||||
|
||||
namespace Platform {
|
||||
namespace Gtk {
|
||||
|
||||
inline void (*gtk_widget_show)(GtkWidget *widget) = nullptr;
|
||||
inline GdkWindow* (*gtk_widget_get_window)(GtkWidget *widget) = nullptr;
|
||||
inline void (*gtk_widget_realize)(GtkWidget *widget) = nullptr;
|
||||
inline void (*gtk_widget_destroy)(GtkWidget *widget) = nullptr;
|
||||
inline GType (*gtk_app_chooser_get_type)(void) G_GNUC_CONST = nullptr;
|
||||
inline GtkWidget* (*gtk_app_chooser_dialog_new)(GtkWindow *parent, GtkDialogFlags flags, GFile *file) = nullptr;
|
||||
inline GAppInfo* (*gtk_app_chooser_get_app_info)(GtkAppChooser *self) = nullptr;
|
||||
|
||||
} // namespace Gtk
|
||||
} // namespace Platform
|
|
@ -1,134 +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/linux/linux_gtk_open_with_dialog.h"
|
||||
|
||||
#include "platform/linux/linux_gtk_integration_p.h"
|
||||
#include "platform/linux/linux_gdk_helper.h"
|
||||
|
||||
#include <giomm.h>
|
||||
|
||||
namespace Platform {
|
||||
namespace File {
|
||||
namespace internal {
|
||||
namespace {
|
||||
|
||||
using namespace Platform::Gtk;
|
||||
|
||||
struct GtkWidgetDeleter {
|
||||
void operator()(GtkWidget *widget) {
|
||||
gtk_widget_destroy(widget);
|
||||
}
|
||||
};
|
||||
|
||||
bool Supported() {
|
||||
return (gtk_app_chooser_dialog_new != nullptr)
|
||||
&& (gtk_app_chooser_get_app_info != nullptr)
|
||||
&& (gtk_app_chooser_get_type != nullptr)
|
||||
&& (gtk_widget_get_window != nullptr)
|
||||
&& (gtk_widget_realize != nullptr)
|
||||
&& (gtk_widget_show != nullptr)
|
||||
&& (gtk_widget_destroy != nullptr);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class GtkOpenWithDialog::Private {
|
||||
public:
|
||||
Private(
|
||||
const QString &parent,
|
||||
const QString &filepath);
|
||||
|
||||
private:
|
||||
friend class GtkOpenWithDialog;
|
||||
|
||||
static void handleResponse(Private *dialog, int responseId);
|
||||
|
||||
const Glib::RefPtr<Gio::File> _file;
|
||||
const std::unique_ptr<GtkWidget, GtkWidgetDeleter> _gtkWidget;
|
||||
rpl::event_stream<bool> _responseStream;
|
||||
};
|
||||
|
||||
GtkOpenWithDialog::Private::Private(
|
||||
const QString &parent,
|
||||
const QString &filepath)
|
||||
: _file(Gio::File::create_for_path(filepath.toStdString()))
|
||||
, _gtkWidget(gtk_app_chooser_dialog_new(
|
||||
nullptr,
|
||||
GTK_DIALOG_MODAL,
|
||||
_file->gobj())) {
|
||||
g_signal_connect_swapped(
|
||||
_gtkWidget.get(),
|
||||
"response",
|
||||
G_CALLBACK(handleResponse),
|
||||
this);
|
||||
|
||||
gtk_widget_realize(_gtkWidget.get());
|
||||
|
||||
Platform::internal::GdkSetTransientFor(
|
||||
gtk_widget_get_window(_gtkWidget.get()),
|
||||
parent);
|
||||
|
||||
gtk_widget_show(_gtkWidget.get());
|
||||
}
|
||||
|
||||
void GtkOpenWithDialog::Private::handleResponse(Private *dialog, int responseId) {
|
||||
Glib::RefPtr<Gio::AppInfo> chosenAppInfo;
|
||||
bool result = true;
|
||||
|
||||
switch (responseId) {
|
||||
case GTK_RESPONSE_OK:
|
||||
chosenAppInfo = Glib::wrap(gtk_app_chooser_get_app_info(
|
||||
GTK_APP_CHOOSER(dialog->_gtkWidget.get())));
|
||||
|
||||
if (chosenAppInfo) {
|
||||
try {
|
||||
chosenAppInfo->launch_uri(dialog->_file->get_uri());
|
||||
} catch (...) {
|
||||
}
|
||||
chosenAppInfo = {};
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GTK_RESPONSE_CANCEL:
|
||||
case GTK_RESPONSE_DELETE_EVENT:
|
||||
break;
|
||||
|
||||
default:
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
dialog->_responseStream.fire_copy(result);
|
||||
}
|
||||
|
||||
GtkOpenWithDialog::GtkOpenWithDialog(
|
||||
const QString &parent,
|
||||
const QString &filepath)
|
||||
: _private(std::make_unique<Private>(parent, filepath)) {
|
||||
}
|
||||
|
||||
GtkOpenWithDialog::~GtkOpenWithDialog() = default;
|
||||
|
||||
rpl::producer<bool> GtkOpenWithDialog::response() {
|
||||
return _private->_responseStream.events();
|
||||
}
|
||||
|
||||
std::unique_ptr<GtkOpenWithDialog> CreateGtkOpenWithDialog(
|
||||
const QString &parent,
|
||||
const QString &filepath) {
|
||||
if (!Supported()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<GtkOpenWithDialog>(parent, filepath);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace File
|
||||
} // namespace Platform
|
|
@ -1,40 +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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace Platform {
|
||||
namespace File {
|
||||
namespace internal {
|
||||
|
||||
class GtkOpenWithDialog {
|
||||
public:
|
||||
GtkOpenWithDialog(
|
||||
const QString &parent,
|
||||
const QString &filepath);
|
||||
|
||||
~GtkOpenWithDialog();
|
||||
|
||||
[[nodiscard]] rpl::producer<bool> response();
|
||||
[[nodiscard]] rpl::lifetime &lifetime() {
|
||||
return _lifetime;
|
||||
}
|
||||
|
||||
private:
|
||||
class Private;
|
||||
const std::unique_ptr<Private> _private;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
};
|
||||
|
||||
[[nodiscard]] std::unique_ptr<GtkOpenWithDialog> CreateGtkOpenWithDialog(
|
||||
const QString &parent,
|
||||
const QString &filepath);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace File
|
||||
} // namespace Platform
|
|
@ -653,7 +653,6 @@ void start() {
|
|||
|
||||
GtkIntegration::Start(GtkIntegration::Type::Base);
|
||||
GtkIntegration::Start(GtkIntegration::Type::Webview);
|
||||
GtkIntegration::Start(GtkIntegration::Type::TDesktop);
|
||||
|
||||
#ifdef DESKTOP_APP_USE_PACKAGED_RLOTTIE
|
||||
g_warning(
|
||||
|
@ -784,16 +783,11 @@ void start() {
|
|||
LOG(("Fallback icon theme: %1").arg(QIcon::fallbackThemeName()));
|
||||
|
||||
GtkIntegration::Autorestart(GtkIntegration::Type::Base);
|
||||
GtkIntegration::Autorestart(GtkIntegration::Type::TDesktop);
|
||||
|
||||
if (const auto integration = BaseGtkIntegration::Instance()) {
|
||||
integration->load(GtkIntegration::AllowedBackends());
|
||||
}
|
||||
|
||||
if (const auto integration = GtkIntegration::Instance()) {
|
||||
integration->load(GtkIntegration::AllowedBackends());
|
||||
}
|
||||
|
||||
// wait for interface announce to know if native window frame is supported
|
||||
if (const auto integration = UiWaylandIntegration::Instance()) {
|
||||
integration->waitForInterfaceAnnounce();
|
||||
|
|
Loading…
Add table
Reference in a new issue