diff --git a/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp b/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp index 3caa9b31a..74456143f 100644 --- a/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_gtk_integration.cpp @@ -154,11 +154,28 @@ void GtkIntegration::Private::handleMethodCall( const auto filepath = base::Platform::GlibVariantCast< Glib::ustring>(parametersCopy.get_child(1)); - const auto result = File::internal::ShowGtkOpenWithDialog( + const auto dialog = File::internal::CreateGtkOpenWithDialog( QString::fromStdString(parent), - QString::fromStdString(filepath)); + 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()); - if (result) { invocation->return_value({}); return; } @@ -340,23 +357,6 @@ int GtkIntegration::exec(const QString &parentDBusName, int ppid) { _private->introspectionData->lookup_interface(), _private->interfaceVTable); - rpl::lifetime lifetime; - - File::internal::GtkOpenWithDialogResponse( - ) | rpl::start_with_next([=](bool response) { - try { - _private->dbusConnection->emit_signal( - std::string(kObjectPath), - std::string(kInterface), - "OpenWithDialogResponse", - _private->parentDBusName, - base::Platform::MakeGlibVariant(std::tuple{ - response, - })); - } catch (...) { - } - }, lifetime); - const auto app = Gio::Application::create(_private->serviceName); app->hold(); _private->parentServiceWatcherId = base::Platform::DBus::RegisterServiceWatcher( @@ -459,21 +459,24 @@ bool GtkIntegration::showOpenWithDialog(const QString &filepath) const { return false; } - if (!File::internal::ShowGtkOpenWithDialog(parent, filepath)) { + 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()); - rpl::lifetime lifetime; bool result = false; - File::internal::GtkOpenWithDialogResponse( + dialog->response( ) | rpl::start_with_next([&](bool response) { result = response; loop->quit(); - }, lifetime); + }, dialog->lifetime()); QWindow window; QGuiApplicationPrivate::showModalWindow(&window); diff --git a/Telegram/SourceFiles/platform/linux/linux_gtk_open_with_dialog.cpp b/Telegram/SourceFiles/platform/linux/linux_gtk_open_with_dialog.cpp index 5bd9442ef..2b99806b8 100644 --- a/Telegram/SourceFiles/platform/linux/linux_gtk_open_with_dialog.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_gtk_open_with_dialog.cpp @@ -19,8 +19,6 @@ namespace { using namespace Platform::Gtk; -rpl::event_stream GtkOpenWithDialogResponseStream; - struct GtkWidgetDeleter { void operator()(GtkWidget *widget) { gtk_widget_destroy(widget); @@ -37,20 +35,25 @@ bool Supported() { && (gtk_widget_destroy != nullptr); } -class GtkOpenWithDialog { +} // namespace + +class GtkOpenWithDialog::Private { public: - GtkOpenWithDialog( + Private( const QString &parent, const QString &filepath); private: - static void handleResponse(GtkOpenWithDialog *dialog, int responseId); + friend class GtkOpenWithDialog; + + static void handleResponse(Private *dialog, int responseId); const Glib::RefPtr _file; const std::unique_ptr _gtkWidget; + rpl::event_stream _responseStream; }; -GtkOpenWithDialog::GtkOpenWithDialog( +GtkOpenWithDialog::Private::Private( const QString &parent, const QString &filepath) : _file(Gio::File::create_for_path(filepath.toStdString())) @@ -73,7 +76,7 @@ GtkOpenWithDialog::GtkOpenWithDialog( gtk_widget_show(_gtkWidget.get()); } -void GtkOpenWithDialog::handleResponse(GtkOpenWithDialog *dialog, int responseId) { +void GtkOpenWithDialog::Private::handleResponse(Private *dialog, int responseId) { Glib::RefPtr chosenAppInfo; bool result = true; @@ -101,24 +104,29 @@ void GtkOpenWithDialog::handleResponse(GtkOpenWithDialog *dialog, int responseId break; } - GtkOpenWithDialogResponseStream.fire_copy(result); - delete dialog; + dialog->_responseStream.fire_copy(result); } -} // namespace +GtkOpenWithDialog::GtkOpenWithDialog( + const QString &parent, + const QString &filepath) +: _private(std::make_unique(parent, filepath)) { +} -bool ShowGtkOpenWithDialog( +GtkOpenWithDialog::~GtkOpenWithDialog() = default; + +rpl::producer GtkOpenWithDialog::response() { + return _private->_responseStream.events(); +} + +std::unique_ptr CreateGtkOpenWithDialog( const QString &parent, const QString &filepath) { if (!Supported()) { - return false; + return nullptr; } - return new GtkOpenWithDialog(parent, filepath); -} - -rpl::producer GtkOpenWithDialogResponse() { - return GtkOpenWithDialogResponseStream.events(); + return std::make_unique(parent, filepath); } } // namespace internal diff --git a/Telegram/SourceFiles/platform/linux/linux_gtk_open_with_dialog.h b/Telegram/SourceFiles/platform/linux/linux_gtk_open_with_dialog.h index 477af9034..5e83492f1 100644 --- a/Telegram/SourceFiles/platform/linux/linux_gtk_open_with_dialog.h +++ b/Telegram/SourceFiles/platform/linux/linux_gtk_open_with_dialog.h @@ -11,12 +11,30 @@ namespace Platform { namespace File { namespace internal { -bool ShowGtkOpenWithDialog( +class GtkOpenWithDialog { +public: + GtkOpenWithDialog( + const QString &parent, + const QString &filepath); + + ~GtkOpenWithDialog(); + + [[nodiscard]] rpl::producer response(); + [[nodiscard]] rpl::lifetime &lifetime() { + return _lifetime; + } + +private: + class Private; + const std::unique_ptr _private; + + rpl::lifetime _lifetime; +}; + +[[nodiscard]] std::unique_ptr CreateGtkOpenWithDialog( const QString &parent, const QString &filepath); -[[nodiscard]] rpl::producer GtkOpenWithDialogResponse(); - } // namespace internal } // namespace File } // namespace Platform