Make open with dialog modal on Linux

This commit is contained in:
Ilya Fedin 2021-01-02 07:52:06 +04:00 committed by John Preston
parent b28da30038
commit 15a9842b9f
3 changed files with 62 additions and 45 deletions

View file

@ -45,45 +45,95 @@ bool ShowOpenWithSupported() {
&& (Libs::gtk_app_chooser_dialog_new != nullptr) && (Libs::gtk_app_chooser_dialog_new != nullptr)
&& (Libs::gtk_app_chooser_get_app_info != nullptr) && (Libs::gtk_app_chooser_get_app_info != nullptr)
&& (Libs::gtk_app_chooser_get_type != nullptr) && (Libs::gtk_app_chooser_get_type != nullptr)
&& (Libs::gtk_widget_get_type != nullptr)
&& (Libs::gtk_widget_get_window != nullptr) && (Libs::gtk_widget_get_window != nullptr)
&& (Libs::gtk_widget_realize != nullptr) && (Libs::gtk_widget_realize != nullptr)
&& (Libs::gtk_widget_show != nullptr) && (Libs::gtk_widget_show != nullptr)
&& (Libs::gtk_widget_destroy != nullptr); && (Libs::gtk_widget_destroy != nullptr);
} }
void HandleAppChooserResponse( class OpenWithDialog : public QWindow {
GtkDialog *dialog, public:
int responseId, OpenWithDialog(const QString &filepath);
GFile *file) { ~OpenWithDialog();
bool exec();
private:
static void handleResponse(OpenWithDialog *dialog, int responseId);
GFile *_gfileInstance = nullptr;
GtkWidget *_gtkWidget = nullptr;
QEventLoop _loop;
std::optional<bool> _result = std::nullopt;
};
OpenWithDialog::OpenWithDialog(const QString &filepath)
: _gfileInstance(g_file_new_for_path(filepath.toUtf8()))
, _gtkWidget(Libs::gtk_app_chooser_dialog_new(
nullptr,
GTK_DIALOG_MODAL,
_gfileInstance)) {
g_signal_connect_swapped(
_gtkWidget,
"response",
G_CALLBACK(handleAppChooserResponse),
this);
}
OpenWithDialog::~OpenWithDialog() {
Libs::gtk_widget_destroy(_gtkWidget);
g_object_unref(_gfileInstance);
}
bool OpenWithDialog::exec() {
Libs::gtk_widget_realize(_gtkWidget);
if (const auto activeWindow = Core::App().activeWindow()) {
Platform::internal::XSetTransientForHint(
Libs::gtk_widget_get_window(_gtkWidget),
activeWindow->widget().get()->windowHandle()->winId());
}
QGuiApplicationPrivate::showModalWindow(this);
Libs::gtk_widget_show(_gtkWidget);
if (!_result.has_value()) {
_loop.exec();
}
QGuiApplicationPrivate::hideModalWindow(this);
return *_result;
}
void OpenWithDialog::handleResponse(OpenWithDialog *dialog, int responseId) {
GAppInfo *chosenAppInfo = nullptr; GAppInfo *chosenAppInfo = nullptr;
dialog->_result = true;
switch (responseId) { switch (responseId) {
case GTK_RESPONSE_OK: case GTK_RESPONSE_OK:
chosenAppInfo = Libs::gtk_app_chooser_get_app_info( chosenAppInfo = Libs::gtk_app_chooser_get_app_info(
Libs::gtk_app_chooser_cast(dialog)); Libs::gtk_app_chooser_cast(dialog->_gtkWidget));
if (chosenAppInfo) { if (chosenAppInfo) {
GList *uris = nullptr; GList *uris = nullptr;
uris = g_list_prepend(uris, g_file_get_uri(file)); uris = g_list_prepend(uris, g_file_get_uri(dialog->_gfileInstance));
g_app_info_launch_uris(chosenAppInfo, uris, nullptr, nullptr); g_app_info_launch_uris(chosenAppInfo, uris, nullptr, nullptr);
g_list_free(uris); g_list_free(uris);
g_object_unref(chosenAppInfo); g_object_unref(chosenAppInfo);
} }
g_object_unref(file);
Libs::gtk_widget_destroy(Libs::gtk_widget_cast(dialog));
break; break;
case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_CANCEL:
case GTK_RESPONSE_DELETE_EVENT: case GTK_RESPONSE_DELETE_EVENT:
g_object_unref(file);
Libs::gtk_widget_destroy(Libs::gtk_widget_cast(dialog));
break; break;
default: default:
dialog->_result = false;
break; break;
} }
dialog->_loop.quit();
} }
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION #endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
@ -141,30 +191,7 @@ bool UnsafeShowOpenWith(const QString &filepath) {
} }
const auto absolutePath = QFileInfo(filepath).absoluteFilePath(); const auto absolutePath = QFileInfo(filepath).absoluteFilePath();
auto gfileInstance = g_file_new_for_path(absolutePath.toUtf8()); return OpenWithDialog(absolutePath).exec();
auto appChooserDialog = Libs::gtk_app_chooser_dialog_new(
nullptr,
GTK_DIALOG_MODAL,
gfileInstance);
g_signal_connect(
appChooserDialog,
"response",
G_CALLBACK(HandleAppChooserResponse),
gfileInstance);
Libs::gtk_widget_realize(appChooserDialog);
if (const auto activeWindow = Core::App().activeWindow()) {
Platform::internal::XSetTransientForHint(
Libs::gtk_widget_get_window(appChooserDialog),
activeWindow->widget().get()->windowHandle()->winId());
}
Libs::gtk_widget_show(appChooserDialog);
return true;
#else // !TDESKTOP_DISABLE_GTK_INTEGRATION #else // !TDESKTOP_DISABLE_GTK_INTEGRATION
return false; return false;
#endif // TDESKTOP_DISABLE_GTK_INTEGRATION #endif // TDESKTOP_DISABLE_GTK_INTEGRATION

