diff --git a/src/include/nfd.h b/src/include/nfd.h index 9aaf6fc..9546294 100644 --- a/src/include/nfd.h +++ b/src/include/nfd.h @@ -93,12 +93,32 @@ typedef struct { typedef nfdu8filteritem_t nfdnfilteritem_t; #endif // _WIN32 +// The native window handle type. +enum { + NFD_WINDOW_HANDLE_TYPE_UNSET = 0, + // Windows: handle is HWND (the Windows API typedefs this to void*) + NFD_WINDOW_HANDLE_TYPE_WINDOWS = 1, + // Cocoa: handle is NSWindow* + NFD_WINDOW_HANDLE_TYPE_COCOA = 2, + // X11: handle is Window + NFD_WINDOW_HANDLE_TYPE_X11 = 3, + // Wayland: handle is wl_surface* + NFD_WINDOW_HANDLE_TYPE_WAYLAND = 4, +}; +// The native window handle. If using a platform abstraction framework (e.g. SDL), this should be +// obtained using the corresponding NFD glue header (e.g. nfd_sdl.h). +typedef struct { + size_t type; // this is one of the values of the enum above + void* handle; +} nfdwindowhandle_t; + typedef size_t nfdversion_t; typedef struct { const nfdu8filteritem_t* filterList; nfdfiltersize_t filterCount; const nfdu8char_t* defaultPath; + nfdwindowhandle_t parentWindow; } nfdopendialogu8args_t; #ifdef _WIN32 @@ -106,6 +126,7 @@ typedef struct { const nfdnfilteritem_t* filterList; nfdfiltersize_t filterCount; const nfdnchar_t* defaultPath; + nfdwindowhandle_t parentWindow; } nfdopendialognargs_t; #else typedef nfdopendialogu8args_t nfdopendialognargs_t; @@ -116,6 +137,7 @@ typedef struct { nfdfiltersize_t filterCount; const nfdu8char_t* defaultPath; const nfdu8char_t* defaultName; + nfdwindowhandle_t parentWindow; } nfdsavedialogu8args_t; #ifdef _WIN32 @@ -124,6 +146,7 @@ typedef struct { nfdfiltersize_t filterCount; const nfdnchar_t* defaultPath; const nfdnchar_t* defaultName; + nfdwindowhandle_t parentWindow; } nfdsavedialognargs_t; #else typedef nfdsavedialogu8args_t nfdsavedialognargs_t; @@ -131,11 +154,13 @@ typedef nfdsavedialogu8args_t nfdsavedialognargs_t; typedef struct { const nfdu8char_t* defaultPath; + nfdwindowhandle_t parentWindow; } nfdpickfolderu8args_t; #ifdef _WIN32 typedef struct { const nfdnchar_t* defaultPath; + nfdwindowhandle_t parentWindow; } nfdpickfoldernargs_t; #else typedef nfdpickfolderu8args_t nfdpickfoldernargs_t; diff --git a/src/nfd_win.cpp b/src/nfd_win.cpp index 2623c46..6e5fdff 100644 --- a/src/nfd_win.cpp +++ b/src/nfd_win.cpp @@ -284,6 +284,13 @@ nfdresult_t AddOptions(IFileDialog* dialog, FILEOPENDIALOGOPTIONS options) { } return NFD_OKAY; } + +HWND GetNativeWindowHandle(const nfdwindowhandle_t& nfd_handle) { + if (nfd_handle.type != NFD_WINDOW_HANDLE_TYPE_WINDOWS) { + return nullptr; + } + return static_cast(nfd_handle.handle); +} } // namespace const char* NFD_GetError(void) { @@ -382,7 +389,7 @@ nfdresult_t NFD_OpenDialogN_With_Impl(nfdversion_t version, } // Show the dialog. - result = fileOpenDialog->Show(nullptr); + result = fileOpenDialog->Show(GetNativeWindowHandle(args->parentWindow)); if (SUCCEEDED(result)) { // Get the file name ::IShellItem* psiResult; @@ -463,7 +470,7 @@ nfdresult_t NFD_OpenDialogMultipleN_With_Impl(nfdversion_t version, } // Show the dialog. - result = fileOpenDialog->Show(nullptr); + result = fileOpenDialog->Show(GetNativeWindowHandle(args->parentWindow)); if (SUCCEEDED(result)) { ::IShellItemArray* shellItems; result = fileOpenDialog->GetResults(&shellItems); @@ -542,7 +549,7 @@ nfdresult_t NFD_SaveDialogN_With_Impl(nfdversion_t version, } // Show the dialog. - result = fileSaveDialog->Show(nullptr); + result = fileSaveDialog->Show(GetNativeWindowHandle(args->parentWindow)); if (SUCCEEDED(result)) { // Get the file name ::IShellItem* psiResult; @@ -607,7 +614,7 @@ nfdresult_t NFD_PickFolderN_With_Impl(nfdversion_t version, } // Show the dialog to the user - const HRESULT result = fileOpenDialog->Show(nullptr); + const HRESULT result = fileOpenDialog->Show(GetNativeWindowHandle(args->parentWindow)); if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED)) { return NFD_CANCEL; } else if (!SUCCEEDED(result)) { @@ -673,7 +680,7 @@ nfdresult_t NFD_PickFolderMultipleN_With_Impl(nfdversion_t version, } // Show the dialog. - const HRESULT result = fileOpenDialog->Show(nullptr); + const HRESULT result = fileOpenDialog->Show(GetNativeWindowHandle(args->parentWindow)); if (SUCCEEDED(result)) { ::IShellItemArray* shellItems; if (!SUCCEEDED(fileOpenDialog->GetResults(&shellItems))) { @@ -933,7 +940,7 @@ nfdresult_t NFD_OpenDialogU8_With_Impl(nfdversion_t version, // call the native function nfdnchar_t* outPathN; const nfdopendialognargs_t argsN{ - filterItemsNGuard.data, args->filterCount, defaultPathNGuard.data}; + filterItemsNGuard.data, args->filterCount, defaultPathNGuard.data, args->parentWindow}; nfdresult_t res = NFD_OpenDialogN_With_Impl(NFD_INTERFACE_VERSION, &outPathN, &argsN); if (res != NFD_OKAY) { @@ -978,7 +985,7 @@ nfdresult_t NFD_OpenDialogMultipleU8_With_Impl(nfdversion_t version, // call the native function const nfdopendialognargs_t argsN{ - filterItemsNGuard.data, args->filterCount, defaultPathNGuard.data}; + filterItemsNGuard.data, args->filterCount, defaultPathNGuard.data, args->parentWindow}; return NFD_OpenDialogMultipleN_With_Impl(NFD_INTERFACE_VERSION, outPaths, &argsN); } @@ -1017,8 +1024,11 @@ nfdresult_t NFD_SaveDialogU8_With_Impl(nfdversion_t version, // call the native function nfdnchar_t* outPathN; - const nfdsavedialognargs_t argsN{ - filterItemsNGuard.data, args->filterCount, defaultPathNGuard.data, defaultNameNGuard.data}; + const nfdsavedialognargs_t argsN{filterItemsNGuard.data, + args->filterCount, + defaultPathNGuard.data, + defaultNameNGuard.data, + args->parentWindow}; nfdresult_t res = NFD_SaveDialogN_With_Impl(NFD_INTERFACE_VERSION, &outPathN, &argsN); if (res != NFD_OKAY) { @@ -1054,7 +1064,7 @@ nfdresult_t NFD_PickFolderU8_With_Impl(nfdversion_t version, // call the native function nfdnchar_t* outPathN; - const nfdpickfoldernargs_t argsN{defaultPathNGuard.data}; + const nfdpickfoldernargs_t argsN{defaultPathNGuard.data, args->parentWindow}; nfdresult_t res = NFD_PickFolderN_With_Impl(NFD_INTERFACE_VERSION, &outPathN, &argsN); if (res != NFD_OKAY) { @@ -1090,7 +1100,7 @@ nfdresult_t NFD_PickFolderMultipleU8_With_Impl(nfdversion_t version, NormalizePathSeparator(defaultPathNGuard.data); // call the native function - const nfdpickfoldernargs_t argsN{defaultPathNGuard.data}; + const nfdpickfoldernargs_t argsN{defaultPathNGuard.data, args->parentWindow}; return NFD_PickFolderMultipleN_With_Impl(NFD_INTERFACE_VERSION, outPaths, &argsN); }