From 360068075b3394e602a5debf88bdaed973463969 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 19 Jan 2014 18:44:41 -0800 Subject: [PATCH] windows: Show the open dialog on a separate thread. Allows the screen to continue rendering, which should prevent black screens, etc. while browsing. May help #2755. --- Windows/W32Util/ShellUtil.cpp | 43 ++++++++++++++++++- Windows/W32Util/ShellUtil.h | 36 ++++++++++++++++ Windows/WndMainWindow.cpp | 79 +++++++++++++++++++---------------- Windows/WndMainWindow.h | 1 + 4 files changed, 121 insertions(+), 38 deletions(-) diff --git a/Windows/W32Util/ShellUtil.cpp b/Windows/W32Util/ShellUtil.cpp index 030b449d4d..bde4d9c216 100644 --- a/Windows/W32Util/ShellUtil.cpp +++ b/Windows/W32Util/ShellUtil.cpp @@ -3,6 +3,8 @@ #include "stdafx.h" #include "shlobj.h" +#include "base/functional.h" +#include "thread/thread.h" #include "util/text/utf8.h" #include "ShellUtil.h" #include "CommDlg.h" @@ -15,11 +17,15 @@ namespace W32Util std::string BrowseForFolder(HWND parent, const char *title) { std::wstring titleString = ConvertUTF8ToWString(title); + return BrowseForFolder(parent, titleString.c_str()); + } + std::string BrowseForFolder(HWND parent, const wchar_t *title) + { BROWSEINFO info; memset(&info,0,sizeof(info)); info.hwndOwner = parent; - info.lpszTitle = titleString.c_str(); + info.lpszTitle = title; info.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS | BIF_USENEWUI; //info.pszDisplayName @@ -119,4 +125,39 @@ namespace W32Util else return std::vector(); // empty vector; } + + AsyncBrowseDialog::AsyncBrowseDialog(HWND parent, UINT completeMsg, std::wstring title) + : type_(DIR), parent_(parent), completeMsg_(completeMsg), title_(title), complete_(false) { + thread_ = new std::thread(std::bind(&AsyncBrowseDialog::Execute, this)); + thread_->detach(); + } + + AsyncBrowseDialog::AsyncBrowseDialog(Type type, HWND parent, UINT completeMsg, std::wstring title, std::wstring initialFolder, std::wstring filter, std::wstring extension) + : type_(type), parent_(parent), completeMsg_(completeMsg), title_(title), initialFolder_(initialFolder), filter_(filter), extension_(extension), complete_(false) { + thread_ = new std::thread(std::bind(&AsyncBrowseDialog::Execute, this)); + thread_->detach(); + } + + bool AsyncBrowseDialog::GetResult(std::string &filename) { + filename = filename_; + return result_; + } + + void AsyncBrowseDialog::Execute() { + switch (type_) { + case DIR: + filename_ = BrowseForFolder(parent_, title_.c_str()); + result_ = filename_ != ""; + complete_ = true; + break; + + case OPEN: + case SAVE: + result_ = BrowseForFileName(type_ == OPEN, parent_, title_.c_str(), initialFolder_.size() ? initialFolder_.c_str() : 0, filter_.c_str(), extension_.c_str(), filename_); + complete_ = true; + break; + } + + PostMessage(parent_, completeMsg_, 0, 0); + } } \ No newline at end of file diff --git a/Windows/W32Util/ShellUtil.h b/Windows/W32Util/ShellUtil.h index 09dd35ae4a..ba7899fc1e 100644 --- a/Windows/W32Util/ShellUtil.h +++ b/Windows/W32Util/ShellUtil.h @@ -2,14 +2,50 @@ #include #include +#include "thread/thread.h" namespace W32Util { std::string BrowseForFolder(HWND parent, const char *title); + std::string BrowseForFolder(HWND parent, const wchar_t *title); bool BrowseForFileName (bool _bLoad, HWND _hParent, const wchar_t*_pTitle, const wchar_t *_pInitialFolder,const wchar_t *_pFilter,const wchar_t*_pExtension, std::string& _strFileName); std::vector BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const wchar_t*_pTitle, const wchar_t*_pInitialFolder,const wchar_t*_pFilter,const wchar_t*_pExtension); + + struct AsyncBrowseDialog { + public: + enum Type { + OPEN, + SAVE, + DIR, + }; + + // For a directory. + AsyncBrowseDialog(HWND parent, UINT completeMsg, std::wstring title); + // For a file (OPEN or SAVE.) + AsyncBrowseDialog(Type type, HWND parent, UINT completeMsg, std::wstring title, std::wstring initialFolder, std::wstring filter, std::wstring extension); + + bool GetResult(std::string &filename); + Type GetType() { + return type_; + } + + private: + void Execute(); + + std::thread *thread_; + Type type_; + HWND parent_; + UINT completeMsg_; + std::wstring title_; + std::wstring initialFolder_; + std::wstring filter_; + std::wstring extension_; + bool complete_; + bool result_; + std::string filename_; + }; } \ No newline at end of file diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 94700f2326..1a3e186c5f 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -126,6 +126,8 @@ namespace MainWindow static std::map initialMenuKeys; static std::vector countryCodes; static std::vector availableShaders; + static W32Util::AsyncBrowseDialog *browseDialog; + static bool browsePauseAfter; #define MAX_LOADSTRING 100 const TCHAR *szTitle = TEXT("PPSSPP"); const TCHAR *szWindowClass = TEXT("PPSSPPWnd"); @@ -809,59 +811,58 @@ namespace MainWindow } void BrowseAndBoot(std::string defaultPath, bool browseDirectory) { - std::string fn; - std::string filter = "All supported file types (*.iso *.cso *.pbp *.elf *.prx *.zip)|*.pbp;*.elf;*.iso;*.cso;*.prx;*.zip|PSP ROMs (*.iso *.cso *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*||"; - - for (int i=0; i<(int)filter.length(); i++) { + static std::wstring filter = L"All supported file types (*.iso *.cso *.pbp *.elf *.prx *.zip)|*.pbp;*.elf;*.iso;*.cso;*.prx;*.zip|PSP ROMs (*.iso *.cso *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*||"; + for (int i = 0; i < (int)filter.length(); i++) { if (filter[i] == '|') filter[i] = '\0'; } - // Pause if a game is being played. - bool isPaused = false; + browsePauseAfter = false; if (globalUIState == UISTATE_INGAME) { - isPaused = Core_IsStepping(); - if (!isPaused) + browsePauseAfter = Core_IsStepping(); + if (!browsePauseAfter) Core_EnableStepping(true); } + W32Util::MakeTopMost(GetHWND(), false); if (browseDirectory) { - std::string dir = W32Util::BrowseForFolder(GetHWND(), "Choose directory"); - if (dir == "") { - if (!isPaused) - Core_EnableStepping(false); - } - else { - if (globalUIState == UISTATE_INGAME || globalUIState == UISTATE_PAUSEMENU) { - Core_EnableStepping(false); - } - - dir = ReplaceAll(dir, "\\", "/"); - NativeMessageReceived("boot", dir.c_str()); - } + browseDialog = new W32Util::AsyncBrowseDialog(GetHWND(), WM_USER_BROWSE_BOOT_DONE, L"Choose directory"); + } else { + browseDialog = new W32Util::AsyncBrowseDialog(W32Util::AsyncBrowseDialog::OPEN, GetHWND(), WM_USER_BROWSE_BOOT_DONE, L"LoadFile", ConvertUTF8ToWString(defaultPath), filter, L"*.pbp;*.elf;*.iso;*.cso;"); } - else if (W32Util::BrowseForFileName(true, GetHWND(), L"Load File", defaultPath.size() ? ConvertUTF8ToWString(defaultPath).c_str() : 0, ConvertUTF8ToWString(filter).c_str(), L"*.pbp;*.elf;*.iso;*.cso;",fn)) - { + } + + void BrowseAndBootDone() { + std::string filename; + if (!browseDialog->GetResult(filename)) { + if (!browsePauseAfter) { + Core_EnableStepping(false); + } + } else { if (globalUIState == UISTATE_INGAME || globalUIState == UISTATE_PAUSEMENU) { Core_EnableStepping(false); } - // Decode the filename with fullpath. - std::string fullpath = fn; - char drive[MAX_PATH]; - char dir[MAX_PATH]; - char fname[MAX_PATH]; - char ext[MAX_PATH]; - _splitpath(fullpath.c_str(), drive, dir, fname, ext); + // TODO: What is this for / what does it fix? + if (browseDialog->GetType() != W32Util::AsyncBrowseDialog::DIR) { + // Decode the filename with fullpath. + char drive[MAX_PATH]; + char dir[MAX_PATH]; + char fname[MAX_PATH]; + char ext[MAX_PATH]; + _splitpath(filename.c_str(), drive, dir, fname, ext); - std::string executable = std::string(drive) + std::string(dir) + std::string(fname) + std::string(ext); - executable = ReplaceAll(executable, "\\", "/"); - NativeMessageReceived("boot", executable.c_str()); - } - else { - if (!isPaused) - Core_EnableStepping(false); + filename = std::string(drive) + std::string(dir) + std::string(fname) + std::string(ext); + } + + filename = ReplaceAll(filename, "\\", "/"); + NativeMessageReceived("boot", filename.c_str()); } + + W32Util::MakeTopMost(GetHWND(), g_Config.bTopMost); + + delete browseDialog; + browseDialog = 0; } void UmdSwitchAction() { @@ -1574,6 +1575,10 @@ namespace MainWindow UpdateWindowTitle(); break; + case WM_USER_BROWSE_BOOT_DONE: + BrowseAndBootDone(); + break; + case WM_MENUSELECT: // Unfortunately, accelerate keys (hotkeys) shares the same enabled/disabled states // with corresponding menu items. diff --git a/Windows/WndMainWindow.h b/Windows/WndMainWindow.h index 06cdbb04bc..e11da181c5 100644 --- a/Windows/WndMainWindow.h +++ b/Windows/WndMainWindow.h @@ -12,6 +12,7 @@ namespace MainWindow WM_USER_UPDATE_UI = WM_USER + 101, WM_USER_UPDATE_SCREEN = WM_USER + 102, WM_USER_WINDOW_TITLE_CHANGED = WM_USER + 103, + WM_USER_BROWSE_BOOT_DONE = WM_USER + 104, }; enum {