mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 23:27:09 +02:00
Add portal-based open with dialog implementation
This commit is contained in:
parent
a27a54798c
commit
b918170464
7 changed files with 229 additions and 20 deletions
|
@ -815,14 +815,16 @@ PRIVATE
|
|||
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_notification_service_watcher.cpp
|
||||
platform/linux/linux_notification_service_watcher.h
|
||||
platform/linux/linux_open_with_dialog.cpp
|
||||
platform/linux/linux_open_with_dialog.h
|
||||
platform/linux/linux_wayland_integration.cpp
|
||||
platform/linux/linux_wayland_integration.h
|
||||
platform/linux/linux_xdp_file_dialog.cpp
|
||||
platform/linux/linux_xdp_file_dialog.h
|
||||
platform/linux/linux_xdp_open_with_dialog.cpp
|
||||
platform/linux/linux_xdp_open_with_dialog.h
|
||||
platform/linux/file_utilities_linux.cpp
|
||||
platform/linux/file_utilities_linux.h
|
||||
platform/linux/launcher_linux.cpp
|
||||
|
@ -1111,6 +1113,8 @@ if (DESKTOP_APP_DISABLE_DBUS_INTEGRATION)
|
|||
platform/linux/linux_notification_service_watcher.h
|
||||
platform/linux/linux_xdp_file_dialog.cpp
|
||||
platform/linux/linux_xdp_file_dialog.h
|
||||
platform/linux/linux_xdp_open_with_dialog.cpp
|
||||
platform/linux/linux_xdp_open_with_dialog.h
|
||||
platform/linux/notifications_manager_linux.cpp
|
||||
)
|
||||
|
||||
|
@ -1133,8 +1137,8 @@ if (DESKTOP_APP_DISABLE_GTK_INTEGRATION)
|
|||
platform/linux/linux_gtk_file_dialog.h
|
||||
platform/linux/linux_gtk_integration_p.h
|
||||
platform/linux/linux_gtk_integration.cpp
|
||||
platform/linux/linux_open_with_dialog.cpp
|
||||
platform/linux/linux_open_with_dialog.h
|
||||
platform/linux/linux_gtk_open_with_dialog.cpp
|
||||
platform/linux/linux_gtk_open_with_dialog.h
|
||||
)
|
||||
|
||||
nice_target_sources(Telegram ${src_loc}
|
||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
#include "platform/linux/linux_xdp_file_dialog.h"
|
||||
#include "platform/linux/linux_xdp_open_with_dialog.h"
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
#include <QtGui/QDesktopServices>
|
||||
|
@ -41,6 +42,12 @@ void UnsafeOpenEmailLink(const QString &email) {
|
|||
}
|
||||
|
||||
bool UnsafeShowOpenWith(const QString &filepath) {
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
if (internal::ShowXDPOpenWithDialog(filepath)) {
|
||||
return true;
|
||||
}
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
if (InFlatpak() || InSnap()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "platform/linux/linux_gtk_integration_p.h"
|
||||
#include "platform/linux/linux_gdk_helper.h"
|
||||
#include "platform/linux/linux_gtk_file_dialog.h"
|
||||
#include "platform/linux/linux_open_with_dialog.h"
|
||||
#include "platform/linux/linux_gtk_open_with_dialog.h"
|
||||
|
||||
namespace Platform {
|
||||
namespace internal {
|
||||
|
@ -185,7 +185,7 @@ bool GtkIntegration::getFileDialog(
|
|||
}
|
||||
|
||||
bool GtkIntegration::showOpenWithDialog(const QString &filepath) const {
|
||||
return File::internal::ShowOpenWithDialog(filepath);
|
||||
return File::internal::ShowGtkOpenWithDialog(filepath);
|
||||
}
|
||||
|
||||
QImage GtkIntegration::getImageFromClipboard() const {
|
||||
|
|
|
@ -5,7 +5,7 @@ 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_open_with_dialog.h"
|
||||
#include "platform/linux/linux_gtk_open_with_dialog.h"
|
||||
|
||||
#include "platform/linux/linux_gtk_integration_p.h"
|
||||
#include "platform/linux/linux_gdk_helper.h"
|
||||
|
@ -21,7 +21,7 @@ namespace {
|
|||
|
||||
using namespace Platform::Gtk;
|
||||
|
||||
bool OpenWithDialogSupported() {
|
||||
bool Supported() {
|
||||
return Platform::internal::GdkHelperLoaded()
|
||||
&& (gtk_app_chooser_dialog_new != nullptr)
|
||||
&& (gtk_app_chooser_get_app_info != nullptr)
|
||||
|
@ -32,15 +32,15 @@ bool OpenWithDialogSupported() {
|
|||
&& (gtk_widget_destroy != nullptr);
|
||||
}
|
||||
|
||||
class OpenWithDialog : public QWindow {
|
||||
class GtkOpenWithDialog : public QWindow {
|
||||
public:
|
||||
OpenWithDialog(const QString &filepath);
|
||||
~OpenWithDialog();
|
||||
GtkOpenWithDialog(const QString &filepath);
|
||||
~GtkOpenWithDialog();
|
||||
|
||||
bool exec();
|
||||
|
||||
private:
|
||||
static void handleResponse(OpenWithDialog *dialog, int responseId);
|
||||
static void handleResponse(GtkOpenWithDialog *dialog, int responseId);
|
||||
|
||||
GFile *_gfileInstance = nullptr;
|
||||
GtkWidget *_gtkWidget = nullptr;
|
||||
|
@ -48,7 +48,7 @@ private:
|
|||
std::optional<bool> _result;
|
||||
};
|
||||
|
||||
OpenWithDialog::OpenWithDialog(const QString &filepath)
|
||||
GtkOpenWithDialog::GtkOpenWithDialog(const QString &filepath)
|
||||
: _gfileInstance(g_file_new_for_path(filepath.toUtf8().constData()))
|
||||
, _gtkWidget(gtk_app_chooser_dialog_new(
|
||||
nullptr,
|
||||
|
@ -61,12 +61,12 @@ OpenWithDialog::OpenWithDialog(const QString &filepath)
|
|||
this);
|
||||
}
|
||||
|
||||
OpenWithDialog::~OpenWithDialog() {
|
||||
GtkOpenWithDialog::~GtkOpenWithDialog() {
|
||||
gtk_widget_destroy(_gtkWidget);
|
||||
g_object_unref(_gfileInstance);
|
||||
}
|
||||
|
||||
bool OpenWithDialog::exec() {
|
||||
bool GtkOpenWithDialog::exec() {
|
||||
gtk_widget_realize(_gtkWidget);
|
||||
|
||||
if (const auto activeWindow = Core::App().activeWindow()) {
|
||||
|
@ -86,7 +86,7 @@ bool OpenWithDialog::exec() {
|
|||
return *_result;
|
||||
}
|
||||
|
||||
void OpenWithDialog::handleResponse(OpenWithDialog *dialog, int responseId) {
|
||||
void GtkOpenWithDialog::handleResponse(GtkOpenWithDialog *dialog, int responseId) {
|
||||
GAppInfo *chosenAppInfo = nullptr;
|
||||
dialog->_result = true;
|
||||
|
||||
|
@ -119,12 +119,12 @@ void OpenWithDialog::handleResponse(OpenWithDialog *dialog, int responseId) {
|
|||
|
||||
} // namespace
|
||||
|
||||
bool ShowOpenWithDialog(const QString &filepath) {
|
||||
if (!OpenWithDialogSupported()) {
|
||||
bool ShowGtkOpenWithDialog(const QString &filepath) {
|
||||
if (!Supported()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return OpenWithDialog(filepath).exec();
|
||||
return GtkOpenWithDialog(filepath).exec();
|
||||
}
|
||||
|
||||
} // namespace internal
|
|
@ -11,7 +11,7 @@ namespace Platform {
|
|||
namespace File {
|
||||
namespace internal {
|
||||
|
||||
bool ShowOpenWithDialog(const QString &filepath);
|
||||
bool ShowGtkOpenWithDialog(const QString &filepath);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace File
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
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_xdp_open_with_dialog.h"
|
||||
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/platform/linux/base_linux_glibmm_helper.h"
|
||||
#include "core/application.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "base/openssl_help.h"
|
||||
|
||||
#include <QtGui/QWindow>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <gio/gunixfdlist.h>
|
||||
#include <glibmm.h>
|
||||
#include <giomm.h>
|
||||
#include <private/qguiapplication_p.h>
|
||||
|
||||
namespace Platform {
|
||||
namespace File {
|
||||
namespace internal {
|
||||
namespace {
|
||||
|
||||
constexpr auto kXDGDesktopPortalService = "org.freedesktop.portal.Desktop"_cs;
|
||||
constexpr auto kXDGDesktopPortalObjectPath = "/org/freedesktop/portal/desktop"_cs;
|
||||
constexpr auto kXDGDesktopPortalOpenURIInterface = "org.freedesktop.portal.OpenURI"_cs;
|
||||
constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs;
|
||||
|
||||
class XDPOpenWithDialog : public QWindow {
|
||||
public:
|
||||
XDPOpenWithDialog(const QString &filepath)
|
||||
: _filepath(filepath.toStdString()) {
|
||||
}
|
||||
|
||||
bool exec();
|
||||
|
||||
private:
|
||||
Glib::ustring _filepath;
|
||||
};
|
||||
|
||||
bool XDPOpenWithDialog::exec() {
|
||||
try {
|
||||
const auto connection = Gio::DBus::Connection::get_sync(
|
||||
Gio::DBus::BusType::BUS_TYPE_SESSION);
|
||||
|
||||
auto reply = connection->call_sync(
|
||||
std::string(kXDGDesktopPortalObjectPath),
|
||||
std::string(kPropertiesInterface),
|
||||
"Get",
|
||||
base::Platform::MakeGlibVariant(std::tuple{
|
||||
Glib::ustring(
|
||||
std::string(kXDGDesktopPortalOpenURIInterface)),
|
||||
Glib::ustring("version"),
|
||||
}),
|
||||
std::string(kXDGDesktopPortalService));
|
||||
|
||||
const auto version = base::Platform::GlibVariantCast<uint>(
|
||||
base::Platform::GlibVariantCast<Glib::VariantBase>(
|
||||
reply.get_child(0)));
|
||||
|
||||
if (version < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto fd = open(
|
||||
_filepath.c_str(),
|
||||
O_RDONLY);
|
||||
|
||||
if (fd == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto fdGuard = gsl::finally([&] { ::close(fd); });
|
||||
auto outFdList = Glib::RefPtr<Gio::UnixFDList>();
|
||||
|
||||
const auto parentWindowId = [&]() -> Glib::ustring {
|
||||
std::stringstream result;
|
||||
if (const auto activeWindow = Core::App().activeWindow()) {
|
||||
if (IsX11()) {
|
||||
result
|
||||
<< "x11:"
|
||||
<< std::hex
|
||||
<< activeWindow
|
||||
->widget()
|
||||
.get()
|
||||
->windowHandle()
|
||||
->winId();
|
||||
}
|
||||
}
|
||||
return result.str();
|
||||
}();
|
||||
|
||||
const auto handleToken = Glib::ustring("tdesktop")
|
||||
+ std::to_string(openssl::RandomValue<uint>());
|
||||
|
||||
auto uniqueName = connection->get_unique_name();
|
||||
uniqueName.erase(0, 1);
|
||||
uniqueName.replace(uniqueName.find('.'), 1, 1, '_');
|
||||
|
||||
const auto requestPath = Glib::ustring(
|
||||
"/org/freedesktop/portal/desktop/request/")
|
||||
+ uniqueName
|
||||
+ '/'
|
||||
+ handleToken;
|
||||
|
||||
QEventLoop loop;
|
||||
|
||||
const auto signalId = connection->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,
|
||||
const Glib::VariantContainerBase ¶meters) {
|
||||
loop.quit();
|
||||
},
|
||||
std::string(kXDGDesktopPortalService),
|
||||
"org.freedesktop.portal.Request",
|
||||
"Response",
|
||||
requestPath);
|
||||
|
||||
const auto signalGuard = gsl::finally([&] {
|
||||
if (signalId != 0) {
|
||||
connection->signal_unsubscribe(signalId);
|
||||
}
|
||||
});
|
||||
|
||||
connection->call_sync(
|
||||
std::string(kXDGDesktopPortalObjectPath),
|
||||
std::string(kXDGDesktopPortalOpenURIInterface),
|
||||
"OpenFile",
|
||||
Glib::VariantContainerBase::create_tuple({
|
||||
Glib::Variant<Glib::ustring>::create(parentWindowId),
|
||||
Glib::wrap(g_variant_new_handle(0)),
|
||||
Glib::Variant<std::map<
|
||||
Glib::ustring,
|
||||
Glib::VariantBase
|
||||
>>::create({
|
||||
{
|
||||
"handle_token",
|
||||
Glib::Variant<Glib::ustring>::create(handleToken)
|
||||
},
|
||||
{
|
||||
"ask",
|
||||
Glib::Variant<bool>::create(true)
|
||||
},
|
||||
}),
|
||||
}),
|
||||
Glib::wrap(g_unix_fd_list_new_from_array(&fd, 1)),
|
||||
outFdList,
|
||||
std::string(kXDGDesktopPortalService));
|
||||
|
||||
if (signalId != 0) {
|
||||
QGuiApplicationPrivate::showModalWindow(this);
|
||||
loop.exec();
|
||||
QGuiApplicationPrivate::hideModalWindow(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool ShowXDPOpenWithDialog(const QString &filepath) {
|
||||
return XDPOpenWithDialog(filepath).exec();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace File
|
||||
} // namespace Platform
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
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 {
|
||||
|
||||
bool ShowXDPOpenWithDialog(const QString &filepath);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace File
|
||||
} // namespace Platform
|
Loading…
Add table
Reference in a new issue