View file

@ -74,7 +74,6 @@ bool setupGtkBase(QLibrary &lib_gtk) {
if (!LOAD_SYMBOL(lib_gtk, "gtk_widget_realize", gtk_widget_realize)) return false; if (!LOAD_SYMBOL(lib_gtk, "gtk_widget_realize", gtk_widget_realize)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_widget_hide_on_delete", gtk_widget_hide_on_delete)) return false; if (!LOAD_SYMBOL(lib_gtk, "gtk_widget_hide_on_delete", gtk_widget_hide_on_delete)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_widget_destroy", gtk_widget_destroy)) return false; if (!LOAD_SYMBOL(lib_gtk, "gtk_widget_destroy", gtk_widget_destroy)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_widget_get_type", gtk_widget_get_type)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_get", gtk_clipboard_get)) return false; if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_get", gtk_clipboard_get)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_store", gtk_clipboard_store)) return false; if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_store", gtk_clipboard_store)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_wait_for_contents", gtk_clipboard_wait_for_contents)) return false; if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_wait_for_contents", gtk_clipboard_wait_for_contents)) return false;
@ -236,7 +235,6 @@ f_gtk_widget_get_window gtk_widget_get_window = nullptr;
f_gtk_widget_realize gtk_widget_realize = nullptr; f_gtk_widget_realize gtk_widget_realize = nullptr;
f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete = nullptr; f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete = nullptr;
f_gtk_widget_destroy gtk_widget_destroy = nullptr; f_gtk_widget_destroy gtk_widget_destroy = nullptr;
f_gtk_widget_get_type gtk_widget_get_type = nullptr;
f_gtk_clipboard_get gtk_clipboard_get = nullptr; f_gtk_clipboard_get gtk_clipboard_get = nullptr;
f_gtk_clipboard_store gtk_clipboard_store = nullptr; f_gtk_clipboard_store gtk_clipboard_store = nullptr;
f_gtk_clipboard_wait_for_contents gtk_clipboard_wait_for_contents = nullptr; f_gtk_clipboard_wait_for_contents gtk_clipboard_wait_for_contents = nullptr;

View file

@ -235,14 +235,6 @@ inline GtkWindow *gtk_window_cast(Object *obj) {
return g_type_cic_helper<GtkWindow, Object>(obj, gtk_window_get_type()); return g_type_cic_helper<GtkWindow, Object>(obj, gtk_window_get_type());
} }
typedef GType (*f_gtk_widget_get_type)(void) G_GNUC_CONST;
extern f_gtk_widget_get_type gtk_widget_get_type;
template <typename Object>
inline GtkWidget *gtk_widget_cast(Object *obj) {
return g_type_cic_helper<GtkWidget, Object>(obj, gtk_widget_get_type());
}
typedef GType (*f_gtk_app_chooser_get_type)(void) G_GNUC_CONST; typedef GType (*f_gtk_app_chooser_get_type)(void) G_GNUC_CONST;
extern f_gtk_app_chooser_get_type gtk_app_chooser_get_type; extern f_gtk_app_chooser_get_type gtk_app_chooser_get_type;