From 71f6b139f8de3ea6bf2b925e095fc0f7864c0274 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 29 May 2020 20:10:04 +0300 Subject: SL-13348 Thread crashing singleton #1 --- indra/llcorehttp/_httpoprequest.cpp | 14 ++++-------- indra/llmessage/llproxy.cpp | 45 +++++++++++++++++++++++-------------- indra/llmessage/llproxy.h | 8 ++++++- indra/newview/llappviewer.cpp | 1 + 4 files changed, 40 insertions(+), 28 deletions(-) diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 0f76ff23ea..6909a650da 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -567,16 +567,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // Use the viewer-based thread-safe API which has a // fast/safe check for proxy enable. Would like to // encapsulate this someway... - if (LLProxy::instanceExists()) - { - // Make sure proxy won't be initialized from here, - // it might conflict with LLStartUp::startLLProxy() - LLProxy::getInstance()->applyProxySettings(mCurlHandle); - } - else - { - LL_WARNS() << "Proxy is not initialized!" << LL_ENDL; - } + // Make sure proxy won't be getInstance() from here, + // it is not thread safe + LLProxy::applyProxySettings(mCurlHandle); } else if (gpolicy.mHttpProxy.size()) @@ -817,6 +810,7 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void const size_t do_size((std::min)(req_size, body_size - op->mCurlBodyPos)); const size_t read_size(op->mReqBody->read(op->mCurlBodyPos, static_cast(data), do_size)); + // FIXME: singleton's instance() is Thread unsafe! Even if stats accumulators inside are. HTTPStats::instance().recordDataUp(read_size); op->mCurlBodyPos += read_size; return read_size; diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 950599217f..d11a1487ab 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -40,6 +40,7 @@ // incoming packet just to do a simple bool test. The getter for this // member is also static bool LLProxy::sUDPProxyEnabled = false; +LLProxy* LLProxy::sProxyInstance = NULL; // Some helpful TCP static functions. static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen); // Do a TCP data handshake @@ -60,11 +61,21 @@ LLProxy::LLProxy(): LLProxy::~LLProxy() { - if (ll_apr_is_initialized()) - { - stopSOCKSProxy(); - disableHTTPProxy(); - } + if (ll_apr_is_initialized()) + { + // locks mutex + stopSOCKSProxy(); + disableHTTPProxy(); + } + // The primary safety of sProxyInstance is the fact that by the + // point SUBSYSTEM_CLEANUP(LLProxy) gets called, nothing should + // be capable of using proxy + sProxyInstance = NULL; +} + +void LLProxy::initSingleton() +{ + sProxyInstance = this; } /** @@ -424,28 +435,28 @@ void LLProxy::cleanupClass() void LLProxy::applyProxySettings(CURL* handle) { // Do a faster unlocked check to see if we are supposed to proxy. - if (mHTTPProxyEnabled) + if (sProxyInstance && sProxyInstance->mHTTPProxyEnabled) { - // We think we should proxy, lock the proxy mutex. - LLMutexLock lock(&mProxyMutex); + // We think we should proxy, lock the proxy mutex. sProxyInstance is not protected by mutex + LLMutexLock lock(&sProxyInstance->mProxyMutex); // Now test again to verify that the proxy wasn't disabled between the first check and the lock. - if (mHTTPProxyEnabled) + if (sProxyInstance->mHTTPProxyEnabled) { - LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str()), CURLOPT_PROXY); - LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort()), CURLOPT_PROXYPORT); + LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, sProxyInstance->mHTTPProxy.getIPString().c_str()), CURLOPT_PROXY); + LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, sProxyInstance->mHTTPProxy.getPort()), CURLOPT_PROXYPORT); - if (mProxyType == LLPROXY_SOCKS) + if (sProxyInstance->mProxyType == LLPROXY_SOCKS) { - LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5), CURLOPT_PROXYTYPE); - if (mAuthMethodSelected == METHOD_PASSWORD) + LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5), CURLOPT_PROXYTYPE); + if (sProxyInstance->mAuthMethodSelected == METHOD_PASSWORD) { - std::string auth_string = mSocksUsername + ":" + mSocksPassword; - LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()), CURLOPT_PROXYUSERPWD); + std::string auth_string = sProxyInstance->mSocksUsername + ":" + sProxyInstance->mSocksPassword; + LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()), CURLOPT_PROXYUSERPWD); } } else { - LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP), CURLOPT_PROXYTYPE); + LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP), CURLOPT_PROXYTYPE); } } } diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h index 87891901ad..f2eefb26d0 100644 --- a/indra/llmessage/llproxy.h +++ b/indra/llmessage/llproxy.h @@ -225,6 +225,8 @@ class LLProxy: public LLSingleton LLSINGLETON(LLProxy); LOG_CLASS(LLProxy); + /*virtual*/ void initSingleton(); + public: // Static check for enabled status for UDP packets. Call from main thread only. static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; } @@ -250,7 +252,7 @@ public: // Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false. // Safe to call from any thread. - void applyProxySettings(CURL* handle); + static void applyProxySettings(CURL* handle); // Start a connection to the SOCKS 5 proxy. Call from main thread only. S32 startSOCKSProxy(LLHost host); @@ -343,6 +345,10 @@ private: /*########################################################################################### END OF SHARED MEMBERS ###########################################################################################*/ + + // A hack to get arround getInstance() and capture_dependency() which are unsafe to use inside threads + // set/reset on init/cleanup, strictly for use in applyProxySettings + static LLProxy* sProxyInstance; }; #endif diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ff921dcfdb..da1a58efd9 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2116,6 +2116,7 @@ bool LLAppViewer::cleanup() LLWeb::loadURLExternal( gLaunchFileOnQuit, false ); LL_INFOS() << "File launched." << LL_ENDL; } + // make sure nothing uses applyProxySettings by this point. LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL; SUBSYSTEM_CLEANUP(LLProxy); LLCore::LLHttp::cleanup(); -- cgit v1.2.3 From 372ed555ed3c895850700be463bd6775d66f6862 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 29 May 2020 20:13:23 +0300 Subject: SL-13348 Thread crashing singleton #2 Reverted LLImage to singleton conversion --- indra/llimage/llimage.cpp | 34 ++++++++++++++++++++++------------ indra/llimage/llimage.h | 32 +++++++++++++++----------------- indra/llimage/llimagej2c.cpp | 4 ++-- indra/llrender/llrender2dutils.h | 1 + indra/newview/llappviewer.cpp | 3 ++- 5 files changed, 42 insertions(+), 32 deletions(-) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 7a0c8cd8f5..aed8943439 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -583,29 +583,39 @@ static void bilinear_scale(const U8 *src, U32 srcW, U32 srcH, U32 srcCh, U32 src // LLImage //--------------------------------------------------------------------------- -LLImage::LLImage(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent) +//static +std::string LLImage::sLastErrorMessage; +LLMutex* LLImage::sMutex = NULL; +bool LLImage::sUseNewByteRange = false; +S32 LLImage::sMinimalReverseByteRangePercent = 75; + +//static +void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent) { - mMutex = new LLMutex(); - mUseNewByteRange = use_new_byte_range; - mMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent; + sUseNewByteRange = use_new_byte_range; + sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent; + sMutex = new LLMutex(); } -LLImage::~LLImage() +//static +void LLImage::cleanupClass() { - delete mMutex; - mMutex = NULL; + delete sMutex; + sMutex = NULL; } -const std::string& LLImage::getLastErrorMessage() +//static +const std::string& LLImage::getLastError() { static const std::string noerr("No Error"); - return mLastErrorMessage.empty() ? noerr : mLastErrorMessage; + return sLastErrorMessage.empty() ? noerr : sLastErrorMessage; } -void LLImage::setLastErrorMessage(const std::string& message) +//static +void LLImage::setLastError(const std::string& message) { - LLMutexLock m(mMutex); - mLastErrorMessage = message; + LLMutexLock m(sMutex); + sLastErrorMessage = message; } //--------------------------------------------------------------------------- diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 9f8d061293..f66b1666d7 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -30,7 +30,6 @@ #include "lluuid.h" #include "llstring.h" #include "llpointer.h" -#include "llsingleton.h" #include "lltrace.h" const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 @@ -88,26 +87,25 @@ typedef enum e_image_codec //============================================================================ // library initialization class +// LLImage is frequently used in threads so do not convert it to LLSingleton -class LLImage : public LLParamSingleton +class LLImage { - LLSINGLETON(LLImage, bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75); - ~LLImage(); public: + static void initClass(bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75); + static void cleanupClass(); - const std::string& getLastErrorMessage(); - static const std::string& getLastError() { return getInstance()->getLastErrorMessage(); }; - void setLastErrorMessage(const std::string& message); - static void setLastError(const std::string& message) { getInstance()->setLastErrorMessage(message); } - - bool useNewByteRange() { return mUseNewByteRange; } - S32 getReverseByteRangePercent() { return mMinimalReverseByteRangePercent; } - -private: - LLMutex* mMutex; - std::string mLastErrorMessage; - bool mUseNewByteRange; - S32 mMinimalReverseByteRangePercent; + static const std::string& getLastError(); + static void setLastError(const std::string& message); + + static bool useNewByteRange() { return sUseNewByteRange; } + static S32 getReverseByteRangePercent() { return sMinimalReverseByteRangePercent; } + +protected: + static LLMutex* sMutex; + static std::string sLastErrorMessage; + static bool sUseNewByteRange; + static S32 sMinimalReverseByteRangePercent; }; //============================================================================ diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 71cab0554d..4bff21610f 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -281,7 +281,7 @@ S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 r S32 bytes; S32 new_bytes = (S32) (sqrt((F32)(w*h))*(F32)(comp)*rate*1000.f/layer_factor); S32 old_bytes = (S32)((F32)(w*h*comp)*rate); - bytes = (LLImage::getInstance()->useNewByteRange() && (new_bytes < old_bytes) ? new_bytes : old_bytes); + bytes = (LLImage::useNewByteRange() && (new_bytes < old_bytes) ? new_bytes : old_bytes); bytes = llmax(bytes, calcHeaderSizeJ2C()); return bytes; } @@ -322,7 +322,7 @@ S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes) { S32 bytes_needed = calcDataSize(discard_level); // Use TextureReverseByteRange percent (see settings.xml) of the optimal size to qualify as correct rendering for the given discard level - if (bytes >= (bytes_needed*LLImage::getInstance()->getReverseByteRangePercent()/100)) + if (bytes >= (bytes_needed*LLImage::getReverseByteRangePercent()/100)) { break; } diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h index 70ab006fd6..8c01784071 100644 --- a/indra/llrender/llrender2dutils.h +++ b/indra/llrender/llrender2dutils.h @@ -32,6 +32,7 @@ #include "llpointer.h" // LLPointer<> #include "llrect.h" +#include "llsingleton.h" #include "llglslshader.h" class LLColor4; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index da1a58efd9..e067ab6778 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2073,6 +2073,7 @@ bool LLAppViewer::cleanup() LLUIImageList::getInstance()->cleanUp(); // This should eventually be done in LLAppViewer + SUBSYSTEM_CLEANUP(LLImage); SUBSYSTEM_CLEANUP(LLVFSThread); SUBSYSTEM_CLEANUP(LLLFSThread); @@ -2182,7 +2183,7 @@ bool LLAppViewer::initThreads() { static const bool enable_threads = true; - LLImage::initParamSingleton(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); + LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); LLVFSThread::initClass(enable_threads && false); LLLFSThread::initClass(enable_threads && false); -- cgit v1.2.3 From cf2f0eddeb066d862151154d0d35f7e9f716270b Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Mon, 1 Jun 2020 18:24:52 +0300 Subject: SL-13278 FIXED Creating default clothing not accessible through "Edit My Outfit" for any type that does not already exist --- indra/newview/llpaneloutfitedit.cpp | 1 + indra/newview/llwearableitemslist.cpp | 58 ++++++++++++++++++++-- indra/newview/llwearableitemslist.h | 7 +++ .../default/xui/en/menu_wearable_list_item.xml | 11 ++++ 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 1d87aa6f5d..dd1130aeba 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -1282,6 +1282,7 @@ void LLPanelOutfitEdit::showFilteredWearablesListView(LLWearableType::EType type //e_list_view_item_type implicitly contains LLWearableType::EType starting from LVIT_SHAPE applyListViewFilter(static_cast(LVIT_SHAPE + type)); + mWearableItemsList->setMenuWearableType(type); } static void update_status_widget_rect(LLView * widget, S32 right_border) diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index e7bbee5efd..3d1bc5249d 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -639,6 +639,7 @@ LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) : LLInventoryItemsList(p) { setSortOrder(E_SORT_BY_TYPE_LAYER, false); + mMenuWearableType = LLWearableType::WT_NONE; mIsStandalone = p.standalone; if (mIsStandalone) { @@ -730,10 +731,15 @@ void LLWearableItemsList::onRightClick(S32 x, S32 y) getSelectedUUIDs(selected_uuids); if (selected_uuids.empty()) { - return; + if ((mMenuWearableType != LLWearableType::WT_NONE) && (size() == 0)) + { + ContextMenu::instance().show(this, mMenuWearableType, x, y); + } + } + else + { + ContextMenu::instance().show(this, selected_uuids, x, y); } - - ContextMenu::instance().show(this, selected_uuids, x, y); } void LLWearableItemsList::setSortOrder(ESortOrder sort_order, bool sort_now) @@ -784,6 +790,46 @@ void LLWearableItemsList::ContextMenu::show(LLView* spawning_view, const uuid_ve mParent = NULL; // to avoid dereferencing an invalid pointer } +void LLWearableItemsList::ContextMenu::show(LLView* spawning_view, LLWearableType::EType w_type, S32 x, S32 y) +{ + mParent = dynamic_cast(spawning_view); + LLContextMenu* menup = mMenuHandle.get(); + if (menup) + { + //preventing parent (menu holder) from deleting already "dead" context menus on exit + LLView* parent = menup->getParent(); + if (parent) + { + parent->removeChild(menup); + } + delete menup; + mUUIDs.clear(); + } + + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("Wearable.CreateNew", boost::bind(createNewWearableByType, w_type)); + menup = createFromFile("menu_wearable_list_item.xml"); + if (!menup) + { + LL_WARNS() << "Context menu creation failed" << LL_ENDL; + return; + } + setMenuItemVisible(menup, "create_new", true); + setMenuItemEnabled(menup, "create_new", true); + setMenuItemVisible(menup, "wearable_attach_to", false); + setMenuItemVisible(menup, "wearable_attach_to_hud", false); + + std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getTypeName(w_type)); + LLMenuItemGL* menu_item = menup->getChild("create_new"); + menu_item->setLabel(new_label); + + mMenuHandle = menup->getHandle(); + menup->show(x, y); + LLMenuGL::showPopup(spawning_view, menup, x, y); + + mParent = NULL; // to avoid dereferencing an invalid pointer +} + // virtual LLContextMenu* LLWearableItemsList::ContextMenu::createMenu() { @@ -1004,4 +1050,10 @@ void LLWearableItemsList::ContextMenu::createNewWearable(const LLUUID& item_id) LLAgentWearables::createWearable(item->getWearableType(), true); } +// static +void LLWearableItemsList::ContextMenu::createNewWearableByType(LLWearableType::EType type) +{ + LLAgentWearables::createWearable(type, true); +} + // EOF diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index f3182ed163..ba8488b237 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -415,6 +415,8 @@ public: public: /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); + void show(LLView* spawning_view, LLWearableType::EType w_type, S32 x, S32 y); + protected: enum { MASK_CLOTHING = 0x01, @@ -431,6 +433,7 @@ public: static void setMenuItemEnabled(LLContextMenu* menu, const std::string& name, bool val); static void updateMask(U32& mask, LLAssetType::EType at); static void createNewWearable(const LLUUID& item_id); + static void createNewWearableByType(LLWearableType::EType type); LLWearableItemsList* mParent; }; @@ -469,6 +472,8 @@ public: void setSortOrder(ESortOrder sort_order, bool sort_now = true); + void setMenuWearableType(LLWearableType::EType type) { mMenuWearableType = type; } + protected: friend class LLUICtrlFactory; LLWearableItemsList(const LLWearableItemsList::Params& p); @@ -479,6 +484,8 @@ protected: bool mWornIndicationEnabled; ESortOrder mSortOrder; + + LLWearableType::EType mMenuWearableType; }; #endif //LL_LLWEARABLEITEMSLIST_H diff --git a/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml index aa56b4ba63..7370dace7f 100644 --- a/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml +++ b/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml @@ -4,6 +4,7 @@ @@ -11,6 +12,7 @@ @@ -18,6 +20,7 @@ @@ -25,6 +28,7 @@ @@ -32,6 +36,7 @@ @@ -47,6 +52,7 @@ @@ -54,6 +60,7 @@ @@ -61,6 +68,7 @@ @@ -68,6 +76,7 @@ @@ -75,6 +84,7 @@ -- cgit v1.2.3 From c471392ef1c0633423ea66158c21ba4d81f2473b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 1 Jun 2020 21:34:12 +0300 Subject: SL-13346 Hi-Res snapshots save a zoomed portion on 4K+ resolutions --- indra/newview/llviewermenufile.cpp | 7 +++++-- indra/newview/llviewerwindow.h | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index d1d3a7fc12..7603a6b18c 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -683,7 +683,8 @@ class LLFileTakeSnapshotToDisk : public view_listener_t S32 width = gViewerWindow->getWindowWidthRaw(); S32 height = gViewerWindow->getWindowHeightRaw(); - if (gSavedSettings.getBOOL("HighResSnapshot")) + BOOL high_res = gSavedSettings.getBOOL("HighResSnapshot"); + if (high_res) { width *= 2; height *= 2; @@ -695,7 +696,9 @@ class LLFileTakeSnapshotToDisk : public view_listener_t TRUE, FALSE, gSavedSettings.getBOOL("RenderUIInSnapshot"), - FALSE)) + FALSE, + LLSnapshotModel::SNAPSHOT_TYPE_COLOR, + high_res ? S32_MAX : MAX_SNAPSHOT_IMAGE_SIZE)) //per side { LLPointer formatted; LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 385bbd57e5..601140d9d2 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -137,7 +137,7 @@ private: }; -static const U32 MAX_SNAPSHOT_IMAGE_SIZE = 6 * 1024; // max snapshot image size 6144 * 6144 +static const U32 MAX_SNAPSHOT_IMAGE_SIZE = 7680; // max snapshot image size 7680 * 7680 UHDTV2 class LLViewerWindow : public LLWindowCallbacks { -- cgit v1.2.3 From 47e474244f42f0e28c8a041d5d34d6656c27db85 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Tue, 2 Jun 2020 18:45:03 +0300 Subject: SL-13362 The worn wearables shouldn't be shareable --- indra/newview/llgiveinventory.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/indra/newview/llgiveinventory.cpp b/indra/newview/llgiveinventory.cpp index 3ab8fed2c6..127055459d 100644 --- a/indra/newview/llgiveinventory.cpp +++ b/indra/newview/llgiveinventory.cpp @@ -129,23 +129,14 @@ bool LLGiveInventory::isInventoryGiveAcceptable(const LLInventoryItem* item) switch(item->getType()) { case LLAssetType::AT_OBJECT: - if (get_is_item_worn(item->getUUID())) - { - acceptable = false; - } - break; case LLAssetType::AT_BODYPART: case LLAssetType::AT_CLOTHING: { - BOOL copyable = false; - if (item->getPermissions().allowCopyBy(gAgentID)) copyable = true; - - if (!copyable && get_is_item_worn(item->getUUID())) + if (get_is_item_worn(item->getUUID())) { - // worn no-copy items can't be transfered, - // but it is valid to transfer a copy of a worn item acceptable = false; } + break; } break; default: -- cgit v1.2.3 From 13b78a0c5a788c617866e3530c65dae616e6520f Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 2 Jun 2020 10:29:15 -0400 Subject: SL-13361: Distill redundant create_console() code to set_stream(). There are separate stanzas in llappviewerwin32.cpp's create_console() function for each of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and STD_ERROR_HANDLE. SL-13361 wants to add more code to each. Factor out new local set_stream() function and make create_console() call it three times. --- indra/newview/llappviewerwin32.cpp | 59 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index d208e135bb..1f66177c37 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -501,11 +501,12 @@ void LLAppViewerWin32::disableWinErrorReporting() const S32 MAX_CONSOLE_LINES = 500; -static bool create_console() -{ - int h_con_handle; - long l_std_handle; +namespace { + +FILE* set_stream(const char* which, DWORD handle_id, const char* mode); +bool create_console() +{ CONSOLE_SCREEN_BUFFER_INFO coninfo; FILE *fp; @@ -518,50 +519,48 @@ static bool create_console() SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); // redirect unbuffered STDOUT to the console - l_std_handle = (long)GetStdHandle(STD_OUTPUT_HANDLE); - h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT); - if (h_con_handle == -1) + FILE* fp = set_stream("stdout", STD_OUTPUT_HANDLE, "w"); + if (fp) { - LL_WARNS() << "create_console() failed to open stdout handle" << LL_ENDL; - } - else - { - fp = _fdopen( h_con_handle, "w" ); *stdout = *fp; - setvbuf( stdout, NULL, _IONBF, 0 ); } // redirect unbuffered STDIN to the console - l_std_handle = (long)GetStdHandle(STD_INPUT_HANDLE); - h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT); - if (h_con_handle == -1) - { - LL_WARNS() << "create_console() failed to open stdin handle" << LL_ENDL; - } - else + fp = set_stream("stdin", STD_INPUT_HANDLE, "r"); + if (fp) { - fp = _fdopen( h_con_handle, "r" ); *stdin = *fp; - setvbuf( stdin, NULL, _IONBF, 0 ); } // redirect unbuffered STDERR to the console - l_std_handle = (long)GetStdHandle(STD_ERROR_HANDLE); - h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT); + fp = set_stream("stderr", STD_ERROR_HANDLE, "w"); + if (fp) + { + *stderr = *fp; + } + + return isConsoleAllocated; +} + +FILE* set_stream(const char* which, DWORD handle_id, const char* mode) +{ + long l_std_handle = (long)GetStdHandle(handle_id); + int h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT); if (h_con_handle == -1) { - LL_WARNS() << "create_console() failed to open stderr handle" << LL_ENDL; + LL_WARNS() << "create_console() failed to open " << which << " handle" << LL_ENDL; + return nullptr; } else { - fp = _fdopen( h_con_handle, "w" ); - *stderr = *fp; - setvbuf( stderr, NULL, _IONBF, 0 ); + FILE* fp = _fdopen( h_con_handle, mode ); + setvbuf( fp, NULL, _IONBF, 0 ); + return fp; } - - return isConsoleAllocated; } +} // anonymous namespace + LLAppViewerWin32::LLAppViewerWin32(const char* cmd_line) : mCmdLine(cmd_line), mIsConsoleAllocated(false) -- cgit v1.2.3 From 0b61150e698537a7e42a4cdae02496da500399d9 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 2 Jun 2020 16:44:22 -0400 Subject: SL-13361: Enable color processing on Windows 10 debug console. --- indra/llcommon/llerror.cpp | 5 ++--- indra/newview/llappviewerwin32.cpp | 21 ++++++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index b46f49ba34..0a83c4a3d7 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -39,6 +39,8 @@ #if !LL_WINDOWS # include # include +#else +# include #endif // !LL_WINDOWS #include #include "string.h" @@ -231,14 +233,11 @@ namespace { bool checkANSI(void) { -#if LL_LINUX || LL_DARWIN // Check whether it's okay to use ANSI; if stderr is // a tty then we assume yes. Can be turned off with // the LL_NO_ANSI_COLOR env var. return (0 != isatty(2)) && (NULL == getenv("LL_NO_ANSI_COLOR")); -#endif // LL_LINUX - return FALSE; // works in a cygwin shell... ;) } }; diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 1f66177c37..f0aa355342 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -500,6 +500,10 @@ void LLAppViewerWin32::disableWinErrorReporting() } const S32 MAX_CONSOLE_LINES = 500; +// Only defined in newer SDKs than we currently use +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 4 +#endif namespace { @@ -507,13 +511,11 @@ FILE* set_stream(const char* which, DWORD handle_id, const char* mode); bool create_console() { - CONSOLE_SCREEN_BUFFER_INFO coninfo; - FILE *fp; - // allocate a console for this app const bool isConsoleAllocated = AllocConsole(); // set the screen buffer to be big enough to let us scroll text + CONSOLE_SCREEN_BUFFER_INFO coninfo; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); coninfo.dwSize.Y = MAX_CONSOLE_LINES; SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); @@ -542,19 +544,24 @@ bool create_console() return isConsoleAllocated; } -FILE* set_stream(const char* which, DWORD handle_id, const char* mode) +FILE* set_stream(const char* desc, DWORD handle_id, const char* mode) { - long l_std_handle = (long)GetStdHandle(handle_id); - int h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT); + auto l_std_handle = GetStdHandle(handle_id); + int h_con_handle = _open_osfhandle(reinterpret_cast(l_std_handle), _O_TEXT); if (h_con_handle == -1) { - LL_WARNS() << "create_console() failed to open " << which << " handle" << LL_ENDL; + LL_WARNS() << "create_console() failed to open " << desc << " handle" << LL_ENDL; return nullptr; } else { FILE* fp = _fdopen( h_con_handle, mode ); setvbuf( fp, NULL, _IONBF, 0 ); + // Enable color processing on Windows 10 console windows. + DWORD dwMode = 0; + GetConsoleMode(l_std_handle, &dwMode); + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + SetConsoleMode(l_std_handle, dwMode); return fp; } } -- cgit v1.2.3 From 6fddbeb3973c3cd2135ba101afc13329a8c9fe49 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 4 Jun 2020 22:43:55 +0300 Subject: SL-12748 Blocked username displays old name after name change --- indra/llmessage/llavatarnamecache.cpp | 17 ++++++++ indra/llmessage/llavatarnamecache.h | 4 ++ indra/newview/llmutelist.cpp | 78 +++++++++++++++++++++++++++++++++-- indra/newview/llmutelist.h | 6 ++- 4 files changed, 100 insertions(+), 5 deletions(-) diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 6a287f0cc5..6ada12962c 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -285,12 +285,27 @@ void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName& return; } + bool updated_account = true; // assume obsolete value for new arrivals by default + + std::map::iterator it = mCache.find(agent_id); + if (it != mCache.end() + && (*it).second.getAccountName() == av_name.getAccountName()) + { + updated_account = false; + } + // Add to the cache mCache[agent_id] = av_name; // Suppress request from the queue mPendingQueue.erase(agent_id); + // notify mute list about changes + if (updated_account && mAccountNameChangedCallback) + { + mAccountNameChangedCallback(agent_id, av_name); + } + // Signal everyone waiting on this name signal_map_t::iterator sig_it = mSignalMap.find(agent_id); if (sig_it != mSignalMap.end()) @@ -303,6 +318,8 @@ void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName& delete signal; signal = NULL; } + + } void LLAvatarNameCache::requestNamesViaCapability() diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index ba89d569f3..549d1703fa 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -42,6 +42,7 @@ class LLAvatarNameCache : public LLSingleton ~LLAvatarNameCache(); public: typedef boost::signals2::signal use_display_name_signal_t; + typedef boost::function account_name_changed_callback_t; // Import/export the name cache to file. bool importFile(std::istream& istr); @@ -103,6 +104,8 @@ public: void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb); + void setAccountNameChangedCallback(const account_name_changed_callback_t& cb) { mAccountNameChangedCallback = cb; } + private: // Handle name response off network. void processName(const LLUUID& agent_id, @@ -141,6 +144,7 @@ private: private: use_display_name_signal_t mUseDisplayNamesSignal; + account_name_changed_callback_t mAccountNameChangedCallback; // Cache starts in a paused state until we can determine if the // current region supports display names. diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 64df449c26..8a10a38b37 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -169,6 +169,14 @@ LLMuteList::LLMuteList() : gMessageSystem.callWhenReady(boost::bind(&LLMessageSystem::setHandlerFuncFast, _1, _PREHASH_UseCachedMuteList, processUseCachedMuteList, static_cast(NULL))); + + // make sure mute list's instance gets initialized before we start any name requests + LLAvatarNameCache::getInstance()->setAccountNameChangedCallback([this](const LLUUID& id, const LLAvatarName& av_name) + { + // it would be better to just pass LLAvatarName instead of doing unnesssesary copies + // but this way is just more convinient + onAccountNameChanged(id, av_name.getUserName()); + }); } //----------------------------------------------------------------------------- @@ -179,6 +187,11 @@ LLMuteList::~LLMuteList() } +void LLMuteList::cleanupSingleton() +{ + LLAvatarNameCache::getInstance()->setAccountNameChangedCallback(NULL); +} + BOOL LLMuteList::isLinden(const std::string& name) const { std::string username = boost::replace_all_copy(name, ".", " "); @@ -232,8 +245,8 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags) LL_WARNS() << "Trying to self; ignored" << LL_ENDL; return FALSE; } - - S32 mute_list_limit = gSavedSettings.getS32("MuteListLimit"); + + static LLCachedControl mute_list_limit(gSavedSettings, "MuteListLimit", 1000); if (getMutes().size() >= mute_list_limit) { LL_WARNS() << "Mute limit is reached; ignored" << LL_ENDL; @@ -358,6 +371,10 @@ void LLMuteList::updateAdd(const LLMute& mute) msg->addU32("MuteFlags", mute.mFlags); gAgent.sendReliableMessage(); + if (!mIsLoaded) + { + LL_WARNS() << "Added elements to non-initialized block list" << LL_ENDL; + } mIsLoaded = TRUE; // why is this here? -MG } @@ -412,7 +429,6 @@ BOOL LLMuteList::remove(const LLMute& mute, U32 flags) // Must be after erase. notifyObserversDetailed(localmute); - setLoaded(); // why is this here? -MG } else { @@ -426,7 +442,6 @@ BOOL LLMuteList::remove(const LLMute& mute, U32 flags) mLegacyMutes.erase(legacy_it); // Must be after erase. notifyObserversDetailed(mute); - setLoaded(); // why is this here? -MG } } @@ -584,6 +599,19 @@ BOOL LLMuteList::loadFromFile(const std::string& filename) } fclose(fp); setLoaded(); + + // server does not maintain up-to date account names (not display names!) + // in this list, so it falls to viewer. + pending_names_t::iterator iter = mPendingAgentNameUpdates.begin(); + pending_names_t::iterator end = mPendingAgentNameUpdates.end(); + while (iter != end) + { + // this will send updates to server, make sure mIsLoaded is set + onAccountNameChanged(iter->first, iter->second); + iter++; + } + mPendingAgentNameUpdates.clear(); + return TRUE; } @@ -767,6 +795,48 @@ void LLMuteList::onFileMuteList(void** user_data, S32 error_code, LLExtStat ext_ delete local_filename_and_path; } +void LLMuteList::onAccountNameChanged(const LLUUID& id, const std::string& username) +{ + if (mIsLoaded) + { + LLMute mute(id, username, LLMute::AGENT); + mute_set_t::iterator mute_it = mMutes.find(mute); + if (mute_it != mMutes.end() + && mute_it->mName != mute.mName + && mute_it->mType == LLMute::AGENT) // just in case, it is std::set, not map + { + // existing mute, but name changed, copy data + mute.mFlags = mute_it->mFlags; + + // erase old variant + mMutes.erase(mute_it); + + // (re)add the mute entry. + { + std::pair result = mMutes.insert(mute); + if (result.second) + { + LL_INFOS() << "Muting " << mute.mName << " id " << mute.mID << " flags " << mute.mFlags << LL_ENDL; + updateAdd(mute); + // Do not notify observers here, observers do not know or need to handle name changes + // Example: block list considers notifyObserversDetailed as a selection update; + // Various chat/voice statuses care only about id and flags + // Since apropriate update time for account names is considered to be in 'hours' it is + // fine not to update UI (will be fine after restart or couple other changes) + + } + } + } + } + else + { + // Delay update until we load file + // Ex: Buddies list can arrive too early since we prerequest + // names from Buddies list before we load blocklist + mPendingAgentNameUpdates[id] = username; + } +} + void LLMuteList::addObserver(LLMuteListObserver* observer) { mObservers.insert(observer); diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index f2fcf3dbb3..0d426fbd48 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -73,6 +73,7 @@ class LLMuteList : public LLSingleton { LLSINGLETON(LLMuteList); ~LLMuteList(); + /*virtual*/ void cleanupSingleton(); public: // reasons for auto-unmuting a resident enum EAutoReason @@ -131,6 +132,7 @@ private: static void processUseCachedMuteList(LLMessageSystem* msg, void**); static void onFileMuteList(void** user_data, S32 code, LLExtStat ext_status); + void onAccountNameChanged(const LLUUID& id, const std::string& username); private: struct compare_by_name @@ -155,7 +157,9 @@ private: }; typedef std::set mute_set_t; mute_set_t mMutes; - + typedef std::map pending_names_t; + pending_names_t mPendingAgentNameUpdates; + typedef std::set string_set_t; string_set_t mLegacyMutes; -- cgit v1.2.3 From 39cf42e6eb0460e6b752a90e4920d8869d83ed51 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Tue, 9 Jun 2020 15:24:03 +0300 Subject: SL-13405 FIXED Preview Asset Types of Content tab in one window no longer works --- indra/newview/llinventoryfunctions.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 646d92b9e1..0083ab0397 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2397,16 +2397,19 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root { bool open_multi_preview = true; - for (std::set::iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) + if ("open" == action) { - LLFolderViewItem* folder_item = *set_iter; - if (folder_item) + for (std::set::iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) { - LLInvFVBridge* bridge = dynamic_cast(folder_item->getViewModelItem()); - if (!bridge || !bridge->isMultiPreviewAllowed()) + LLFolderViewItem* folder_item = *set_iter; + if (folder_item) { - open_multi_preview = false; - break; + LLInvFVBridge* bridge = dynamic_cast(folder_item->getViewModelItem()); + if (!bridge || !bridge->isMultiPreviewAllowed()) + { + open_multi_preview = false; + break; + } } } } -- cgit v1.2.3 From 5afedc9177893daa4c60ee2c20471241b4b38dc8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 9 Jun 2020 18:29:46 +0300 Subject: SL-3584 Alpha masked textures occasionally changing to alpha mode none --- indra/newview/llvovolume.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 2ffd462ac3..34b801a097 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -2319,7 +2319,8 @@ bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture) //setup new materials for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) { - LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); + // These are placeholder materials, they shouldn't be sent to server + LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), it->second); LLViewerObject::setTEMaterialParams(it->first, it->second); } -- cgit v1.2.3 From 161ea5b13579cb21c07cbd04062a44d09064517e Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Wed, 10 Jun 2020 14:14:38 +0300 Subject: SL-13413 FIXED Camera behaviour changed on ESC in Camera Presets viewer --- indra/newview/llviewermenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index b6c7be2ed3..f5f8b87ed5 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -4104,7 +4104,7 @@ void handle_reset_view() // switching to outfit selector should automagically save any currently edited wearable LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits")); } - + gAgentCamera.setFocusOnAvatar(TRUE, FALSE, FALSE); reset_view_final( TRUE ); LLFloaterCamera::resetCameraMode(); } -- cgit v1.2.3 From 9608b6dcac894c5251d9419c66943d6473fa5d41 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 11 Jun 2020 17:41:59 +0300 Subject: SL-13433 Viewer should recognizes ipv6 links --- indra/llui/llurlentry.cpp | 39 +++++++++++++++++++++++++++++++++++++++ indra/llui/llurlentry.h | 13 +++++++++++++ indra/llui/llurlregistry.cpp | 1 + 3 files changed, 53 insertions(+) diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 333d03f208..ac86101f69 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -1475,4 +1475,43 @@ void LLUrlEntryExperienceProfile::onExperienceDetails( const LLSD& experience_de callObservers(experience_details[LLExperienceCache::EXPERIENCE_ID].asString(), name, LLStringUtil::null); } +// +// LLUrlEntryEmail Describes an IPv6 address +// +LLUrlEntryIPv6::LLUrlEntryIPv6() + : LLUrlEntryBase() +{ + mHostPath = "https?://\\[([a-f0-9:]+:+)+[a-f0-9]+]"; + mPattern = boost::regex(mHostPath + "(:\\d{1,5})?(/\\S*)?", + boost::regex::perl | boost::regex::icase); + mMenuName = "menu_url_http.xml"; + mTooltip = LLTrans::getString("TooltipHttpUrl"); +} +std::string LLUrlEntryIPv6::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ + boost::regex regex = boost::regex(mHostPath, boost::regex::perl | boost::regex::icase); + boost::match_results matches; + + if (boost::regex_search(url, matches, regex)) + { + return url.substr(0, matches[0].length()); + } + else + { + return url; + } +} + +std::string LLUrlEntryIPv6::getQuery(const std::string &url) const +{ + boost::regex regex = boost::regex(mHostPath, boost::regex::perl | boost::regex::icase); + boost::match_results matches; + + return boost::regex_replace(url, regex, ""); +} + +std::string LLUrlEntryIPv6::getUrl(const std::string &string) const +{ + return string; +} diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 78c149d9fd..0a0c247a6a 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -513,5 +513,18 @@ public: /*virtual*/ std::string getUrl(const std::string &string) const; }; +/// +/// LLUrlEntryEmail Describes an IPv6 address +/// +class LLUrlEntryIPv6 : public LLUrlEntryBase +{ +public: + LLUrlEntryIPv6(); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + /*virtual*/ std::string getUrl(const std::string &string) const; + /*virtual*/ std::string getQuery(const std::string &url) const; + + std::string mHostPath; +}; #endif diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index ba6fa1e2e9..321a0ec5b9 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -79,6 +79,7 @@ LLUrlRegistry::LLUrlRegistry() mUrlEntrySLLabel = new LLUrlEntrySLLabel(); registerUrl(mUrlEntrySLLabel); registerUrl(new LLUrlEntryEmail()); + registerUrl(new LLUrlEntryIPv6()); } LLUrlRegistry::~LLUrlRegistry() -- cgit v1.2.3 From 905005be3c7e15429d8380c99d7590e677482286 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 11 Jun 2020 20:54:09 +0300 Subject: SL-13433 Add tests for new url entry --- indra/llui/tests/llurlentry_test.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 3c34fd269e..4a4fdb72e3 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -903,4 +903,38 @@ namespace tut "and even no www something lindenlab.com", ""); } + + template<> template<> + void object::test<16>() + { + // + // test LLUrlEntryIPv6 + // + LLUrlEntryIPv6 url; + + // Regex tests. + testRegex("match urls with a protocol", url, + "this url should match http://[::1]", + "http://[::1]"); + + testRegex("match urls with a protocol and query", url, + "this url should match http://[::1]/file.mp3", + "http://[::1]/file.mp3"); + + testRegex("match urls with a protocol", url, + "this url should match http://[2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d]", + "http://[2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d]"); + + testRegex("match urls with port", url, + "let's specify some port http://[2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d]:8080", + "http://[2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d]:8080"); + + testRegex("don't match urls w/o protocol", url, + "looks like an url something [2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d] but no https prefix", + ""); + + testRegex("don't match incorrect urls", url, + "http://[ 2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d ]", + ""); + } } -- cgit v1.2.3 From b95d780b2ec38078100a96ed3b5760c29598a0db Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Mon, 15 Jun 2020 16:07:05 +0300 Subject: SL-13457 FIXED Crash in LLFolderViewGroupedItemBridge::canWearSelected --- indra/newview/llinventorybridge.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 657c65c68d..b1de884f06 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -7655,8 +7655,7 @@ bool LLFolderViewGroupedItemBridge::canWearSelected(uuid_vec_t item_ids) for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it) { LLViewerInventoryItem* item = gInventory.getItem(*it); - LLAssetType::EType asset_type = item->getType(); - if (!item || (asset_type >= LLAssetType::AT_COUNT) || (asset_type <= LLAssetType::AT_NONE)) + if (!item || (item->getType() >= LLAssetType::AT_COUNT) || (item->getType() <= LLAssetType::AT_NONE)) { return false; } -- cgit v1.2.3 From 307534c9781b312608ccce6a9b4e12499a66170a Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Tue, 16 Jun 2020 17:26:39 +0300 Subject: SL-13463 Add 'Reset scripts' button to Content tab of Build floater --- indra/newview/llpanelcontents.cpp | 11 +++ indra/newview/llpanelcontents.h | 1 + indra/newview/llviewermenu.cpp | 100 +++++++++++---------- indra/newview/llviewermenu.h | 2 + .../newview/skins/default/xui/en/floater_tools.xml | 13 ++- 5 files changed, 77 insertions(+), 50 deletions(-) diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index 3bae0cebfb..116b23e595 100644 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -54,6 +54,7 @@ #include "lltrans.h" #include "llviewerassettype.h" #include "llviewerinventory.h" +#include "llviewermenu.h" #include "llviewerobject.h" #include "llviewerregion.h" #include "llviewerwindow.h" @@ -82,6 +83,7 @@ BOOL LLPanelContents::postBuild() childSetAction("button new script",&LLPanelContents::onClickNewScript, this); childSetAction("button permissions",&LLPanelContents::onClickPermissions, this); + childSetAction("btn_reset_scripts", &LLPanelContents::onClickResetScripts, this); mPanelInventoryObject = getChild("contents_inventory"); @@ -106,6 +108,7 @@ void LLPanelContents::getState(LLViewerObject *objectp ) if( !objectp ) { getChildView("button new script")->setEnabled(FALSE); + getChildView("btn_reset_scripts")->setEnabled(FALSE); return; } @@ -125,6 +128,8 @@ void LLPanelContents::getState(LLViewerObject *objectp ) ((LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1) || (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1))); + getChildView("btn_reset_scripts")->setEnabled(editable); + getChildView("button permissions")->setEnabled(!objectp->isPermanentEnforced()); mPanelInventoryObject->setEnabled(!objectp->isPermanentEnforced()); } @@ -206,3 +211,9 @@ void LLPanelContents::onClickPermissions(void *userdata) LLPanelContents* self = (LLPanelContents*)userdata; gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterReg::showInstance("bulk_perms")); } + +// static +void LLPanelContents::onClickResetScripts(void *userdata) +{ + handle_selected_script_action("reset"); +} diff --git a/indra/newview/llpanelcontents.h b/indra/newview/llpanelcontents.h index 6ecc78afa0..5b1a57de42 100644 --- a/indra/newview/llpanelcontents.h +++ b/indra/newview/llpanelcontents.h @@ -53,6 +53,7 @@ public: static void onClickNewScript(void*); static void onClickPermissions(void*); + static void onClickResetScripts(void*); // Key suffix for "tentative" fields static const char* TENTATIVE_SUFFIX; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index f5f8b87ed5..ef31f5e3bf 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7202,58 +7202,62 @@ class LLToolsSelectedScriptAction : public view_listener_t { bool handleEvent(const LLSD& userdata) { - std::string action = userdata.asString(); - bool mono = false; - std::string msg, name; - std::string title; - if (action == "compile mono") - { - name = "compile_queue"; - mono = true; - msg = "Recompile"; - title = LLTrans::getString("CompileQueueTitle"); - } - if (action == "compile lsl") - { - name = "compile_queue"; - msg = "Recompile"; - title = LLTrans::getString("CompileQueueTitle"); - } - else if (action == "reset") - { - name = "reset_queue"; - msg = "Reset"; - title = LLTrans::getString("ResetQueueTitle"); - } - else if (action == "start") - { - name = "start_queue"; - msg = "SetRunning"; - title = LLTrans::getString("RunQueueTitle"); - } - else if (action == "stop") - { - name = "stop_queue"; - msg = "SetRunningNot"; - title = LLTrans::getString("NotRunQueueTitle"); - } - LLUUID id; id.generate(); - - LLFloaterScriptQueue* queue =LLFloaterReg::getTypedInstance(name, LLSD(id)); - if (queue) - { - queue->setMono(mono); - queue_actions(queue, msg); - queue->setTitle(title); - } - else - { - LL_WARNS() << "Failed to generate LLFloaterScriptQueue with action: " << action << LL_ENDL; - } + handle_selected_script_action(userdata.asString()); return true; } }; +void handle_selected_script_action(const std::string& action) +{ + bool mono = false; + std::string msg, name; + std::string title; + if (action == "compile mono") + { + name = "compile_queue"; + mono = true; + msg = "Recompile"; + title = LLTrans::getString("CompileQueueTitle"); + } + if (action == "compile lsl") + { + name = "compile_queue"; + msg = "Recompile"; + title = LLTrans::getString("CompileQueueTitle"); + } + else if (action == "reset") + { + name = "reset_queue"; + msg = "Reset"; + title = LLTrans::getString("ResetQueueTitle"); + } + else if (action == "start") + { + name = "start_queue"; + msg = "SetRunning"; + title = LLTrans::getString("RunQueueTitle"); + } + else if (action == "stop") + { + name = "stop_queue"; + msg = "SetRunningNot"; + title = LLTrans::getString("NotRunQueueTitle"); + } + LLUUID id; id.generate(); + + LLFloaterScriptQueue* queue = LLFloaterReg::getTypedInstance(name, LLSD(id)); + if (queue) + { + queue->setMono(mono); + queue_actions(queue, msg); + queue->setTitle(title); + } + else + { + LL_WARNS() << "Failed to generate LLFloaterScriptQueue with action: " << action << LL_ENDL; + } +} + void handle_selected_texture_info(void*) { for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin(); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 6882405407..74a15af50c 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -110,6 +110,8 @@ void handle_object_return(); void handle_object_delete(); void handle_object_edit(); +void handle_selected_script_action(const std::string& action); + void handle_buy_land(); // Takes avatar UUID, or if no UUID passed, uses last selected object diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 0abee2ff80..1377bad6cf 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2575,13 +2575,22 @@ even though the user gets a free copy. border_visible="true" bevel_style="in" follows="left|top|right" - height="325" + height="300" layout="topleft" left="10" name="contents_inventory" top="50" width="275" /> - +