summaryrefslogtreecommitdiffstats
path: root/widget
diff options
context:
space:
mode:
authorAscrod <32915892+Ascrod@users.noreply.github.com>2019-08-10 17:26:31 -0400
committerAscrod <32915892+Ascrod@users.noreply.github.com>2019-08-10 17:26:31 -0400
commit47c48dfcb87a574f6b96f3abf3ed14b9b08b2371 (patch)
tree0903b79fb1799e91a22d2ecb437e21588172fdc4 /widget
parentb5cbb4d2f8d43469d1eb80cfcff5eae4dee706e2 (diff)
downloadUXP-47c48dfcb87a574f6b96f3abf3ed14b9b08b2371.tar
UXP-47c48dfcb87a574f6b96f3abf3ed14b9b08b2371.tar.gz
UXP-47c48dfcb87a574f6b96f3abf3ed14b9b08b2371.tar.lz
UXP-47c48dfcb87a574f6b96f3abf3ed14b9b08b2371.tar.xz
UXP-47c48dfcb87a574f6b96f3abf3ed14b9b08b2371.zip
Issue #999 - Use xdg-desktop-portal for file selection dialogs on Linux.
Diffstat (limited to 'widget')
-rw-r--r--widget/gtk/nsFilePicker.cpp131
-rw-r--r--widget/gtk/nsFilePicker.h17
2 files changed, 109 insertions, 39 deletions
diff --git a/widget/gtk/nsFilePicker.cpp b/widget/gtk/nsFilePicker.cpp
index 172cb4444..a2d2e1cff 100644
--- a/widget/gtk/nsFilePicker.cpp
+++ b/widget/gtk/nsFilePicker.cpp
@@ -197,7 +197,7 @@ ReadMultipleFiles(gpointer filename, gpointer array)
}
void
-nsFilePicker::ReadValuesFromFileChooser(GtkWidget *file_chooser)
+nsFilePicker::ReadValuesFromFileChooser(void *file_chooser)
{
mFiles.Clear();
@@ -389,19 +389,10 @@ nsFilePicker::Open(nsIFilePickerShownCallback *aCallback)
if (!mOkButtonLabel.IsEmpty()) {
accept_button = buttonLabel.get();
} else {
- accept_button = (action == GTK_FILE_CHOOSER_ACTION_SAVE) ?
- GTK_STOCK_SAVE : GTK_STOCK_OPEN;
+ accept_button = nullptr;
}
- GtkWidget *file_chooser =
- gtk_file_chooser_dialog_new(title, parent_widget, action,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- accept_button, GTK_RESPONSE_ACCEPT,
- nullptr);
- gtk_dialog_set_alternative_button_order(GTK_DIALOG(file_chooser),
- GTK_RESPONSE_ACCEPT,
- GTK_RESPONSE_CANCEL,
- -1);
+ void *file_chooser = GtkFileChooserNew(title.get(), parent_widget, action, accept_button);
if (mAllowURLs) {
gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(file_chooser), FALSE);
}
@@ -412,11 +403,7 @@ nsFilePicker::Open(nsIFilePickerShownCallback *aCallback)
g_signal_connect(file_chooser, "update-preview", G_CALLBACK(UpdateFilePreviewWidget), img_preview);
}
- GtkWindow *window = GTK_WINDOW(file_chooser);
- gtk_window_set_modal(window, TRUE);
- if (parent_widget) {
- gtk_window_set_destroy_with_parent(window, TRUE);
- }
+ GtkFileChooserSetModal(file_chooser, parent_widget, TRUE);
NS_ConvertUTF16toUTF8 defaultName(mDefault);
switch (mMode) {
@@ -454,18 +441,21 @@ nsFilePicker::Open(nsIFilePickerShownCallback *aCallback)
// Otherwise, if our dialog gets destroyed, we'll lose the dialog's
// delegate by the time this gets processed in the event loop.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1166741
- GtkDialog *dialog = GTK_DIALOG(file_chooser);
- GtkContainer *area = GTK_CONTAINER(gtk_dialog_get_content_area(dialog));
- gtk_container_forall(area, [](GtkWidget *widget,
- gpointer data) {
- if (GTK_IS_FILE_CHOOSER_WIDGET(widget)) {
- auto result = static_cast<GtkFileChooserWidget**>(data);
- *result = GTK_FILE_CHOOSER_WIDGET(widget);
- }
- }, &mFileChooserDelegate);
-
- if (mFileChooserDelegate)
- g_object_ref(mFileChooserDelegate);
+ if (GTK_IS_DIALOG(file_chooser)) {
+ GtkDialog *dialog = GTK_DIALOG(file_chooser);
+ GtkContainer *area = GTK_CONTAINER(gtk_dialog_get_content_area(dialog));
+ gtk_container_forall(area, [](GtkWidget *widget,
+ gpointer data) {
+ if (GTK_IS_FILE_CHOOSER_WIDGET(widget)) {
+ auto result = static_cast<GtkFileChooserWidget**>(data);
+ *result = GTK_FILE_CHOOSER_WIDGET(widget);
+ }
+ }, &mFileChooserDelegate);
+
+ if (mFileChooserDelegate) {
+ g_object_ref(mFileChooserDelegate);
+ }
+ }
#endif
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_chooser),
@@ -473,7 +463,9 @@ nsFilePicker::Open(nsIFilePickerShownCallback *aCallback)
}
}
- gtk_dialog_set_default_response(GTK_DIALOG(file_chooser), GTK_RESPONSE_ACCEPT);
+ if (GTK_IS_DIALOG(file_chooser)) {
+ gtk_dialog_set_default_response(GTK_DIALOG(file_chooser), GTK_RESPONSE_ACCEPT);
+ }
int32_t count = mFilters.Length();
for (int32_t i = 0; i < count; ++i) {
@@ -517,14 +509,13 @@ nsFilePicker::Open(nsIFilePickerShownCallback *aCallback)
mCallback = aCallback;
NS_ADDREF_THIS();
g_signal_connect(file_chooser, "response", G_CALLBACK(OnResponse), this);
- g_signal_connect(file_chooser, "destroy", G_CALLBACK(OnDestroy), this);
- gtk_widget_show(file_chooser);
+ GtkFileChooserShow(file_chooser);
return NS_OK;
}
/* static */ void
-nsFilePicker::OnResponse(GtkWidget* file_chooser, gint response_id,
+nsFilePicker::OnResponse(void* file_chooser, gint response_id,
gpointer user_data)
{
static_cast<nsFilePicker*>(user_data)->
@@ -539,7 +530,7 @@ nsFilePicker::OnDestroy(GtkWidget* file_chooser, gpointer user_data)
}
void
-nsFilePicker::Done(GtkWidget* file_chooser, gint response)
+nsFilePicker::Done(void* file_chooser, gint response)
{
mRunning = false;
@@ -583,7 +574,7 @@ nsFilePicker::Done(GtkWidget* file_chooser, gint response)
// requests that any remaining references be released, but the reference
// count will not be decremented again if GtkWindow's reference has already
// been released.
- gtk_widget_destroy(file_chooser);
+ GtkFileChooserDestroy(file_chooser);
#if (MOZ_WIDGET_GTK == 3)
if (mFileChooserDelegate) {
@@ -608,3 +599,73 @@ nsFilePicker::Done(GtkWidget* file_chooser, gint response)
}
NS_RELEASE_THIS();
}
+
+// All below functions available as of GTK 3.20+
+
+void *
+nsFilePicker::GtkFileChooserNew(
+ const gchar *title, GtkWindow *parent,
+ GtkFileChooserAction action,
+ const gchar *accept_label)
+{
+ static auto sGtkFileChooserNativeNewPtr = (void * (*)(
+ const gchar *, GtkWindow *,
+ GtkFileChooserAction,
+ const gchar *, const gchar *))
+ dlsym(RTLD_DEFAULT, "gtk_file_chooser_native_new");
+ if (sGtkFileChooserNativeNewPtr != nullptr) {
+ return (*sGtkFileChooserNativeNewPtr)(title, parent, action, accept_label, nullptr);
+ }
+ if (accept_label == nullptr) {
+ accept_label = (action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ ? GTK_STOCK_SAVE : GTK_STOCK_OPEN;
+ }
+ GtkWidget *file_chooser = gtk_file_chooser_dialog_new(title, parent, action,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ accept_label, GTK_RESPONSE_ACCEPT, nullptr);
+ gtk_dialog_set_alternative_button_order(GTK_DIALOG(file_chooser),
+ GTK_RESPONSE_ACCEPT, GTK_RESPONSE_CANCEL, -1);
+ return file_chooser;
+}
+
+void
+nsFilePicker::GtkFileChooserShow(void *file_chooser)
+{
+ static auto sGtkNativeDialogShowPtr = (void (*)(void *))
+ dlsym(RTLD_DEFAULT, "gtk_native_dialog_show");
+ if (sGtkNativeDialogShowPtr != nullptr) {
+ (*sGtkNativeDialogShowPtr)(file_chooser);
+ } else {
+ g_signal_connect(file_chooser, "destroy", G_CALLBACK(OnDestroy), this);
+ gtk_widget_show(GTK_WIDGET(file_chooser));
+ }
+}
+
+void
+nsFilePicker::GtkFileChooserDestroy(void *file_chooser)
+{
+ static auto sGtkNativeDialogDestroyPtr = (void (*)(void *))
+ dlsym(RTLD_DEFAULT, "gtk_native_dialog_destroy");
+ if (sGtkNativeDialogDestroyPtr != nullptr) {
+ (*sGtkNativeDialogDestroyPtr)(file_chooser);
+ } else {
+ gtk_widget_destroy(GTK_WIDGET(file_chooser));
+ }
+}
+
+void
+nsFilePicker::GtkFileChooserSetModal(void *file_chooser,
+ GtkWindow *parent_widget, gboolean modal)
+{
+ static auto sGtkNativeDialogSetModalPtr = (void (*)(void *, gboolean))
+ dlsym(RTLD_DEFAULT, "gtk_native_dialog_set_modal");
+ if (sGtkNativeDialogSetModalPtr != nullptr) {
+ (*sGtkNativeDialogSetModalPtr)(file_chooser, modal);
+ } else {
+ GtkWindow *window = GTK_WINDOW(file_chooser);
+ gtk_window_set_modal(window, modal);
+ if (parent_widget != nullptr) {
+ gtk_window_set_destroy_with_parent(window, modal);
+ }
+ }
+}
diff --git a/widget/gtk/nsFilePicker.h b/widget/gtk/nsFilePicker.h
index 2b5042098..f462ca324 100644
--- a/widget/gtk/nsFilePicker.h
+++ b/widget/gtk/nsFilePicker.h
@@ -48,12 +48,12 @@ public:
protected:
virtual ~nsFilePicker();
- void ReadValuesFromFileChooser(GtkWidget *file_chooser);
+ void ReadValuesFromFileChooser(void *file_chooser);
- static void OnResponse(GtkWidget* dialog, gint response_id,
+ static void OnResponse(void* dialog, gint response_id,
gpointer user_data);
- static void OnDestroy(GtkWidget* dialog, gpointer user_data);
- void Done(GtkWidget* dialog, gint response_id);
+ static void OnDestroy(GtkWidget* file_chooser, gpointer user_data);
+ void Done(void* file_chooser, gint response_id);
nsCOMPtr<nsIWidget> mParentWidget;
nsCOMPtr<nsIFilePickerShownCallback> mCallback;
@@ -74,6 +74,15 @@ protected:
private:
static nsIFile *mPrevDisplayDirectory;
+ void *GtkFileChooserNew(
+ const gchar *title, GtkWindow *parent,
+ GtkFileChooserAction action,
+ const gchar *accept_label);
+ void GtkFileChooserShow(void *file_chooser);
+ void GtkFileChooserDestroy(void *file_chooser);
+ void GtkFileChooserSetModal(void *file_chooser, GtkWindow* parent_widget,
+ gboolean modal);
+
#if (MOZ_WIDGET_GTK == 3)
GtkFileChooserWidget *mFileChooserDelegate;
#endif