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

Implement D-Bus portal backend #48

Merged
merged 3 commits into from
Jan 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,28 @@ jobs:
build/src/libnfd.a
build/test/test_*

build-ubuntu-portal-gcc:

name: Ubuntu latest, desktop portals - GCC
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v2
- name: Installing Dependencies
run: sudo apt-get update && sudo apt-get install libdbus-1-dev
- name: Configure
run: mkdir build && mkdir install && cd build && cmake -DCMAKE_INSTALL_PREFIX="../install" -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-Wall -Wextra -Werror -pedantic" -DNFD_PORTAL=ON -DNFD_BUILD_TESTS=ON ..
- name: Build
run: cmake --build build --target install
- name: Upload test binaries
uses: actions/upload-artifact@v2
with:
name: Ubuntu latest, desktop portals - GCC
path: |
build/src/libnfd.a
build/test/test_*

build-ubuntu-clang:

name: Ubuntu latest - Clang
Expand Down
35 changes: 31 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ This library is based on Michael Labbe's Native File Dialog ([mlabbe/nativefiled

Features:

- Lean C API, static library -- no C++/ObjC runtime needed
- Supports Windows (MSVC, MinGW), MacOS (Clang), and Linux (GCC, Clang)
- Lean C API, static library — no C++/ObjC runtime needed
- Supports Windows (MSVC, MinGW), MacOS (Clang), and Linux (GTK, portal) (GCC, Clang)
- Zlib licensed
- Friendly names for filters (e.g. `C/C++ Source files (*.c;*.cpp)` instead of `(*.c;*.cpp)`) on platforms that support it
- Automatically append file extension on platforms where users expect it
- Support for setting a default folder path
- Support for setting a default file name (e.g. `Untitled.c`)
- Consistent UTF-8 support on all platforms
- Native character set (UTF-16 `wchar_t`) support on Windows
- Initialization and de-initialization of platform library (e.g. COM (Windows) / GTK (Linux)) decoupled from dialog functions, so applications can choose when to initialize/de-initialize
- Initialization and de-initialization of platform library (e.g. COM (Windows) / GTK (Linux GTK) / D-Bus (Linux portal)) decoupled from dialog functions, so applications can choose when to initialize/de-initialize
- Multiple file selection support (for file open dialog)
- Support for Vista's modern `IFileDialog` on Windows
- No third party dependencies
Expand All @@ -36,6 +36,7 @@ Features added in Native File Dialog Extended:
- Automatically appending file extensions
- Support for setting a default file name
- Native character set (UTF-16 `wchar_t`) support on Windows
- xdg-desktop-portal support on Linux that opens the "native" file chooser (see "Usage" section below)
- Initialization and de-initialization of platform library decoupled from file dialog functions
- Modern CMake build system
- Optional C++ wrapper with `unique_ptr` auto-freeing semantics and optional parameters
Expand Down Expand Up @@ -116,6 +117,10 @@ to build a debug version of the library instead.
If you want to build the sample programs,
add `-DNFD_BUILD_TESTS=ON` (sample programs are not built by default).

On Linux, if you want to use the Flatpak desktop portal instead of GTK, add `-DNFD_PORTAL=ON`. (Otherwise, GTK will be used.) See the "Usage" section below for more information.

See the [CI build file](.github/workflows/cmake.yml) for some example build commands.

### Visual Studio on Windows
Recent versions of Visual Studio have CMake support built into the IDE.
You should be able to "Open Folder" in the project root directory,
Expand All @@ -135,7 +140,12 @@ and it probably works on Visual Studio 2017 too.
## Dependencies

### Linux
`apt-get libgtk-3-dev` installs the GTK+3 dependency on debian based systems.

#### GTK (default)
Make sure `libgtk-3-dev` is installed on your system.

#### Portal
Make sure `libdbus-1-dev` is installed on your system.

