From d914a439ce86d700090902f74f80820ea8bf8ccd Mon Sep 17 00:00:00 2001 From: Rye Mutt <rye@alchemyviewer.org> Date: Wed, 1 Feb 2023 21:18:22 -0500 Subject: [PATCH] Modernize windows directory picker --- indra/newview/lldirpicker.cpp | 52 ++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp index d3dd633a1f6..d9bff40da3a 100644 --- a/indra/newview/lldirpicker.cpp +++ b/indra/newview/lldirpicker.cpp @@ -92,6 +92,13 @@ LLDirPicker::~LLDirPicker() // nothing } +template <typename T> +struct Release_Guard { + T* data; + Release_Guard(T* releasable) noexcept : data(releasable) {} + ~Release_Guard() { data->Release(); } +}; + BOOL LLDirPicker::getDir(std::string* filename, bool blocking) { if( mLocked ) @@ -114,27 +121,46 @@ BOOL LLDirPicker::getDir(std::string* filename, bool blocking) send_agent_pause(); } - bi.hwndOwner = (HWND)gViewerWindow->getPlatformWindow(); + CoInitialize(0); - ::OleInitialize(NULL); - LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi); + ::IFileOpenDialog* fileOpenDialog; - if(pIDL != NULL) + // Create dialog + if (SUCCEEDED(::CoCreateInstance(::CLSID_FileOpenDialog, + nullptr, + CLSCTX_ALL, + ::IID_IFileOpenDialog, + reinterpret_cast<void**>(&fileOpenDialog)))) { - WCHAR buffer[_MAX_PATH] = {'\0'}; + Release_Guard<::IFileOpenDialog> fileOpenDialogGuard(fileOpenDialog); - if(::SHGetPathFromIDList(pIDL, buffer) != 0) + FILEOPENDIALOGOPTIONS existingOptions; + if (SUCCEEDED(fileOpenDialog->GetOptions(&existingOptions))) { - // Set the string value. - - mDir = ll_convert_wide_to_string(buffer); - success = TRUE; + if (SUCCEEDED(fileOpenDialog->SetOptions(existingOptions | (::FOS_FORCEFILESYSTEM | ::FOS_PICKFOLDERS)))) + { + // Show the dialog to the user + const HRESULT result = fileOpenDialog->Show(nullptr); + if (result != HRESULT_FROM_WIN32(ERROR_CANCELLED) && SUCCEEDED(result)) + { + // Get the shell item result + ::IShellItem* psiResult; + if (SUCCEEDED(fileOpenDialog->GetResult(&psiResult))) + { + Release_Guard<::IShellItem> psiResultGuard(psiResult); + wchar_t* filePath; + if (SUCCEEDED(psiResult->GetDisplayName(::SIGDN_FILESYSPATH, &filePath))) + { + mDir = ll_convert_wide_to_string(std::wstring(filePath)); + success = TRUE; + } + } + } + } } - // free the item id list - CoTaskMemFree(pIDL); } - ::OleUninitialize(); + CoUninitialize(); if (blocking) { -- GitLab