summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormaxim_productengine <mnikolenko@productengine.com>2018-06-18 17:49:49 +0300
committermaxim_productengine <mnikolenko@productengine.com>2018-06-18 17:49:49 +0300
commitbbc49ea0b6fba760954f0ed8cc89434ef83afcc5 (patch)
tree641c2461e00e021aed966293d41bd6eba5c65c04
parentdc580b3a0af5528329052f014a80365e3c34c353 (diff)
MAINT-8759 FIXED [Win] Choosing new cache location will cause disconnect if you do not choose desired path in File picker quickly
-rw-r--r--indra/newview/llappviewer.cpp5
-rw-r--r--indra/newview/lldirpicker.cpp153
-rw-r--r--indra/newview/lldirpicker.h42
-rw-r--r--indra/newview/llfloaterpreference.cpp39
-rw-r--r--indra/newview/llfloaterpreference.h2
5 files changed, 190 insertions, 51 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b9e2657351..acec68f393 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -42,6 +42,7 @@
#include "llagentlanguage.h"
#include "llagentui.h"
#include "llagentwearables.h"
+#include "lldirpicker.h"
#include "llfloaterimcontainer.h"
#include "llimprocessing.h"
#include "llwindow.h"
@@ -1985,6 +1986,7 @@ bool LLAppViewer::cleanup()
mAppCoreHttp.cleanup();
SUBSYSTEM_CLEANUP(LLFilePickerThread);
+ SUBSYSTEM_CLEANUP(LLDirPickerThread);
//MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl)
delete sTextureCache;
@@ -2155,6 +2157,7 @@ bool LLAppViewer::initThreads()
gMeshRepo.init();
LLFilePickerThread::initClass();
+ LLDirPickerThread::initClass();
// *FIX: no error handling here!
return true;
@@ -4589,7 +4592,7 @@ void LLAppViewer::idle()
LLSmoothInterpolation::updateInterpolants();
LLMortician::updateClass();
LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify()
-
+ LLDirPickerThread::clearDead();
F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
// Cap out-of-control frame times
diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp
index 5c4f0f4d5d..768b1c2021 100644
--- a/indra/newview/lldirpicker.cpp
+++ b/indra/newview/lldirpicker.cpp
@@ -77,6 +77,14 @@ LLDirPicker::LLDirPicker() :
mFileName(NULL),
mLocked(false)
{
+ bi.hwndOwner = NULL;
+ bi.pidlRoot = NULL;
+ bi.pszDisplayName = NULL;
+ bi.lpszTitle = NULL;
+ bi.ulFlags = BIF_USENEWUI;
+ bi.lpfn = NULL;
+ bi.lParam = NULL;
+ bi.iImage = 0;
}
LLDirPicker::~LLDirPicker()
@@ -84,7 +92,7 @@ LLDirPicker::~LLDirPicker()
// nothing
}
-BOOL LLDirPicker::getDir(std::string* filename)
+BOOL LLDirPicker::getDir(std::string filename, bool blocking)
{
if( mLocked )
{
@@ -99,39 +107,39 @@ BOOL LLDirPicker::getDir(std::string* filename)
BOOL success = FALSE;
- // Modal, so pause agent
- send_agent_pause();
-
- BROWSEINFO bi;
- memset(&bi, 0, sizeof(bi));
-
- bi.ulFlags = BIF_USENEWUI;
- bi.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
- bi.lpszTitle = NULL;
-
- ::OleInitialize(NULL);
+
+ if (blocking)
+ {
+ // Modal, so pause agent
+ send_agent_pause();
+ }
- LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);
+ bi.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
- if(pIDL != NULL)
- {
- WCHAR buffer[_MAX_PATH] = {'\0'};
+ ::OleInitialize(NULL);
+ LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);
- if(::SHGetPathFromIDList(pIDL, buffer) != 0)
- {
- // Set the string value.
+ if(pIDL != NULL)
+ {
+ WCHAR buffer[_MAX_PATH] = {'\0'};
- mDir = utf16str_to_utf8str(llutf16string(buffer));
- success = TRUE;
- }
+ if(::SHGetPathFromIDList(pIDL, buffer) != 0)
+ {
+ // Set the string value.
- // free the item id list
- CoTaskMemFree(pIDL);
- }
+ mDir = utf16str_to_utf8str(llutf16string(buffer));
+ success = TRUE;
+ }
+ // free the item id list
+ CoTaskMemFree(pIDL);
+ }
- ::OleUninitialize();
+ ::OleUninitialize();
- send_agent_resume();
+ if (blocking)
+ {
+ send_agent_resume();
+ }
// Account for the fact that the app has been stalled.
LLFrameTimer::updateFrameTime();
@@ -267,3 +275,94 @@ std::string LLDirPicker::getDirName()
}
#endif
+
+
+LLMutex* LLDirPickerThread::sMutex = NULL;
+std::queue<LLDirPickerThread*> LLDirPickerThread::sDeadQ;
+
+void LLDirPickerThread::getFile()
+{
+#if LL_WINDOWS
+ start();
+#else
+ run();
+#endif
+}
+
+//virtual
+void LLDirPickerThread::run()
+{
+#if LL_WINDOWS
+ bool blocking = false;
+#else
+ bool blocking = true; // modal
+#endif
+
+ LLDirPicker picker;
+
+ if (picker.getDir(mProposedName, blocking))
+ {
+ mResponses.push_back(picker.getDirName());
+ }
+
+ {
+ LLMutexLock lock(sMutex);
+ sDeadQ.push(this);
+ }
+
+}
+
+//static
+void LLDirPickerThread::initClass()
+{
+ sMutex = new LLMutex(NULL);
+}
+
+//static
+void LLDirPickerThread::cleanupClass()
+{
+ clearDead();
+
+ delete sMutex;
+ sMutex = NULL;
+}
+
+//static
+void LLDirPickerThread::clearDead()
+{
+ if (!sDeadQ.empty())
+ {
+ LLMutexLock lock(sMutex);
+ while (!sDeadQ.empty())
+ {
+ LLDirPickerThread* thread = sDeadQ.front();
+ thread->notify(thread->mResponses);
+ delete thread;
+ sDeadQ.pop();
+ }
+ }
+}
+
+LLDirPickerThread::LLDirPickerThread(const dir_picked_signal_t::slot_type& cb, const std::string &proposed_name)
+ : LLThread("dir picker"),
+ mFilePickedSignal(NULL)
+{
+ mFilePickedSignal = new dir_picked_signal_t();
+ mFilePickedSignal->connect(cb);
+}
+
+LLDirPickerThread::~LLDirPickerThread()
+{
+ delete mFilePickedSignal;
+}
+
+void LLDirPickerThread::notify(const std::vector<std::string>& filenames)
+{
+ if (!filenames.empty())
+ {
+ if (mFilePickedSignal)
+ {
+ (*mFilePickedSignal)(filenames, mProposedName);
+ }
+ }
+}
diff --git a/indra/newview/lldirpicker.h b/indra/newview/lldirpicker.h
index 8656b23afd..c1087c70ac 100644
--- a/indra/newview/lldirpicker.h
+++ b/indra/newview/lldirpicker.h
@@ -33,6 +33,13 @@
#include "stdtypes.h"
+#include "llthread.h"
+#include <queue>
+
+#if LL_WINDOWS
+#include <shlobj.h>
+#endif
+
#if LL_DARWIN
// AssertMacros.h does bad things.
@@ -53,7 +60,7 @@ public:
// calling this before main() is undefined
static LLDirPicker& instance( void ) { return sInstance; }
- BOOL getDir(std::string* filename);
+ BOOL getDir(std::string filename, bool blocking = true);
std::string getDirName();
// clear any lists of buffers or whatever, and make sure the dir
@@ -76,11 +83,15 @@ private:
LLFilePicker *mFilePicker;
#endif
+
std::string* mFileName;
std::string mDir;
bool mLocked;
static LLDirPicker sInstance;
+#if LL_WINDOWS
+ BROWSEINFO bi;
+#endif
public:
// don't call these directly please.
@@ -88,4 +99,33 @@ public:
~LLDirPicker();
};
+class LLDirPickerThread : public LLThread
+{
+public:
+
+ static std::queue<LLDirPickerThread*> sDeadQ;
+ static LLMutex* sMutex;
+
+ static void initClass();
+ static void cleanupClass();
+ static void clearDead();
+
+ std::vector<std::string> mResponses;
+ std::string mProposedName;
+
+ typedef boost::signals2::signal<void(const std::vector<std::string>& filenames, std::string proposed_name)> dir_picked_signal_t;
+
+ LLDirPickerThread(const dir_picked_signal_t::slot_type& cb, const std::string &proposed_name);
+ ~LLDirPickerThread();
+
+ void getFile();
+
+ virtual void run();
+
+ virtual void notify(const std::vector<std::string>& filenames);
+
+private:
+ dir_picked_signal_t* mFilePickedSignal;
+};
+
#endif
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 9d723bdd9d..4ce35643b1 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1096,16 +1096,15 @@ void LLFloaterPreference::onClickSetCache()
std::string proposed_name(cur_name);
- LLDirPicker& picker = LLDirPicker::instance();
- if (! picker.getDir(&proposed_name ) )
- {
- return; //Canceled!
- }
+ (new LLDirPickerThread(boost::bind(&LLFloaterPreference::changeCachePath, this, _1, _2), proposed_name))->getFile();
+}
- std::string dir_name = picker.getDirName();
- if (!dir_name.empty() && dir_name != cur_name)
+void LLFloaterPreference::changeCachePath(const std::vector<std::string>& filenames, std::string proposed_name)
+{
+ std::string dir_name = filenames[0];
+ if (!dir_name.empty() && dir_name != proposed_name)
{
- std::string new_top_folder(gDirUtilp->getBaseFileName(dir_name));
+ std::string new_top_folder(gDirUtilp->getBaseFileName(dir_name));
LLNotificationsUtil::add("CacheWillBeMoved");
gSavedSettings.setString("NewCacheLocation", dir_name);
gSavedSettings.setString("NewCacheLocationTopFolder", new_top_folder);
@@ -1744,25 +1743,21 @@ void LLFloaterPreference::onClickLogPath()
std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath"));
mPriorInstantMessageLogPath.clear();
- LLDirPicker& picker = LLDirPicker::instance();
- //Launches a directory picker and waits for feedback
- if (!picker.getDir(&proposed_name ) )
- {
- return; //Canceled!
- }
- //Gets the path from the directory picker
- std::string dir_name = picker.getDirName();
+ (new LLDirPickerThread(boost::bind(&LLFloaterPreference::changeLogPath, this, _1, _2), proposed_name))->getFile();
+}
+void LLFloaterPreference::changeLogPath(const std::vector<std::string>& filenames, std::string proposed_name)
+{
//Path changed
- if(proposed_name != dir_name)
+ if (proposed_name != filenames[0])
{
- gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name);
+ gSavedPerAccountSettings.setString("InstantMessageLogPath", filenames[0]);
mPriorInstantMessageLogPath = proposed_name;
-
- // enable/disable 'Delete transcripts button
- updateDeleteTranscriptsButton();
-}
+
+ // enable/disable 'Delete transcripts button
+ updateDeleteTranscriptsButton();
+ }
}
bool LLFloaterPreference::moveTranscriptsAndLog()
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 0cd7bac20f..8339a18296 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -133,6 +133,7 @@ public:
void setCacheLocation(const LLStringExplicit& location);
void onClickSetCache();
+ void changeCachePath(const std::vector<std::string>& filenames, std::string proposed_name);
void onClickResetCache();
void onClickSkin(LLUICtrl* ctrl,const LLSD& userdata);
void onSelectSkin();
@@ -145,6 +146,7 @@ public:
void resetAllIgnored();
void setAllIgnored();
void onClickLogPath();
+ void changeLogPath(const std::vector<std::string>& filenames, std::string proposed_name);
bool moveTranscriptsAndLog();
void enableHistory();
void setPersonalInfo(const std::string& visibility, bool im_via_email, bool is_verified_email);