Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Use GtkFileChooserNative to support the XDG Desktop Portal specification #19159

Merged
merged 50 commits into from Apr 1, 2021

Conversation

tristan957
Copy link
Contributor

@tristan957 tristan957 commented Jul 8, 2019

Description of Change

With this commit, users on KDE/plasma will finally have support in Electron for their native file chooser dialogs. Fixes #2911.

Checklist

Release Notes

Notes: Added support for alternative file choosers on Linux through the usage of the XDG Desktop Portal in GtkFileChooserNative.

This PR is backwards compatible to support platforms like Ubuntu 16.04/14.04 whose GTK versions are less than 3.20.

@electron-cation electron-cation bot added the new-pr 🌱 label Jul 8, 2019
@welcome
Copy link

@welcome welcome bot commented Jul 8, 2019

💖 Thanks for opening this pull request! 💖

We use semantic commit messages to streamline the release process. Before your pull request can be merged, you should update your pull request title to start with a semantic prefix.

Examples of commit messages with semantic prefixes:

  • fix: don't overwrite prevent_default if default wasn't prevented
  • feat: add app.isPackaged() method
  • docs: app.isDefaultProtocolClient is now available on Linux

Things that will help get your PR across the finish line:

  • Follow the JavaScript, C++, and Python coding style.
  • Run npm run lint locally to catch formatting errors earlier.
  • Document any user-facing changes you've made following the documentation styleguide.
  • Include tests when adding/changing behavior.
  • Include screenshots and animated GIFs whenever possible.

We get a lot of pull requests on this repo, so please be patient and we will get back to you as soon as we can.

@tristan957
Copy link
Contributor Author

@tristan957 tristan957 commented Jul 8, 2019

I would appreciate guidance in getting this PR to completion with regard to CI builds, styling, implementation, and testing.

Off the bat, there are a few issues with this PR:

  • I currently am not sure how to cast a GtkFileChooserNative to a GtkNativeDialog
  • Does the include of dlfcn.h need to be guarded in anyway?

I am going to take a look at the Chromium source code, and see what I find.

@tristan957
Copy link
Contributor Author

@tristan957 tristan957 commented Jul 8, 2019

Please note that this was not on my dev machine, so I could not compile to check my work.

@tristan957
Copy link
Contributor Author

@tristan957 tristan957 commented Jul 8, 2019

Lint should be fixed. Apologies.

@tristan957
Copy link
Contributor Author

@tristan957 tristan957 commented Jul 8, 2019

@TingPing @ckerr since you guys were a part of the last PR, can you provide assistance on this one?

@TingPing specifically if you see anything that can be done about casting a GtkFileChooserNative to GtkNativeDialog without the macro GTK_NATIVE_DIALOG that would be extremely helpful. This is dependent on whether or not GTK stays dynamically loaded or not.

@TingPing
Copy link
Contributor

@TingPing TingPing commented Jul 9, 2019

Thanks a lot for picking this up!

@TingPing specifically if you see anything that can be done about casting a GtkFileChooserNative to GtkNativeDialog without the macro GTK_NATIVE_DIALOG that would be extremely helpful.