### MacOS
On MacOS, add `AppKit` to the list of frameworks.
Expand Down Expand Up @@ -230,11 +240,28 @@ NFD_Quit(); // deinitialize NFDe first
SDL_Quit(); // Then deinitialize SDL2
```

## Using xdg-desktop-portal on Linux

On Linux, you can use the portal implementation instead of GTK, which will open the "native" file chooser selected by the OS or customized by the user. The user must have `xdg-desktop-portal` and a suitable backend installed (this comes pre-installed with most common desktop distros), otherwise `NFD_ERROR` will be returned.

The portal implementation is much less battle-tested than the GTK implementation. There may be bugs — please report them on the issue tracker.

To use the portal implementation, add `-DNFD_PORTAL=ON` to the build command.

*Note: Setting a default path is not supported by the portal implementation, and any default path passed to NFDe will be ignored. This is a limitation of the portal API, so there is no way NFDe can work around it.*

### What is a portal?

Unlike Windows and MacOS, Linux does not have a file chooser baked into the operating system. Linux applications that want a file chooser usually link with a library that provides one (such as GTK, as in the Linux screenshot above). This is a mostly acceptable solution that many applications use, but may make the file chooser look foreign on non-GTK distros.

Flatpak was introduced in 2015, and with it came a standardized interface to open a file chooser. Applications using this interface did not need to come with a file chooser, and could use the one provided by Flatpak. This interface became known as the desktop portal, and its use expanded to non-Flatpak applications. Now, most major desktop Linux distros come with the desktop portal installed, with file choosers that fit the theme of the distro. Users can also install a different portal backend if desired. There are currently two known backends: GTK and KDE. (XFCE does not currently seem to have a portal backend.)

# Known Limitations #

- No support for Windows XP's legacy dialogs such as `GetOpenFileName`. (There are no plans to support this; you shouldn't be still using Windows XP anyway.)
- No Emscripten (WebAssembly) bindings. (This might get implemented if I decide to port Circuit Sandbox for the web, but I don't think there is any way to implement a web-based folder picker.)
- GTK dialogs don't set the existing window as parent, so if users click the existing window while the dialog is open then the dialog will go behind it. GTK writes a warning to stdout or stderr about this.
- Portal dialogs (the alternative to GTK on Linux) don't support a default path. Any default path you supply will be ignored.
- This library is not compatible with the original Native File Dialog library. Things might break if you use both in the same project. (There are no plans to support this; you have to use one or the other.)
- This library does not explicitly dispatch calls to the UI thread. This may lead to crashes if you call functions from other threads when the platform does not support it (e.g. MacOS). Users are generally expected to call NFDe from an appropriate UI thread (i.e. the thread performing the UI event loop).

Expand Down
31 changes: 24 additions & 7 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,17 @@ endif()

if(nfd_PLATFORM STREQUAL PLATFORM_LINUX)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
message("Using GTK version: ${GTK3_VERSION}")
list(APPEND SOURCE_FILES nfd_gtk.cpp)
# for Linux, we support GTK3 and xdg-desktop-portal
option(NFD_PORTAL "Use xdg-desktop-portal instead of GTK" OFF)
if(NOT NFD_PORTAL)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
message("Using GTK version: ${GTK3_VERSION}")
list(APPEND SOURCE_FILES nfd_gtk.cpp)
else()
pkg_check_modules(DBUS REQUIRED dbus-1)
message("Using DBUS version: ${DBUS_VERSION}")
list(APPEND SOURCE_FILES nfd_portal.cpp)
endif()
endif()

if(nfd_PLATFORM STREQUAL PLATFORM_MACOS)
Expand All @@ -31,10 +39,19 @@ target_include_directories(${TARGET_NAME}
PUBLIC include/)

if(nfd_PLATFORM STREQUAL PLATFORM_LINUX)
target_include_directories(${TARGET_NAME}
PRIVATE ${GTK3_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME}
PRIVATE ${GTK3_LIBRARIES})
if(NOT NFD_PORTAL)
target_include_directories(${TARGET_NAME}
PRIVATE ${GTK3_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME}
PRIVATE ${GTK3_LIBRARIES})
else()
target_include_directories(${TARGET_NAME}
PRIVATE ${DBUS_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME}
PRIVATE ${DBUS_LIBRARIES})
target_compile_definitions(${TARGET_NAME}
PUBLIC NFD_PORTAL)
endif()
endif()

if(nfd_PLATFORM STREQUAL PLATFORM_MACOS)
Expand Down
19 changes: 19 additions & 0 deletions src/include/nfd.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,28 @@ typedef char nfdnchar_t;

/* opaque data structure -- see NFD_PathSet_* */
typedef void nfdpathset_t;
#ifndef NFD_PORTAL
typedef struct {
void* ptr;
} nfdpathsetenum_t;
#else
typedef struct {
void* d1;
void* d2;
unsigned int d3;
int d4;
int d5;
int d6;
int d7;
int d8;
int d9;
int d10;
int d11;
int p1;
void* p2;
void* p3;
} nfdpathsetenum_t;
#endif

typedef unsigned int nfdfiltersize_t;

Expand Down
Loading