From e2e1b763b294b5c5a84cc91a4c0014c70fa87344 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 12 Aug 2023 10:07:35 -0600 Subject: [PATCH] [wpigui] Fix PFD file dialogs not closing after window closing (#5530) Also applies samhocevar/portable-file-dialogs#91 to properly retrieve the HWND on Windows. --- .../main/native/cpp/portable-file-dialogs.cpp | 25 +++++++++++++------ .../native/include/portable-file-dialogs.h | 3 ++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/wpigui/src/main/native/cpp/portable-file-dialogs.cpp b/wpigui/src/main/native/cpp/portable-file-dialogs.cpp index 2e2ac7becf..c4afb0b00e 100644 --- a/wpigui/src/main/native/cpp/portable-file-dialogs.cpp +++ b/wpigui/src/main/native/cpp/portable-file-dialogs.cpp @@ -702,6 +702,12 @@ HANDLE internal::platform::new_style_context::create() // dialog implementation +internal::dialog::~dialog() { + if (m_async->m_running) { + kill(); + } +} + bool internal::dialog::ready(int timeout /* = default_wait_timeout */) const { return m_async->ready(timeout); @@ -804,7 +810,7 @@ class internal::file_dialog::Impl { #if _WIN32 static int CALLBACK bffcallback(HWND hwnd, UINT uMsg, LPARAM, LPARAM pData); #if PFD_HAS_IFILEDIALOG - std::string select_folder_vista(IFileDialog *ifd, bool force_path); + std::string select_folder_vista(IFileDialog *ifd, bool force_path, HWND active_window); #endif std::wstring m_wtitle; @@ -831,8 +837,9 @@ internal::file_dialog::file_dialog(type in_type, } filter_list += '\0'; + HWND active_window = GetActiveWindow(); m_async->start_func([this, in_type, title, default_path, filter_list, - options](int *exit_code) -> std::string + options, active_window](int *exit_code) -> std::string { (void)exit_code; m_impl->m_wtitle = internal::str2wstr(title); @@ -858,7 +865,7 @@ internal::file_dialog::file_dialog(type in_type, // In case CoCreateInstance fails (which it should not), try legacy approach if (SUCCEEDED(hr)) - return m_impl->select_folder_vista(ifd, options & opt::force_path); + return m_impl->select_folder_vista(ifd, options & opt::force_path, active_window); } #endif @@ -892,7 +899,7 @@ internal::file_dialog::file_dialog(type in_type, OPENFILENAMEW ofn; memset(&ofn, 0, sizeof(ofn)); ofn.lStructSize = sizeof(OPENFILENAMEW); - ofn.hwndOwner = GetActiveWindow(); + ofn.hwndOwner = active_window; ofn.lpstrFilter = wfilter_list.c_str(); @@ -1169,7 +1176,7 @@ int CALLBACK internal::file_dialog::Impl::bffcallback(HWND hwnd, UINT uMsg, } #if PFD_HAS_IFILEDIALOG -std::string internal::file_dialog::Impl::select_folder_vista(IFileDialog *ifd, bool force_path) +std::string internal::file_dialog::Impl::select_folder_vista(IFileDialog *ifd, bool force_path, HWND active_window) { std::string result; @@ -1206,7 +1213,7 @@ std::string internal::file_dialog::Impl::select_folder_vista(IFileDialog *ifd, b ifd->SetOptions(FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM); ifd->SetTitle(m_wtitle.c_str()); - hr = ifd->Show(GetActiveWindow()); + hr = ifd->Show(active_window); if (SUCCEEDED(hr)) { IShellItem* item; @@ -1393,13 +1400,15 @@ message::message(std::string const &title, m_mappings[IDRETRY] = button::retry; m_mappings[IDIGNORE] = button::ignore; - m_async->start_func([text, title, style](int* exit_code) -> std::string + HWND active_window = GetActiveWindow(); + + m_async->start_func([text, title, style, active_window](int* exit_code) -> std::string { auto wtext = internal::str2wstr(text); auto wtitle = internal::str2wstr(title); // Apply new visual style (required for all Windows versions) internal::platform::new_style_context ctx; - *exit_code = MessageBoxW(GetActiveWindow(), wtext.c_str(), wtitle.c_str(), style); + *exit_code = MessageBoxW(active_window, wtext.c_str(), wtitle.c_str(), style); return ""; }); diff --git a/wpigui/src/main/native/include/portable-file-dialogs.h b/wpigui/src/main/native/include/portable-file-dialogs.h index 95d5f430dc..e4a4f967eb 100644 --- a/wpigui/src/main/native/include/portable-file-dialogs.h +++ b/wpigui/src/main/native/include/portable-file-dialogs.h @@ -128,6 +128,7 @@ class executor; class dialog : protected settings { public: + virtual ~dialog(); bool ready(int timeout = default_wait_timeout) const; bool kill() const; @@ -146,7 +147,7 @@ protected: std::shared_ptr m_async; }; -class file_dialog : public dialog +class file_dialog : public internal::dialog { protected: enum type