Honestly I think its acceptable to just ignore in this specific case and cast away to void*. (EDIT: Oh sorry, C++ is more strict about that right. I'm not sure off-hand then)

Hardcoding -ldl is not ideal as that isn't used on all unix-like systems.

Since this already depends on GLib I suggest using GModule which avoids the linking and header portability concerns.

You'd then use g_module_open(), g_module_symbol(), etc: https://developer.gnome.org/glib/stable/glib-Dynamic-Loading-of-Modules.html

@tristan957
Copy link
Contributor Author

@tristan957 tristan957 commented Jul 9, 2019

Thanks for the link @TingPing. I will take a look at GModule later today and update the PR accordingly.

@tristan957
Copy link
Contributor Author

@tristan957 tristan957 commented Jul 9, 2019

Call for action: I do not currently run a KDE Plasma desktop. If someone who does could inevitably test this PR, that would be great.

@tristan957
Copy link
Contributor Author

@tristan957 tristan957 commented Jul 9, 2019

@TingPing I was more wondering if the GtkFileChooserNative object is located in memory at the same spot as the GtkNativeDialog or does GTK_NATIVE_DIALOG move the pointer. I don't have a complete grasp of the GObject type system just yet. I can write it, but I don't know technicalities like this. If they are at the same spot, I can avoid the cast.

@tristan957 tristan957 force-pushed the master branch 4 times, most recently from 8fcc326 to 4d36308 Compare Jul 9, 2019
@tristan957
Copy link
Contributor Author

@tristan957 tristan957 commented Jul 9, 2019

This is going to require a little more effort than previously thought. Still doable I think, but I am under the impression _dialog is going to have to change its type to a GtkFileChooser. I am also going to have to dip into libgtkui::SetGtkTransientForAura to account for this.

@electron-cation electron-cation bot removed the new-pr 🌱 label Jul 9, 2019
@tristan957
Copy link
Contributor Author

@tristan957 tristan957 commented Jul 9, 2019

The behavior of FileDialog::RunAsynchronous needs to be re-evaluated as "delete-event" does not exist for GtkNativeDialog & GtkFileChooserNative. Also there is no "present with time" api, so that will need to be reevaluated.

Both CHROME_CALLBACKS need to be adjusted.

I am going to need some guidance on libgtkui::SetGtkTransientForAura. I cannot find the definition. I just need to overload the function to have a SetGtkTransientForAura(void* dialog, aura::Window* parent). I need use the underlying GtkNativeDialog if GTK_IS_WIDGET(dialog) fails because that API provides gtk_native_dialog_set_transient_for.

Any skilled Electron contributor would be a huge help at this point.

@tristan957 tristan957 force-pushed the master branch 3 times, most recently from 72a53d3 to 6dd34aa Compare Jul 9, 2019
@tristan957
Copy link
Contributor Author

@tristan957 tristan957 commented Jul 10, 2019

I have also learned that preview widgets are ignored in the Native API. What should be the best course of action regarding that? Leaving the preview widget code in regardless of what dialog is actually being used seems best to me instead of making conditional checks around the code.

@tristan957 tristan957 force-pushed the master branch 2 times, most recently from baf26ce to a36ba29 Compare Jul 10, 2019
@tristan957
Copy link
Contributor Author

@tristan957 tristan957 commented Jul 10, 2019

I have gotten the build where it only fails on the libgtkui::SetGtkTransientForAura call. Looking at the codebase, this seems like something in the chromium code base. Relevant: https://github.com/chromium/chromium/blob/5250f0fc05c7af7cf4512714ac832749547b1bd0/chrome/browser/ui/libgtkui/gtk_util.cc#L137.

So...I think this leaves a couple of options. Ask the Chromium developers for an overloaded function to be added, or mirror the function in Electron. I am thinking mirroring the function in Electron will work best.

@tristan957
Copy link
Contributor Author

@tristan957 tristan957 commented Jul 10, 2019

I have come up with the following patch

diff --git a/shell/browser/ui/file_dialog_gtk.cc b/shell/browser/ui/file_dialog_gtk.cc
index ef6d3a545..50e536ad5 100644
--- a/shell/browser/ui/file_dialog_gtk.cc
+++ b/shell/browser/ui/file_dialog_gtk.cc
@@ -77,7 +77,10 @@ class FileChooserDialog {
 
     if (parent_) {
       parent_->SetEnabled(false);
-      libgtkui::SetGtkTransientForAura(dialog_, parent_->GetNativeWindow());
+      if (GTK_IS_WIDGET(dialog_))
+        libgtkui::SetGtkTransientForAura(dialog_, parent_->GetNativeWindow());
+      else
+        SetGtkTransientForAura(parent_->GetNativeWindow());
       if (GTK_IS_WINDOW(dialog_)) {
         gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
       } else {
@@ -225,6 +228,19 @@ class FileChooserDialog {
   CHROMEG_CALLBACK_0(FileChooserDialog, void, OnUpdatePreview, GtkFileChooser*);
 
   DISALLOW_COPY_AND_ASSIGN(FileChooserDialog);
+
+  // Sets |dialog| as transient for |parent|, which will keep it on top and
+  // center it above |parent|. Do nothing if |parent| is nullptr.
+  void SetGtkTransientForAura(aura::Window* parent) {
+    if (!parent || !parent->GetHost())
+      return;
+
+    void (*dl_gtk_native_dialog_set_transient_for)(void*, GtkWindow*) = nullptr;
+    g_module_symbol(
+        gtk_module_, "gtk_native_dialog_set_transient_for",
+        reinterpret_cast<void**>(&dl_gtk_native_dialog_set_transient_for);
+    dl_gtk_native_dialog_set_transient_for(dialog_, reinterpret_cast<GtkWindow*>(parent));
+  }
 };
 
 void FileChooserDialog::OnFileDialogResponse(GtkFileChooser* widget, int response) {

I have decided to merge this patch for the time being. It can be reverted though.

@tristan957 tristan957 force-pushed the master branch 2 times, most recently from c735f82 to fb7b5ac Compare Jul 10, 2019
@MatthewForrester
Copy link

@MatthewForrester MatthewForrester commented Jul 4, 2021

Thank you to everyone who has worked on this. It will be much appreciated by KDE users.

lionirdeadman pushed a commit to lionirdeadman/electron that referenced this issue Jul 4, 2021
…ification (electron#19159)

* feat: Use GtkFileChooserNative if available to support XDG portals

With this commit, users on KDE/plasma will finally have support in
Electron for their native file choosers dialogs.

* fix: namespace

* fix: labels were reversed

* fix: lint issue

* fix: clean up some implementation

* fix: remove deprecation branch

* fix: remove unused header

* fix: remove unused gi18n.h include

Not sure why this is

* fix: add the set_data call into the mirrored SetGtkTransientForAura func

* fix: remove gmodule support and use native for the dialog regardless

* fix: undo yarn.lock changes

* fix: lint

* fix: remove x11 unncessary x11 include

* fix: lint

* fix: remove SetGtkTransientForAura

* Revert "fix: remove gmodule support and use native for the dialog regardless"

This reverts commit 062db59.

* fix: add support in a backwards compatible way

Use GModule to dynamically load functions from libgtk in order to
support GtkNativeDialog.

* fix: lint

* docs: update comment

* Revert "fix: remove x11 unncessary x11 include"

This reverts commit 589cff5.

* fix: compiler errors

* fix: int -> x11::time

* fix: move GtkNativeDialog static data to global state

* fix: revert yarn.lock change

* update: for code review comments

* fix: remove functional header

* fix: variable name

* fix: rename GTK native initalization func

* Help out the compiler

* Help out the compiler

* Help out the compiler

* Fix function signature

* Remove unused header

* Rename optional boolean for GtkFileChooserNative support

* Add back in USE_X11 check

* Satisfy linter

* Resatisfy linter

* Fix alignment of if

* Fix alignment of arguments

* linting...

* fix: add back in the i18n hack

* fix: lint

* Respond to some review comments

* fix: lint

* Make adding filter agnostic

* fix: transform is in place

* fix: remove std::transform because not c++17

* Remove unused include

* fix: address Cheng's review

* fix: Remove unused header
@tristan957 tristan957 deleted the master branch Aug 6, 2021
proletarius101 added a commit to flathub/net.agalwood.Motrix that referenced this issue Aug 15, 2021
`GtkFileChooserNative` has merged and will be landed in Electron 14
(electron/electron#19159)
@squalou
Copy link

@squalou squalou commented Sep 1, 2021

Hi,
I'm wondering : has it landed in 14.0.0 released yesterday ?
(I've beeing trying to use it without a great success, with portal-kde installed, GTK_USE_PORTAL set to 1. )

[Edit] : no consistent result depending on distributions. Cannot have ubuntu family work. Did have some success on Arch. Weird.

@vchernin
Copy link

@vchernin vchernin commented Oct 2, 2021

No one’s been able to figure out the cause of this feature seemingly not working on Ubuntu (or in Flatpak) so I’ve opened a follow up: #31258

If anyone has ideas on what might be the problem please share them.

csett86 added a commit to jitsi/jitsi-meet-electron that referenced this issue Dec 1, 2021
Contains:

- Chromium 91 -> 96, including multiple webrtc and security fixes
- Linux file chooser portal fixes (electron/electron#19159)

Closes: #629
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-review/requested 🗳 semver/minor
Projects
None yet
Development

Successfully merging this pull request may close these issues.