Fixes for the native zenity Linux file dialog [patch]


#1

I saw that JUCE uses zenity for its native file dialogs in Linux. This has currently two problems:

The first problem is the file filter is ignored. This is easily fixed by adding the required --file-filter argument.

The second problem is that on a lot of Linux distributions, the zenity window doesn't pop up, unless it's launched directly from a terminal. For users it will seem the application just freezes (it's waiting for zenity to finish), while the zenity popup window is hidden under all the other windows.

This can be solved by setting the WINDOWID environment variable to the window ID of your application window:

ChildProcess doesn't allow adding extra environment variables, so for now I just modify the current environment before starting the child process.

the resulting patch:

--- a/modules/juce_gui_basics/native/juce_linux_FileChooser.cpp
+++ b/modules/juce_gui_basics/native/juce_linux_FileChooser.cpp
@@ -124,6 +124,28 @@ void FileChooser::showPlatformDialog (Array<File>& results,
             if (isSave)       args.add ("--save");
         }
 
+        if (filters.isNotEmpty())
+        {
+            // file filter
+            args.add ("--file-filter");
+            args.add (filters.replaceCharacter (';', ' '));
+            // Adding a second file filter argument allows users to override
+            // the given filter if needed.
+            args.add ("--file-filter");
+            args.add ("All files | *");
+        }
+
+        // make sure zenity actually pops up, by giving it the window ID of the
+        // parent component
+        TopLevelWindow* top = TopLevelWindow::getActiveTopLevelWindow();
+        if (top && top->getPeer())
+        {
+            unsigned long long handle = reinterpret_cast<unsigned long long>(to
+            char envVar[64];
+            snprintf(envVar, 64, "%llu", handle);
+            setenv("WINDOWID", envVar, true);
+        }
+
         if (file.isDirectory())
             file.setAsCurrentWorkingDirectory();
         else if (file.getParentDirectory().exists())

--

Roeland

 


#2

will be nice to have kdialog supporting the window-Id as well. according to "kdialog --help":

  --attach <winid>          Makes the dialog transient for an X app specified by winid

 


#3

Excellent stuff, thanks!

One of the lines in the code you posted seems to be truncated though - for the window ID, is it just the value of getWindowHandle() converted to a decimal string?


#4

Yes, it is. The full line is:

unsigned long long handle = reinterpret_cast<unsigned long long>(top->getPeer()->getNativeHandle());


--
Roeland


#5

I already added some changes yesterday - let me know if it works for you.


#6

Yes, it works when using Zenity. I don't have a machine with KDE installed so I can't tell for the kdialog case.

--
Roeland