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:
Ilya Fedin 2021-08-25 10:03:05 +04:00 committed by John Preston
parent 2694cb76a7
commit 51df482571
12 changed files with 8 additions and 838 deletions

View File

@ -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)

View File

@ -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;
}

View File

@ -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)));
}
}

View File

@ -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

View File

@ -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

View File

@ -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 (...) {

View File

@ -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

View File

@ -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 {};
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();