diff options
55 files changed, 1074 insertions, 671 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt index 5930bab04f..bcdc5a63d2 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -177,6 +177,8 @@ Ardy Lay VWR-24917 Argent Stonecutter VWR-68 +ArminWeatherHax + STORM-1532 Armin Weatherwax VWR-8436 ArminasX Saiman @@ -568,6 +570,7 @@ Jonathan Yap STORM-1276 STORM-1462 STORM-1459 + STORM-1297 STORM-1522 STORM-1567 STORM-1572 diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index cc6bddc4da..60d4cfe6d3 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -322,6 +322,7 @@ if (LL_TESTS) LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}" "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/setpython.py") + LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}") diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp index ebb5961c91..463f558c2c 100644 --- a/indra/llcommon/llfasttimer_class.cpp +++ b/indra/llcommon/llfasttimer_class.cpp @@ -303,14 +303,15 @@ LLFastTimer::NamedTimer::~NamedTimer() std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx) { + F64 ms_multiplier = 1000.0 / (F64)LLFastTimer::countsPerSecond(); if (history_idx < 0) { - // by default, show average number of calls - return llformat("%s (%d calls)", getName().c_str(), (S32)getCallAverage()); + // by default, show average number of call + return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getCountAverage() * ms_multiplier), (S32)getCallAverage()); } else { - return llformat("%s (%d calls)", getName().c_str(), (S32)getHistoricalCalls(history_idx)); + return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getHistoricalCount(history_idx) * ms_multiplier), (S32)getHistoricalCalls(history_idx)); } } @@ -693,17 +694,7 @@ void LLFastTimer::nextFrame() llinfos << "Slow frame, fast timers inaccurate" << llendl; } - if (sPauseHistory) - { - sResetHistory = true; - } - else if (sResetHistory) - { - sLastFrameIndex = 0; - sCurFrameIndex = 0; - sResetHistory = false; - } - else // not paused + if (!sPauseHistory) { NamedTimer::processTimes(); sLastFrameIndex = sCurFrameIndex++; diff --git a/indra/llcommon/llfasttimer_class.h b/indra/llcommon/llfasttimer_class.h index 827747f0c6..f481e968a6 100644 --- a/indra/llcommon/llfasttimer_class.h +++ b/indra/llcommon/llfasttimer_class.h @@ -66,7 +66,7 @@ public: public: ~NamedTimer(); - enum { HISTORY_NUM = 60 }; + enum { HISTORY_NUM = 300 }; const std::string& getName() const { return mName; } NamedTimer* getParent() const { return mParent; } diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp index f576204511..5dc3ea5d7b 100644 --- a/indra/llcommon/llinstancetracker.cpp +++ b/indra/llcommon/llinstancetracker.cpp @@ -35,14 +35,15 @@ //static void * & LLInstanceTrackerBase::getInstances(std::type_info const & info) { - static std::map<std::string, void *> instances; + typedef std::map<std::string, void *> InstancesMap; + static InstancesMap instances; - std::string k = info.name(); - if(instances.find(k) == instances.end()) - { - instances[k] = NULL; - } - - return instances[k]; + // std::map::insert() is just what we want here. You attempt to insert a + // (key, value) pair. If the specified key doesn't yet exist, it inserts + // the pair and returns a std::pair of (iterator, true). If the specified + // key DOES exist, insert() simply returns (iterator, false). One lookup + // handles both cases. + return instances.insert(InstancesMap::value_type(info.name(), + InstancesMap::mapped_type())) + .first->second; } - diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index afb714c71c..5a3990a8df 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -29,6 +29,7 @@ #define LL_LLINSTANCETRACKER_H #include <map> +#include <typeinfo> #include "string_table.h" #include <boost/utility.hpp> @@ -37,10 +38,40 @@ #include <boost/iterator/transform_iterator.hpp> #include <boost/iterator/indirect_iterator.hpp> +/** + * Base class manages "class-static" data that must actually have singleton + * semantics: one instance per process, rather than one instance per module as + * sometimes happens with data simply declared static. + */ class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable { - protected: - static void * & getInstances(std::type_info const & info); +protected: + /// Get a process-unique void* pointer slot for the specified type_info + static void * & getInstances(std::type_info const & info); + + /// Find or create a STATICDATA instance for the specified TRACKED class. + /// STATICDATA must be default-constructible. + template<typename STATICDATA, class TRACKED> + static STATICDATA& getStatic() + { + void *& instances = getInstances(typeid(TRACKED)); + if (! instances) + { + instances = new STATICDATA; + } + return *static_cast<STATICDATA*>(instances); + } + + /// It's not essential to derive your STATICDATA (for use with + /// getStatic()) from StaticBase; it's just that both known + /// implementations do. + struct StaticBase + { + StaticBase(): + sIterationNestDepth(0) + {} + S32 sIterationNestDepth; + }; }; /// This mix-in class adds support for tracking all instances of the specified class parameter T @@ -50,8 +81,15 @@ class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable template<typename T, typename KEY = T*> class LLInstanceTracker : public LLInstanceTrackerBase { - typedef typename std::map<KEY, T*> InstanceMap; typedef LLInstanceTracker<T, KEY> MyT; + typedef typename std::map<KEY, T*> InstanceMap; + struct StaticData: public StaticBase + { + InstanceMap sMap; + }; + static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); } + static InstanceMap& getMap_() { return getStatic().sMap; } + public: class instance_iter : public boost::iterator_facade<instance_iter, T, boost::forward_traversal_tag> { @@ -61,12 +99,12 @@ public: instance_iter(const typename InstanceMap::iterator& it) : mIterator(it) { - ++sIterationNestDepth; + ++getStatic().sIterationNestDepth; } ~instance_iter() { - --sIterationNestDepth; + --getStatic().sIterationNestDepth; } @@ -95,18 +133,18 @@ public: key_iter(typename InstanceMap::iterator it) : mIterator(it) { - ++sIterationNestDepth; + ++getStatic().sIterationNestDepth; } key_iter(const key_iter& other) : mIterator(other.mIterator) { - ++sIterationNestDepth; + ++getStatic().sIterationNestDepth; } ~key_iter() { - --sIterationNestDepth; + --getStatic().sIterationNestDepth; } @@ -159,8 +197,8 @@ protected: virtual ~LLInstanceTracker() { // it's unsafe to delete instances of this type while all instances are being iterated over. - llassert(sIterationNestDepth == 0); - remove_(); + llassert_always(getStatic().sIterationNestDepth == 0); + remove_(); } virtual void setKey(KEY key) { remove_(); add_(key); } virtual const KEY& getKey() const { return mInstanceKey; } @@ -176,31 +214,24 @@ private: getMap_().erase(mInstanceKey); } - static InstanceMap& getMap_() - { - void * & instances = getInstances(typeid(MyT)); - if (! instances) - { - instances = new InstanceMap; - } - return * static_cast<InstanceMap*>(instances); - } - private: - KEY mInstanceKey; - static S32 sIterationNestDepth; }; -template <typename T, typename KEY> S32 LLInstanceTracker<T, KEY>::sIterationNestDepth = 0; - /// explicit specialization for default case where KEY is T* /// use a simple std::set<T*> template<typename T> class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase { - typedef typename std::set<T*> InstanceSet; typedef LLInstanceTracker<T, T*> MyT; + typedef typename std::set<T*> InstanceSet; + struct StaticData: public StaticBase + { + InstanceSet sSet; + }; + static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); } + static InstanceSet& getSet_() { return getStatic().sSet; } + public: /// for completeness of analogy with the generic implementation @@ -213,18 +244,18 @@ public: instance_iter(const typename InstanceSet::iterator& it) : mIterator(it) { - ++sIterationNestDepth; + ++getStatic().sIterationNestDepth; } instance_iter(const instance_iter& other) : mIterator(other.mIterator) { - ++sIterationNestDepth; + ++getStatic().sIterationNestDepth; } ~instance_iter() { - --sIterationNestDepth; + --getStatic().sIterationNestDepth; } private: @@ -250,13 +281,13 @@ public: protected: LLInstanceTracker() { - // it's safe but unpredictable to create instances of this type while all instances are being iterated over. I hate unpredictable. This assert will probably be turned on early in the next development cycle. + // it's safe but unpredictable to create instances of this type while all instances are being iterated over. I hate unpredictable. This assert will probably be turned on early in the next development cycle. getSet_().insert(static_cast<T*>(this)); } virtual ~LLInstanceTracker() { // it's unsafe to delete instances of this type while all instances are being iterated over. - llassert(sIterationNestDepth == 0); + llassert_always(getStatic().sIterationNestDepth == 0); getSet_().erase(static_cast<T*>(this)); } @@ -264,20 +295,6 @@ protected: { getSet_().insert(static_cast<T*>(this)); } - - static InstanceSet& getSet_() - { - void * & instances = getInstances(typeid(MyT)); - if (! instances) - { - instances = new InstanceSet; - } - return * static_cast<InstanceSet *>(instances); - } - - static S32 sIterationNestDepth; }; -template <typename T> S32 LLInstanceTracker<T, T*>::sIterationNestDepth = 0; - #endif diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 00757be277..49d99f2cd0 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -114,8 +114,7 @@ private: ~SingletonInstanceData() { - SingletonInstanceData& data = getData(); - if (data.mInitState != DELETED) + if (mInitState != DELETED) { deleteSingleton(); } @@ -130,7 +129,26 @@ public: data.mInitState = DELETED; } - // Can be used to control when the singleton is deleted. Not normally needed. + /** + * @brief Immediately delete the singleton. + * + * A subsequent call to LLProxy::getInstance() will construct a new + * instance of the class. + * + * LLSingletons are normally destroyed after main() has exited and the C++ + * runtime is cleaning up statically-constructed objects. Some classes + * derived from LLSingleton have objects that are part of a runtime system + * that is terminated before main() exits. Calling the destructor of those + * objects after the termination of their respective systems can cause + * crashes and other problems during termination of the project. Using this + * method to destroy the singleton early can prevent these crashes. + * + * An example where this is needed is for a LLSingleton that has an APR + * object as a member that makes APR calls on destruction. The APR system is + * shut down explicitly before main() exits. This causes a crash on exit. + * Using this method before the call to apr_terminate() and NOT calling + * getInstance() again will prevent the crash. + */ static void deleteSingleton() { delete getData().mSingletonInstance; diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index 80b35bbdc3..b34d1c5fd3 100644 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -40,6 +40,7 @@ #include <boost/scoped_ptr.hpp> // other Linden headers #include "../test/lltut.h" +#include "wrapllerrs.h" struct Keyed: public LLInstanceTracker<Keyed, std::string> { @@ -165,4 +166,67 @@ namespace tut ensure_equals("unreported instance", instances.size(), 0); } + + template<> template<> + void object::test<5>() + { + set_test_name("delete Keyed with outstanding instance_iter"); + std::string what; + Keyed* keyed = new Keyed("one"); + { + WrapLL_ERRS wrapper; + Keyed::instance_iter i(Keyed::beginInstances()); + try + { + delete keyed; + } + catch (const WrapLL_ERRS::FatalException& e) + { + what = e.what(); + } + } + ensure(! what.empty()); + } + + template<> template<> + void object::test<6>() + { + set_test_name("delete Keyed with outstanding key_iter"); + std::string what; + Keyed* keyed = new Keyed("one"); + { + WrapLL_ERRS wrapper; + Keyed::key_iter i(Keyed::beginKeys()); + try + { + delete keyed; + } + catch (const WrapLL_ERRS::FatalException& e) + { + what = e.what(); + } + } + ensure(! what.empty()); + } + + template<> template<> + void object::test<7>() + { + set_test_name("delete Unkeyed with outstanding instance_iter"); + std::string what; + Unkeyed* unkeyed = new Unkeyed; + { + WrapLL_ERRS wrapper; + Unkeyed::instance_iter i(Unkeyed::beginInstances()); + try + { + delete unkeyed; + } + catch (const WrapLL_ERRS::FatalException& e) + { + what = e.what(); + } + } + ensure(! what.empty()); + } } // namespace tut diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp new file mode 100644 index 0000000000..385289aefe --- /dev/null +++ b/indra/llcommon/tests/llsingleton_test.cpp @@ -0,0 +1,76 @@ +/** + * @file llsingleton_test.cpp + * @date 2011-08-11 + * @brief Unit test for the LLSingleton class + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llsingleton.h" +#include "../test/lltut.h" + +namespace tut +{ + struct singleton + { + // We need a class created with the LLSingleton template to test with. + class LLSingletonTest: public LLSingleton<LLSingletonTest> + { + + }; + }; + + typedef test_group<singleton> singleton_t; + typedef singleton_t::object singleton_object_t; + tut::singleton_t tut_singleton("LLSingleton"); + + template<> template<> + void singleton_object_t::test<1>() + { + + } + template<> template<> + void singleton_object_t::test<2>() + { + LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); + ensure(singleton_test); + } + template<> template<> + void singleton_object_t::test<3>() + { + //Construct the instance + LLSingletonTest::getInstance(); + ensure(LLSingletonTest::instanceExists()); + + //Delete the instance + LLSingletonTest::deleteSingleton(); + ensure(LLSingletonTest::destroyed()); + ensure(!LLSingletonTest::instanceExists()); + + //Construct it again. + LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); + ensure(singleton_test); + ensure(LLSingletonTest::instanceExists()); + } +} diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index a3de178d78..14e169c6b1 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -499,7 +499,7 @@ void LLCurl::Easy::prepRequest(const std::string& url, //don't verify host name so urls with scrubbed host names will work (improves DNS performance) setopt(CURLOPT_SSL_VERIFYHOST, 0); - setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT); + setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT)); setoptString(CURLOPT_URL, url); @@ -1213,3 +1213,13 @@ void LLCurl::cleanupClass() } const unsigned int LLCurl::MAX_REDIRECTS = 5; + +// Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. +void LLCurlFF::check_easy_code(CURLcode code) +{ + check_curl_code(code); +} +void LLCurlFF::check_multi_code(CURLMcode code) +{ + check_curl_multi_code(code); +} diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 5ab4dc35b9..213b281e72 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -371,7 +371,11 @@ private: bool mResultReturned; }; -void check_curl_code(CURLcode code); -void check_curl_multi_code(CURLMcode code); +// Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. +namespace LLCurlFF +{ + void check_easy_code(CURLcode code); + void check_multi_code(CURLMcode code); +} #endif // LL_LLCURL_H diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index 7628984de4..fc6e9c5193 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -228,13 +228,13 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap) if (LLProxy::isSOCKSProxyEnabled()) { U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; - packet_size = receive_packet(socket, reinterpret_cast<char *>(buffer)); + packet_size = receive_packet(socket, static_cast<char*>(static_cast<void*>(buffer))); if (packet_size > SOCKS_HEADER_SIZE) { // *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6) memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE); - proxywrap_t * header = reinterpret_cast<proxywrap_t *>(buffer); + proxywrap_t * header = static_cast<proxywrap_t*>(static_cast<void*>(buffer)); mLastSender.setAddress(header->addr); mLastSender.setPort(ntohs(header->port)); @@ -353,14 +353,20 @@ BOOL LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 bu return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort()); } - proxywrap_t *socks_header = reinterpret_cast<proxywrap_t *>(&mProxyWrappedSendBuffer); + char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; + + proxywrap_t *socks_header = static_cast<proxywrap_t*>(static_cast<void*>(&headered_send_buffer)); socks_header->rsv = 0; socks_header->addr = host.getAddress(); socks_header->port = htons(host.getPort()); socks_header->atype = ADDRESS_IPV4; socks_header->frag = 0; - memcpy(mProxyWrappedSendBuffer + SOCKS_HEADER_SIZE, send_buffer, buf_size); + memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, send_buffer, buf_size); - return send_packet(h_socket, (const char*) mProxyWrappedSendBuffer, buf_size + 10, LLProxy::getInstance()->getUDPProxy().getAddress(), LLProxy::getInstance()->getUDPProxy().getPort()); + return send_packet( h_socket, + headered_send_buffer, + buf_size + SOCKS_HEADER_SIZE, + LLProxy::getInstance()->getUDPProxy().getAddress(), + LLProxy::getInstance()->getUDPProxy().getPort()); } diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h index 7edcc834db..b214271e78 100644 --- a/indra/llmessage/llpacketring.h +++ b/indra/llmessage/llpacketring.h @@ -83,9 +83,6 @@ protected: LLHost mLastSender; LLHost mLastReceivingIF; - - U8 mProxyWrappedSendBuffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; - private: BOOL sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host); }; diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 19f1fc6545..4a7d326c0e 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -43,7 +43,7 @@ bool LLProxy::sUDPProxyEnabled = false; // Some helpful TCP static functions. -static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen); // Do a TCP data handshake +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 static LLSocket::ptr_t tcp_open_channel(LLHost host); // Open a TCP channel to a given host static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP channel @@ -63,14 +63,13 @@ LLProxy::LLProxy(): LLProxy::~LLProxy() { stopSOCKSProxy(); - sUDPProxyEnabled = false; - mHTTPProxyEnabled = false; + disableHTTPProxy(); } /** * @brief Open the SOCKS 5 TCP control channel. * - * Perform a SOCKS 5 authentication and UDP association to the proxy server. + * Perform a SOCKS 5 authentication and UDP association with the proxy server. * * @param proxy The SOCKS 5 server to connect to. * @return SOCKS_OK if successful, otherwise a socks error code from llproxy.h. @@ -83,11 +82,15 @@ S32 LLProxy::proxyHandshake(LLHost proxy) socks_auth_request_t socks_auth_request; socks_auth_response_t socks_auth_response; - socks_auth_request.version = SOCKS_VERSION; // SOCKS version 5 - socks_auth_request.num_methods = 1; // Sending 1 method. - socks_auth_request.methods = getSelectedAuthMethod(); // Send only the selected method. + socks_auth_request.version = SOCKS_VERSION; // SOCKS version 5 + socks_auth_request.num_methods = 1; // Sending 1 method. + socks_auth_request.methods = getSelectedAuthMethod(); // Send only the selected method. - result = tcp_handshake(mProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request), (char*)&socks_auth_response, sizeof(socks_auth_response)); + result = tcp_blocking_handshake(mProxyControlChannel, + static_cast<char*>(static_cast<void*>(&socks_auth_request)), + sizeof(socks_auth_request), + static_cast<char*>(static_cast<void*>(&socks_auth_response)), + sizeof(socks_auth_response)); if (result != APR_SUCCESS) { LL_WARNS("Proxy") << "SOCKS authentication request failed, error on TCP control channel : " << result << LL_ENDL; @@ -97,12 +100,12 @@ S32 LLProxy::proxyHandshake(LLHost proxy) if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE) { - LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods" << LL_ENDL; + LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods." << LL_ENDL; stopSOCKSProxy(); return SOCKS_NOT_ACCEPTABLE; } - // SOCKS 5 USERNAME/PASSWORD authentication + /* SOCKS 5 USERNAME/PASSWORD authentication */ if (socks_auth_response.method == METHOD_PASSWORD) { // The server has requested a username/password combination @@ -114,11 +117,15 @@ S32 LLProxy::proxyHandshake(LLHost proxy) password_auth[1] = socks_username.size(); memcpy(&password_auth[2], socks_username.c_str(), socks_username.size()); password_auth[socks_username.size() + 2] = socks_password.size(); - memcpy(&password_auth[socks_username.size()+3], socks_password.c_str(), socks_password.size()); + memcpy(&password_auth[socks_username.size() + 3], socks_password.c_str(), socks_password.size()); authmethod_password_reply_t password_reply; - result = tcp_handshake(mProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(password_reply)); + result = tcp_blocking_handshake(mProxyControlChannel, + password_auth, + request_size, + static_cast<char*>(static_cast<void*>(&password_reply)), + sizeof(password_reply)); delete[] password_auth; if (result != APR_SUCCESS) @@ -150,7 +157,11 @@ S32 LLProxy::proxyHandshake(LLHost proxy) // "If the client is not in possession of the information at the time of the UDP ASSOCIATE, // the client MUST use a port number and address of all zeros. RFC 1928" - result = tcp_handshake(mProxyControlChannel, (char*)&connect_request, sizeof(connect_request), (char*)&connect_reply, sizeof(connect_reply)); + result = tcp_blocking_handshake(mProxyControlChannel, + static_cast<char*>(static_cast<void*>(&connect_request)), + sizeof(connect_request), + static_cast<char*>(static_cast<void*>(&connect_reply)), + sizeof(connect_reply)); if (result != APR_SUCCESS) { LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL; @@ -169,6 +180,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy) mUDPProxy.setAddress(proxy.getAddress()); // The connection was successful. We now have the UDP port to send requests that need forwarding to. LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << mUDPProxy << LL_ENDL; + return SOCKS_OK; } @@ -176,7 +188,8 @@ S32 LLProxy::proxyHandshake(LLHost proxy) * @brief Initiates a SOCKS 5 proxy session. * * Performs basic checks on host to verify that it is a valid address. Opens the control channel - * and then negotiates the proxy connection with the server. + * and then negotiates the proxy connection with the server. Closes any existing SOCKS + * connection before proceeding. Also disables an HTTP proxy if it is using SOCKS as the proxy. * * * @param host Socks server to connect to. @@ -184,43 +197,37 @@ S32 LLProxy::proxyHandshake(LLHost proxy) */ S32 LLProxy::startSOCKSProxy(LLHost host) { - S32 status = SOCKS_OK; - if (host.isOk()) { mTCPProxy = host; } else { - status = SOCKS_INVALID_HOST; + return SOCKS_INVALID_HOST; } - if (mProxyControlChannel && status == SOCKS_OK) - { - tcp_close_channel(&mProxyControlChannel); - } + // Close any running SOCKS connection. + stopSOCKSProxy(); - if (status == SOCKS_OK) + mProxyControlChannel = tcp_open_channel(mTCPProxy); + if (!mProxyControlChannel) { - mProxyControlChannel = tcp_open_channel(mTCPProxy); - if (!mProxyControlChannel) - { - status = SOCKS_HOST_CONNECT_FAILED; - } + return SOCKS_HOST_CONNECT_FAILED; } - if (status == SOCKS_OK) - { - status = proxyHandshake(mTCPProxy); - } - if (status == SOCKS_OK) + S32 status = proxyHandshake(mTCPProxy); + + if (status != SOCKS_OK) { - sUDPProxyEnabled = true; + // Shut down the proxy if any of the above steps failed. + stopSOCKSProxy(); } else { - stopSOCKSProxy(); + // Connection was successful. + sUDPProxyEnabled = true; } + return status; } @@ -241,7 +248,7 @@ void LLProxy::stopSOCKSProxy() if (LLPROXY_SOCKS == getHTTPProxyType()) { - void disableHTTPProxy(); + disableHTTPProxy(); } if (mProxyControlChannel) @@ -350,16 +357,6 @@ void LLProxy::disableHTTPProxy() } /** - * @brief Get the HTTP proxy address and port - */ -// -LLHost LLProxy::getHTTPProxy() const -{ - LLMutexLock lock(&mProxyMutex); - return mHTTPProxy; -} - -/** * @brief Get the currently selected HTTP proxy type */ LLHttpProxyType LLProxy::getHTTPProxyType() const @@ -440,21 +437,21 @@ void LLProxy::applyProxySettings(CURL* handle) // Now test again to verify that the proxy wasn't disabled between the first check and the lock. if (mHTTPProxyEnabled) { - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str())); - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort())); + LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str())); + LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort())); if (mProxyType == LLPROXY_SOCKS) { - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); + LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); if (mAuthMethodSelected == METHOD_PASSWORD) { std::string auth_string = mSocksUsername + ":" + mSocksPassword; - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str())); + LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str())); } } else { - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); + LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); } } } @@ -473,7 +470,7 @@ void LLProxy::applyProxySettings(CURL* handle) * @param maxinlen Maximum possible length of received data. Short reads are allowed. * @return Indicates APR status code of exchange. APR_SUCCESS if exchange was successful, -1 if invalid data length was received. */ -static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen) +static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen) { apr_socket_t* apr_socket = handle->getSocket(); apr_status_t rv = APR_SUCCESS; @@ -522,7 +519,6 @@ static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outl * * Checks for a successful connection, and makes sure the connection is closed if it fails. * - * @param pool APR pool to pass into the LLSocket. * @param host The host to open the connection to. * @return The created socket. Will evaluate as NULL if the connection is unsuccessful. */ @@ -541,7 +537,7 @@ static LLSocket::ptr_t tcp_open_channel(LLHost host) /** * @brief Close the socket. * - * @param handle_ptr A pointer-to-pointer to avoid increasing the use count. + * @param handle_ptr The handle of the socket being closed. A pointer-to-pointer to avoid increasing the use count. */ static void tcp_close_channel(LLSocket::ptr_t* handle_ptr) { diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h index 621debb61d..a919370540 100644 --- a/indra/llmessage/llproxy.h +++ b/indra/llmessage/llproxy.h @@ -36,7 +36,6 @@ #include <string> // SOCKS error codes returned from the StartProxy method - #define SOCKS_OK 0 #define SOCKS_CONNECT_ERROR (-1) #define SOCKS_NOT_PERMITTED (-2) @@ -46,7 +45,6 @@ #define SOCKS_HOST_CONNECT_FAILED (-6) #define SOCKS_INVALID_HOST (-7) - #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */ #endif @@ -225,62 +223,71 @@ class LLProxy: public LLSingleton<LLProxy> { LOG_CLASS(LLProxy); public: - // METHODS THAT DO NOT LOCK mProxyMutex! - + /*########################################################################################### + METHODS THAT DO NOT LOCK mProxyMutex! + ###########################################################################################*/ + // Constructor, cannot have parameters due to LLSingleton parent class. Call from main thread only. LLProxy(); - // static check for enabled status for UDP packets + // Static check for enabled status for UDP packets. Call from main thread only. static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; } - // check for enabled status for HTTP packets - // mHTTPProxyEnabled is atomic, so no locking is required for thread safety. - bool isHTTPProxyEnabled() const { return mHTTPProxyEnabled; } - - // Get the UDP proxy address and port + // Get the UDP proxy address and port. Call from main thread only. LLHost getUDPProxy() const { return mUDPProxy; } - // Get the SOCKS 5 TCP control channel address and port - LLHost getTCPProxy() const { return mTCPProxy; } + /*########################################################################################### + END OF NON-LOCKING METHODS + ###########################################################################################*/ - // END OF NON-LOCKING METHODS + /*########################################################################################### + METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED! + ###########################################################################################*/ + // Destructor, closes open connections. Do not call directly, use cleanupClass(). + ~LLProxy(); - // METHODS THAT DO LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED! + // Delete LLProxy singleton. Allows the apr_socket used in the SOCKS 5 control channel to be + // destroyed before the call to apr_terminate. Call from main thread only. + static void cleanupClass(); - ~LLProxy(); + // 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); + void applyProxySettings(LLCurl::Easy* handle); + void applyProxySettings(LLCurlEasyRequest* handle); - // Start a connection to the SOCKS 5 proxy + // Start a connection to the SOCKS 5 proxy. Call from main thread only. S32 startSOCKSProxy(LLHost host); - // Disconnect and clean up any connection to the SOCKS 5 proxy + // Disconnect and clean up any connection to the SOCKS 5 proxy. Call from main thread only. void stopSOCKSProxy(); - // Delete LLProxy singleton, destroying the APR pool used by the control channel. - static void cleanupClass(); - - // Set up to use Password auth when connecting to the SOCKS proxy + // Use Password auth when connecting to the SOCKS proxy. Call from main thread only. bool setAuthPassword(const std::string &username, const std::string &password); - // Set up to use No Auth when connecting to the SOCKS proxy + // Disable authentication when connecting to the SOCKS proxy. Call from main thread only. void setAuthNone(); - // Get the currently selected auth method. - LLSocks5AuthType getSelectedAuthMethod() const; - - // Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy - // as specified in type + // Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy. + // as specified in type. Call from main thread only. bool enableHTTPProxy(LLHost httpHost, LLHttpProxyType type); bool enableHTTPProxy(); - // Stop proxying HTTP packets + // Stop proxying HTTP packets. Call from main thread only. void disableHTTPProxy(); - // Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false. - void applyProxySettings(CURL* handle); - void applyProxySettings(LLCurl::Easy* handle); - void applyProxySettings(LLCurlEasyRequest* handle); + /*########################################################################################### + END OF LOCKING METHODS + ###########################################################################################*/ +private: + /*########################################################################################### + METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED! + ###########################################################################################*/ - // Get the HTTP proxy address and port - LLHost getHTTPProxy() const; + // Perform a SOCKS 5 authentication and UDP association with the proxy server. + S32 proxyHandshake(LLHost proxy); + + // Get the currently selected auth method. + LLSocks5AuthType getSelectedAuthMethod() const; // Get the currently selected HTTP proxy type LLHttpProxyType getHTTPProxyType() const; @@ -288,21 +295,21 @@ public: std::string getSocksPwd() const; std::string getSocksUser() const; - // END OF LOCKING METHODS -private: - // Open a communication channel to the SOCKS 5 proxy proxy, at port messagePort - S32 proxyHandshake(LLHost proxy); + /*########################################################################################### + END OF LOCKING METHODS + ###########################################################################################*/ private: - // Is the HTTP proxy enabled? - // Safe to read in any thread, do not write directly, - // use enableHTTPProxy() and disableHTTPProxy() instead. + // Is the HTTP proxy enabled? Safe to read in any thread, but do not write directly. + // Instead use enableHTTPProxy() and disableHTTPProxy() instead. mutable LLAtomic32<bool> mHTTPProxyEnabled; - // Mutex to protect shared members in non-main thread calls to applyProxySettings() + // Mutex to protect shared members in non-main thread calls to applyProxySettings(). mutable LLMutex mProxyMutex; - // MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE! + /*########################################################################################### + MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE! + ###########################################################################################*/ // Is the UDP proxy enabled? static bool sUDPProxyEnabled; @@ -315,9 +322,13 @@ private: // socket handle to proxy TCP control channel LLSocket::ptr_t mProxyControlChannel; - // END OF UNSHARED MEMBERS + /*########################################################################################### + END OF UNSHARED MEMBERS + ###########################################################################################*/ - // MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex! + /*########################################################################################### + MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex! + ###########################################################################################*/ // HTTP proxy address and port LLHost mHTTPProxy; @@ -325,7 +336,7 @@ private: // Currently selected HTTP proxy type. Can be web or socks. LLHttpProxyType mProxyType; - // SOCKS 5 auth method selected + // SOCKS 5 selected authentication method. LLSocks5AuthType mAuthMethodSelected; // SOCKS 5 username @@ -333,7 +344,9 @@ private: // SOCKS 5 password std::string mSocksPassword; - // END OF SHARED MEMBERS + /*########################################################################################### + END OF SHARED MEMBERS + ###########################################################################################*/ }; #endif diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 6085c61f9a..ffe5908a9d 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -245,7 +245,6 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica LLParamSDParser parser; parser.writeSD(mFormData, p.form_elements); - mFormData = mFormData[""]; if (!mFormData.isArray()) { // change existing contents to a one element array diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index eff572b553..ab777d37a5 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -88,10 +88,10 @@ struct LLNotificationTemplate { private: // this idiom allows - // <notification unique="true"> + // <notification> <unique/> </notification> // as well as // <notification> <unique> <context></context> </unique>... - Optional<bool> dummy_val; + Flag dummy_val; public: Multiple<UniquenessContext> contexts; diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index b44b4c36b6..fe3f688fc5 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -223,6 +223,15 @@ BOOL LLScrollContainer::handleKeyHere(KEY key, MASK mask) return FALSE; } +BOOL LLScrollContainer::handleUnicodeCharHere(llwchar uni_char) +{ + if (mScrolledView && mScrolledView->handleUnicodeCharHere(uni_char)) + { + return TRUE; + } + return FALSE; +} + BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks ) { // Give event to my child views - they may have scroll bars diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index 46a71a7e30..3aa79cc255 100644 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -103,6 +103,7 @@ public: // LLView functionality virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); virtual BOOL handleKeyHere(KEY key, MASK mask); + virtual BOOL handleUnicodeCharHere(llwchar uni_char); virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 9ad13054cb..04919e6991 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -183,7 +183,7 @@ LLSD* LLParamSDParser::getSDWriteNode(const parser_t::name_stack_t& name_stack) } } - LLSD* child_sd = &(*sd_to_write)[it->first]; + LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first]; if (child_sd->isArray()) { diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index f0ba7fc7d7..d345ad4cd0 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -125,12 +125,12 @@ private: // base case for recursion, there are NO base classes of LLInitParam::BaseBlock template<int DUMMY> - class ParamDefaults<LLInitParam::BaseBlock, DUMMY> : public LLSingleton<ParamDefaults<LLInitParam::BaseBlock, DUMMY> > + class ParamDefaults<LLInitParam::BaseBlockWithFlags, DUMMY> : public LLSingleton<ParamDefaults<LLInitParam::BaseBlockWithFlags, DUMMY> > { public: - const LLInitParam::BaseBlock& get() { return mBaseBlock; } + const LLInitParam::BaseBlockWithFlags& get() { return mBaseBlock; } private: - LLInitParam::BaseBlock mBaseBlock; + LLInitParam::BaseBlockWithFlags mBaseBlock; }; public: diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 9d0fe781ce..69dcd474f7 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -289,15 +289,15 @@ namespace LLInitParam protected: bool anyProvided() const { return mIsProvided; } - Param(class BaseBlock* enclosing_block); + Param(BaseBlock* enclosing_block); // store pointer to enclosing block as offset to reduce space and allow for quick copying - class BaseBlock& enclosingBlock() const + BaseBlock& enclosingBlock() const { const U8* my_addr = reinterpret_cast<const U8*>(this); // get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class - return *const_cast<class BaseBlock*> - (reinterpret_cast<const class BaseBlock*> + return *const_cast<BaseBlock*> + (reinterpret_cast<const BaseBlock*> (my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset)); } @@ -367,18 +367,16 @@ namespace LLInitParam typedef boost::unordered_map<const std::string, ParamDescriptorPtr> param_map_t; typedef std::vector<ParamDescriptorPtr> param_list_t; - typedef std::list<ParamDescriptorPtr> all_params_list_t; + typedef std::list<ParamDescriptorPtr> all_params_list_t; typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> > param_validation_list_t; param_map_t mNamedParams; // parameters with associated names param_list_t mUnnamedParams; // parameters with_out_ associated names param_validation_list_t mValidationList; // parameters that must be validated all_params_list_t mAllParams; // all parameters, owns descriptors - - size_t mMaxParamOffset; - - EInitializationState mInitializationState; // whether or not static block data has been initialized - class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed + size_t mMaxParamOffset; + EInitializationState mInitializationState; // whether or not static block data has been initialized + BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed }; class BaseBlock @@ -499,6 +497,92 @@ namespace LLInitParam const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; }; + class BaseBlockWithFlags : public BaseBlock + { + public: + class FlagBase : public Param + { + public: + typedef FlagBase self_t; + + FlagBase(const char* name, BaseBlock* enclosing_block) : Param(enclosing_block) + { + if (LL_UNLIKELY(enclosing_block->mostDerivedBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + enclosing_block->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + NULL, + &inspectParam, + 0, 1)); + BaseBlock::addParam(enclosing_block->mostDerivedBlockDescriptor(), param_descriptor, name); + } + } + + bool isProvided() const { return anyProvided(); } + + private: + static bool mergeWith(Param& dst, const Param& src, bool overwrite) + { + const self_t& src_typed_param = static_cast<const self_t&>(src); + self_t& dst_typed_param = static_cast<self_t&>(dst); + + if (src_typed_param.isProvided() + && (overwrite || !dst_typed_param.isProvided())) + { + dst.setProvided(true); + return true; + } + return false; + } + + static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation) + { + self_t& typed_param = static_cast<self_t&>(param); + + // no further names in stack, parse value now + if (name_stack.first == name_stack.second) + { + typed_param.setProvided(true); + typed_param.enclosingBlock().paramChanged(param, true); + return true; + } + + return false; + } + + static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + { + const self_t& typed_param = static_cast<const self_t&>(param); + const self_t* typed_diff_param = static_cast<const self_t*>(diff_param); + + if (!typed_param.isProvided()) return; + + if (!name_stack.empty()) + { + name_stack.back().second = parser.newParseGeneration(); + } + + // then try to serialize value directly + if (!typed_diff_param || !typed_diff_param->isProvided()) + { + if (!parser.writeValue(NoParamValue(), name_stack)) + { + return; + } + } + } + + static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) + { + // tell parser about our actual type + parser.inspectValue<NoParamValue>(name_stack, min_count, max_count, NULL); + } + }; + }; + // these templates allow us to distinguish between template parameters // that derive from BaseBlock and those that don't template<typename T, typename Void = void> @@ -1424,7 +1508,7 @@ namespace LLInitParam } }; - template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock> + template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlockWithFlags> class Block : public BASE_BLOCK { @@ -1520,6 +1604,13 @@ namespace LLInitParam }; + class Flag : public BaseBlockWithFlags::FlagBase + { + public: + Flag(const char* name) : FlagBase(name, DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr) + {} + }; + template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> > class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true> { diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index 72a7bb7af5..4af077b22c 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -440,12 +440,11 @@ bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block) && nodep->mAttributes.empty() && nodep->getSanitizedValue().empty()) { - // empty node, just parse as NoValue + // empty node, just parse as flag mCurReadNode = DUMMY_NODE; return block.submitValue(mNameStack, *this, silent); } - // submit attributes for current node values_parsed |= readAttributes(nodep, block); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 7ab9f36b87..60025707a4 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1858,7 +1858,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>Cursor3D</key> <map> @@ -4059,7 +4059,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>http://search.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]</string> + <string>http://search.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]&p=[AUTH_TOKEN]&r=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID]&channel=[CHANNEL]&version=[VERSION]&major=[VERSION_MAJOR]&minor=[VERSION_MINOR]&patch=[VERSION_PATCH]&build=[VERSION_BUILD]</string> </map> <key>WebProfileURL</key> <map> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index c7140283f1..d8295ddb87 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -34,15 +34,15 @@ <string /> </map> <key>LastInventoryInboxActivity</key> - <map> - <key>Comment</key> + <map> + <key>Comment</key> <string>The last time the received items inbox was poked by the user.</string> - <key>Persist</key> + <key>Persist</key> <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string /> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>0</integer> </map> <key>LastLogoff</key> <map> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 7e597fe5dc..4e1ef59765 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -786,6 +786,12 @@ bool LLAppViewer::init() &LLUI::sGLScaleFactor); LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ; + // Setup paths and LLTrans after LLUI::initClass has been called. + LLUI::setupPaths(); + LLTransUtil::parseStrings("strings.xml", default_trans_args); + LLTransUtil::parseLanguageStrings("language_settings.xml"); + + // Setup notifications after LLUI::setupPaths() has been called. LLNotifications::instance(); LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ; @@ -831,12 +837,6 @@ bool LLAppViewer::init() LLError::setPrintLocation(true); } - - // Setup paths and LLTrans after LLUI::initClass has been called - LLUI::setupPaths(); - LLTransUtil::parseStrings("strings.xml", default_trans_args); - LLTransUtil::parseLanguageStrings("language_settings.xml"); - // LLKeyboard relies on LLUI to know what some accelerator keys are called. LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString ); diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 79e6c7b66b..c8cfe5b51e 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -201,7 +201,8 @@ public: }; LLBottomTray::LLBottomTray(const LLSD&) -: mChicletPanel(NULL), +: mDesiredNearbyChatWidth(0), + mChicletPanel(NULL), mSpeakPanel(NULL), mSpeakBtn(NULL), mNearbyChatBar(NULL), @@ -1095,33 +1096,35 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width) if (still_should_be_processed) { processShrinkButtons(delta_width, buttons_freed_width); + still_should_be_processed = delta_width < 0; } + // 3. Decreasing width of nearby chat. const S32 chatbar_panel_min_width = get_panel_min_width(mToolbarStack, mChatBarContainer); const S32 chatbar_panel_width = mChatBarContainer->getRect().getWidth(); if (still_should_be_processed && chatbar_panel_width > chatbar_panel_min_width) { // we have some space to decrease chatbar panel - S32 panel_delta_min = chatbar_panel_width - chatbar_panel_min_width; + S32 chatbar_shrink_headroom = chatbar_panel_width - chatbar_panel_min_width; - S32 delta_panel = llmin(-delta_width, panel_delta_min); + S32 shrink_by = llmin(-delta_width, chatbar_shrink_headroom); // is chatbar panel wide enough to process resizing? - delta_width += panel_delta_min; + delta_width += chatbar_shrink_headroom; still_should_be_processed = delta_width < 0; // chatbar should only be shrunk here, not stretched - if(delta_panel > 0) + if (shrink_by > 0) { - lldebugs << "Shrinking nearby chat bar by " << delta_panel << " px " << llendl; - mChatBarContainer->reshape(mNearbyChatBar->getRect().getWidth() - delta_panel, mChatBarContainer->getRect().getHeight()); + lldebugs << "Shrinking nearby chat bar by " << shrink_by << " px " << llendl; + mChatBarContainer->reshape(mNearbyChatBar->getRect().getWidth() - shrink_by, mChatBarContainer->getRect().getHeight()); } log(mNearbyChatBar, "after processing panel decreasing via nearby chatbar panel"); lldebugs << "RS_CHATBAR_INPUT" - << ", delta_panel: " << delta_panel + << ", shrink_by: " << shrink_by << ", delta_width: " << delta_width << llendl; } @@ -1200,16 +1203,16 @@ void LLBottomTray::processWidthIncreased(S32 delta_width) << ", mDesiredNearbyChatWidth = " << mDesiredNearbyChatWidth << llendl; if (delta_width > 0 && chatbar_panel_width < mDesiredNearbyChatWidth) { - S32 delta_panel_max = mDesiredNearbyChatWidth - chatbar_panel_width; - S32 delta_panel = llmin(delta_width, delta_panel_max); - lldebugs << "Unprocesed delta width: " << delta_width - << ", can be applied to chatbar: " << delta_panel_max - << ", will be applied: " << delta_panel + S32 extend_by_max = mDesiredNearbyChatWidth - chatbar_panel_width; + S32 extend_by = llmin(delta_width, extend_by_max); + lldebugs << "Unprocessed delta width: " << delta_width + << " px, chatbar can be extended by " << extend_by_max + << " px, extending it by " << extend_by << " px" << llendl; - delta_width -= delta_panel_max; - lldebugs << "Extending nearby chat bar by " << delta_panel << " px " << llendl; - mChatBarContainer->reshape(chatbar_panel_width + delta_panel, mChatBarContainer->getRect().getHeight()); + delta_width -= extend_by_max; + lldebugs << "Extending nearby chat bar by " << extend_by << " px " << llendl; + mChatBarContainer->reshape(chatbar_panel_width + extend_by, mChatBarContainer->getRect().getHeight()); log(mNearbyChatBar, "applied unprocessed delta width"); } diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 62718531ef..e26b0792e9 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -323,7 +323,7 @@ private: void processExtendButtons(S32& available_width); /** - * Extends the Speak button if there is anough headroom. + * Extends the Speak button if there is enough headroom. * * Unlike other buttons, the Speak buttons has only two possible widths: * the minimal one (without label) and the maximal (default) one. diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp index 216cc66ef8..cc6ba05e7e 100644 --- a/indra/newview/lldebugview.cpp +++ b/indra/newview/lldebugview.cpp @@ -41,6 +41,7 @@ #include "llmemoryview.h" #include "llsceneview.h" #include "llviewertexture.h" +#include "llfloaterreg.h" // // Globals @@ -79,12 +80,7 @@ void LLDebugView::init() r.setLeftTopAndSize(25, rect.getHeight() - 50, (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f), (S32) (gViewerWindow->getWindowRectScaled().getHeight() * 0.75f)); - mFastTimerView = new LLFastTimerView(r); - mFastTimerView->setFollowsTop(); - mFastTimerView->setFollowsLeft(); - mFastTimerView->setVisible(FALSE); // start invisible - addChild(mFastTimerView); - mFastTimerView->setRect(rect); + mFastTimerView = dynamic_cast<LLFastTimerView*>(LLFloaterReg::getInstance("fast_timers")); gSceneView = new LLSceneView(r); gSceneView->setFollowsTop(); diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 366154302c..a161428c2b 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -80,12 +80,10 @@ static timer_tree_iterator_t end_timer_tree() return timer_tree_iterator_t(); } -LLFastTimerView::LLFastTimerView(const LLRect& rect) -: LLFloater(LLSD()), +LLFastTimerView::LLFastTimerView(const LLSD& key) +: LLFloater(key), mHoverTimer(NULL) { - setRect(rect); - setVisible(FALSE); mDisplayMode = 0; mAvgCountTotal = 0; mMaxCountTotal = 0; @@ -98,10 +96,30 @@ LLFastTimerView::LLFastTimerView(const LLRect& rect) FTV_NUM_TIMERS = LLFastTimer::NamedTimer::instanceCount(); mPrintStats = -1; mAverageCyclesPerTimer = 0; - setCanMinimize(false); - setCanClose(true); } +void LLFastTimerView::onPause() +{ + LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory; + // reset scroll to bottom when unpausing + if (!LLFastTimer::sPauseHistory) + { + mScrollIndex = 0; + getChild<LLButton>("pause_btn")->setLabel(getString("pause")); + } + else + { + getChild<LLButton>("pause_btn")->setLabel(getString("run")); + } +} + +BOOL LLFastTimerView::postBuild() +{ + LLButton& pause_btn = getChildRef<LLButton>("pause_btn"); + + pause_btn.setCommitCallback(boost::bind(&LLFastTimerView::onPause, this)); + return TRUE; +} BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask) { @@ -116,14 +134,16 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask) { mHoverTimer->getParent()->setCollapsed(true); } + return TRUE; } else if (mBarRect.pointInRect(x, y)) { S32 bar_idx = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight()); bar_idx = llclamp(bar_idx, 0, MAX_VISIBLE_HISTORY); mPrintStats = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - bar_idx; + return TRUE; } - return FALSE; + return LLFloater::handleRightMouseDown(x, y, mask); } LLFastTimer::NamedTimer* LLFastTimerView::getLegendID(S32 y) @@ -151,18 +171,6 @@ BOOL LLFastTimerView::handleDoubleClick(S32 x, S32 y, MASK mask) BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask) { - - { - S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft; - S32 local_y = y - mButtons[BUTTON_CLOSE]->getRect().mBottom; - if(mButtons[BUTTON_CLOSE]->getVisible() - && mButtons[BUTTON_CLOSE]->pointInView(local_x, local_y) ) - { - return LLFloater::handleMouseDown(x, y, mask);; - } - } - - if (x < mBarRect.mLeft) { LLFastTimer::NamedTimer* idp = getLegendID(y); @@ -196,36 +204,42 @@ BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask) { mDisplayCenter = (ChildAlignment)((mDisplayCenter + 1) % ALIGN_COUNT); } - else + else if (mGraphRect.pointInRect(x, y)) { - // pause/unpause - LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory; - // reset scroll to bottom when unpausing - if (!LLFastTimer::sPauseHistory) - { - mScrollIndex = 0; - } + gFocusMgr.setMouseCapture(this); + return TRUE; } - // SJB: Don't pass mouse clicks through the display - return TRUE; + //else + //{ + // // pause/unpause + // LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory; + // // reset scroll to bottom when unpausing + // if (!LLFastTimer::sPauseHistory) + // { + // mScrollIndex = 0; + // } + //} + return LLFloater::handleMouseDown(x, y, mask); } BOOL LLFastTimerView::handleMouseUp(S32 x, S32 y, MASK mask) { + if (hasMouseCapture()) { - S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft; - S32 local_y = y - mButtons[BUTTON_CLOSE]->getRect().mBottom; - if(mButtons[BUTTON_CLOSE]->getVisible() - && mButtons[BUTTON_CLOSE]->pointInView(local_x, local_y) ) - { - return LLFloater::handleMouseUp(x, y, mask);; - } + gFocusMgr.setMouseCapture(NULL); } - return FALSE; + return LLFloater::handleMouseUp(x, y, mask);; } BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) { + if (hasMouseCapture()) + { + F32 lerp = llclamp(1.f - (F32) (x - mGraphRect.mLeft) / (F32) mGraphRect.getWidth(), 0.f, 1.f); + mScrollIndex = llround( lerp * (F32)(LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY)); + mScrollIndex = llclamp( mScrollIndex, 0, LLFastTimer::getLastFrameIndex()); + return TRUE; + } mHoverTimer = NULL; mHoverID = NULL; @@ -282,7 +296,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) } } - return FALSE; + return LLFloater::handleHover(x, y, mask); } @@ -318,15 +332,15 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask) } } } - - return FALSE; + + return LLFloater::handleToolTip(x, y, mask); } BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks) { LLFastTimer::sPauseHistory = TRUE; - mScrollIndex = llclamp(mScrollIndex - clicks, - 0, + mScrollIndex = llclamp( mScrollIndex + clicks, + 0, llmin(LLFastTimer::getLastFrameIndex(), (S32)LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY)); return TRUE; } @@ -345,8 +359,8 @@ void LLFastTimerView::draw() F64 iclock_freq = 1000.0 / clock_freq; S32 margin = 10; - S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f); - S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f); + S32 height = getRect().getHeight(); + S32 width = getRect().getWidth(); LLRect new_rect; new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height); @@ -630,7 +644,6 @@ void LLFastTimerView::draw() LLFontGL::LEFT, LLFontGL::TOP); } - LLRect graph_rect; // Draw borders { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -663,9 +676,9 @@ void LLFastTimerView::draw() by = LINE_GRAPH_HEIGHT-barh-dy-7; //line graph - graph_rect = LLRect(xleft-5, by, getRect().getWidth()-5, 5); + mGraphRect = LLRect(xleft-5, by, getRect().getWidth()-5, 5); - gl_rect_2d(graph_rect, FALSE); + gl_rect_2d(mGraphRect, FALSE); } mBarStart.clear(); @@ -813,7 +826,7 @@ void LLFastTimerView::draw() //draw line graph history { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLLocalClipRect clip(graph_rect); + LLLocalClipRect clip(mGraphRect); //normalize based on last frame's maximum static U64 last_max = 0; @@ -830,8 +843,8 @@ void LLFastTimerView::draw() else tdesc = llformat("%4.2f ms", ms); - x = graph_rect.mRight - LLFontGL::getFontMonospace()->getWidth(tdesc)-5; - y = graph_rect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight()); + x = mGraphRect.mRight - LLFontGL::getFontMonospace()->getWidth(tdesc)-5; + y = mGraphRect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight()); LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); @@ -841,24 +854,24 @@ void LLFastTimerView::draw() S32 first_frame = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex; S32 last_frame = first_frame - MAX_VISIBLE_HISTORY; - F32 frame_delta = ((F32) (graph_rect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1); + F32 frame_delta = ((F32) (mGraphRect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1); - F32 right = (F32) graph_rect.mLeft + frame_delta*first_frame; - F32 left = (F32) graph_rect.mLeft + frame_delta*last_frame; + F32 right = (F32) mGraphRect.mLeft + frame_delta*first_frame; + F32 left = (F32) mGraphRect.mLeft + frame_delta*last_frame; gGL.color4f(0.5f,0.5f,0.5f,0.3f); - gl_rect_2d((S32) left, graph_rect.mTop, (S32) right, graph_rect.mBottom); + gl_rect_2d((S32) left, mGraphRect.mTop, (S32) right, mGraphRect.mBottom); if (mHoverBarIndex >= 0) { S32 bar_frame = first_frame - mHoverBarIndex; - F32 bar = (F32) graph_rect.mLeft + frame_delta*bar_frame; + F32 bar = (F32) mGraphRect.mLeft + frame_delta*bar_frame; gGL.color4f(0.5f,0.5f,0.5f,1); gGL.begin(LLRender::LINES); - gGL.vertex2i((S32)bar, graph_rect.mBottom); - gGL.vertex2i((S32)bar, graph_rect.mTop); + gGL.vertex2i((S32)bar, mGraphRect.mBottom); + gGL.vertex2i((S32)bar, mGraphRect.mTop); gGL.end(); } } @@ -883,7 +896,7 @@ void LLFastTimerView::draw() if (mHoverID != NULL && idp != mHoverID) - { //fade out non-hihglighted timers + { //fade out non-highlighted timers if (idp->getParent() != mHoverID) { alpha = alpha_interp; @@ -891,8 +904,10 @@ void LLFastTimerView::draw() } gGL.color4f(col[0], col[1], col[2], alpha); - gGL.begin(LLRender::LINE_STRIP); - for (U32 j = 0; j < LLFastTimer::NamedTimer::HISTORY_NUM; j++) + gGL.begin(LLRender::TRIANGLE_STRIP); + for (U32 j = llmax(0, LLFastTimer::NamedTimer::HISTORY_NUM - LLFastTimer::getLastFrameIndex()); + j < LLFastTimer::NamedTimer::HISTORY_NUM; + j++) { U64 ticks = idp->getHistoricalCount(j); @@ -912,9 +927,10 @@ void LLFastTimerView::draw() //normalize to highlighted timer cur_max = llmax(cur_max, ticks); } - F32 x = graph_rect.mLeft + ((F32) (graph_rect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1)*j; - F32 y = graph_rect.mBottom + (F32) graph_rect.getHeight()/max_ticks*ticks; + F32 x = mGraphRect.mLeft + ((F32) (mGraphRect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1)*j; + F32 y = mGraphRect.mBottom + (F32) mGraphRect.getHeight()/max_ticks*ticks; gGL.vertex2f(x,y); + gGL.vertex2f(x,mGraphRect.mBottom); } gGL.end(); @@ -932,18 +948,20 @@ void LLFastTimerView::draw() } //interpolate towards new maximum - F32 dt = gFrameIntervalSeconds*3.f; - last_max = (U64) ((F32) last_max + ((F32) cur_max- (F32) last_max) * dt); + last_max = (U64) lerp((F32)last_max, (F32) cur_max, LLCriticalDamp::getInterpolant(0.1f)); + if (last_max - cur_max <= 1 || cur_max - last_max <= 1) + { + last_max = cur_max; + } F32 alpha_target = last_max > cur_max ? llmin((F32) last_max/ (F32) cur_max - 1.f,1.f) : llmin((F32) cur_max/ (F32) last_max - 1.f,1.f); - - alpha_interp = alpha_interp + (alpha_target-alpha_interp) * dt; + alpha_interp = lerp(alpha_interp, alpha_target, LLCriticalDamp::getInterpolant(0.1f)); if (mHoverID != NULL) { - x = (graph_rect.mRight + graph_rect.mLeft)/2; - y = graph_rect.mBottom + 8; + x = (mGraphRect.mRight + mGraphRect.mLeft)/2; + y = mGraphRect.mBottom + 8; LLFontGL::getFontMonospace()->renderUTF8( mHoverID->getName(), diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index ea8251191b..a349e7ad4c 100644 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -33,8 +33,9 @@ class LLFastTimerView : public LLFloater { public: - LLFastTimerView(const LLRect& rect); - + LLFastTimerView(const LLSD&); + BOOL postBuild(); + static BOOL sAnalyzePerformance; static void outputAllMetrics(); @@ -44,6 +45,7 @@ private: static void doAnalysisDefault(std::string baseline, std::string target, std::string output) ; static LLSD analyzePerformanceLogDefault(std::istream& is) ; static void exportCharts(const std::string& base, const std::string& target); + void onPause(); public: @@ -89,6 +91,7 @@ private: LLFrameTimer mHighlightTimer; S32 mPrintStats; S32 mAverageCyclesPerTimer; + LLRect mGraphRect; }; #endif diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 23cc23376f..2a946b1edf 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -27,26 +27,16 @@ #include "llviewerprecompiledheaders.h" -#include "llappviewer.h" -#include "llbase64.h" #include "llcommandhandler.h" #include "llfloaterreg.h" #include "llfloatersearch.h" #include "llmediactrl.h" #include "llnotificationsutil.h" -#include "llparcel.h" -#include "llplugincookiestore.h" #include "lllogininstance.h" #include "lluri.h" #include "llagent.h" -#include "llsdserialize.h" #include "llui.h" #include "llviewercontrol.h" -#include "llviewerregion.h" -#include "llversioninfo.h" -#include "llviewermedia.h" -#include "llviewernetwork.h" -#include "llviewerparcelmgr.h" #include "llweb.h" // support secondlife:///app/search/{CATEGORY}/{QUERY} SLapps @@ -178,14 +168,12 @@ void LLFloaterSearch::search(const SearchQuery &p) // add the permissions token that login.cgi gave us // We use "search_token", and fallback to "auth_token" if not present. - LLSD search_cookie; - LLSD search_token = LLLoginInstance::getInstance()->getResponse("search_token"); if (search_token.asString().empty()) { search_token = LLLoginInstance::getInstance()->getResponse("auth_token"); } - search_cookie["AUTH_TOKEN"] = search_token.asString(); + subs["AUTH_TOKEN"] = search_token.asString(); // add the user's preferred maturity (can be changed via prefs) std::string maturity; @@ -201,57 +189,10 @@ void LLFloaterSearch::search(const SearchQuery &p) { maturity = "13"; // PG } - search_cookie["MATURITY"] = maturity; + subs["MATURITY"] = maturity; // add the user's god status - search_cookie["GODLIKE"] = gAgent.isGodlike() ? "1" : "0"; - search_cookie["VERSION"] = LLVersionInfo::getVersion(); - search_cookie["VERSION_MAJOR"] = LLVersionInfo::getMajor(); - search_cookie["VERSION_MINOR"] = LLVersionInfo::getMinor(); - search_cookie["VERSION_PATCH"] = LLVersionInfo::getPatch(); - search_cookie["VERSION_BUILD"] = LLVersionInfo::getBuild(); - search_cookie["CHANNEL"] = LLVersionInfo::getChannel(); - search_cookie["GRID"] = LLGridManager::getInstance()->getGridLabel(); - search_cookie["OS"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple(); - search_cookie["SESSION_ID"] = gAgent.getSessionID(); - search_cookie["FIRST_LOGIN"] = gAgent.isFirstLogin(); - - std::string lang = LLUI::getLanguage(); - if (lang == "en-us") - { - lang = "en"; - } - search_cookie["LANGUAGE"] = lang; - - // find the region ID - LLUUID region_id; - LLViewerRegion *region = gAgent.getRegion(); - if (region) - { - region_id = region->getRegionID(); - } - search_cookie["REGION_ID"] = region_id; - - // find the parcel local ID - S32 parcel_id = 0; - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (parcel) - { - parcel_id = parcel->getLocalID(); - } - search_cookie["PARCEL_ID"] = llformat("%d", parcel_id); - - std::stringstream cookie_string_stream; - LLSDSerialize::toXML(search_cookie, cookie_string_stream); - std::string cookie_string = cookie_string_stream.str(); - - U8* cookie_string_buffer = (U8*)cookie_string.c_str(); - std::string cookie_value = LLBase64::encode(cookie_string_buffer, cookie_string.size()); - - // for staging services - LLViewerMedia::getCookieStore()->setCookiesFromHost(std::string("viewer_session_info=") + cookie_value, ".lindenlab.com"); - // for live services - LLViewerMedia::getCookieStore()->setCookiesFromHost(std::string("viewer_session_info=") + cookie_value, ".secondlife.com"); + subs["GODLIKE"] = gAgent.isGodlike() ? "1" : "0"; // get the search URL and expand all of the substitutions // (also adds things like [LANGUAGE], [VERSION], [OS], etc.) diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 8b72d83830..9ba5f827e2 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -1723,7 +1723,7 @@ BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) } BOOL handled = FALSE; - if (gFocusMgr.childHasKeyboardFocus(getRoot())) + if (mParentPanel->hasFocus()) { // SL-51858: Key presses are not being passed to the Popup menu. // A proper fix is non-trivial so instead just close the menu. diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 2888f779f4..622dcfe8dd 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -282,9 +282,9 @@ void LLFolderViewItem::refreshFromListener() setToolTip(mLabel); setIcon(mListener->getIcon()); time_t creation_date = mListener->getCreationDate(); - if (mCreationDate != creation_date) + if ((creation_date > 0) && (mCreationDate != creation_date)) { - setCreationDate(mListener->getCreationDate()); + setCreationDate(creation_date); dirtyFilter(); } if (mRoot->useLabelSuffix()) diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index d6278a5fda..516b47e616 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -256,16 +256,20 @@ std::string::size_type LLInventoryFilter::getStringMatchOffset() const // has user modified default filter params? BOOL LLInventoryFilter::isNotDefault() const { - return mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes - || mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes - || mFilterOps.mFilterWearableTypes != mDefaultFilterOps.mFilterWearableTypes - || mFilterOps.mFilterTypes != FILTERTYPE_OBJECT - || mFilterOps.mFilterLinks != FILTERLINK_INCLUDE_LINKS - || mFilterSubString.size() - || mFilterOps.mPermissions != mDefaultFilterOps.mPermissions - || mFilterOps.mMinDate != mDefaultFilterOps.mMinDate - || mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate - || mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo; + BOOL not_default = FALSE; + + not_default |= (mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes); + not_default |= (mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes); + not_default |= (mFilterOps.mFilterWearableTypes != mDefaultFilterOps.mFilterWearableTypes); + not_default |= (mFilterOps.mFilterTypes != mDefaultFilterOps.mFilterTypes); + not_default |= (mFilterOps.mFilterLinks != mDefaultFilterOps.mFilterLinks); + not_default |= (mFilterSubString.size()); + not_default |= (mFilterOps.mPermissions != mDefaultFilterOps.mPermissions); + not_default |= (mFilterOps.mMinDate != mDefaultFilterOps.mMinDate); + not_default |= (mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate); + not_default |= (mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo); + + return not_default; } BOOL LLInventoryFilter::isActive() const diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 173e5c6ae6..615d3aefde 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -129,6 +129,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mScroller(NULL), mSortOrderSetting(p.sort_order_setting), mInventory(p.inventory), + mAcceptsDragAndDrop(p.accepts_drag_and_drop), mAllowMultiSelect(p.allow_multi_select), mShowItemLinkOverlays(p.show_item_link_overlays), mShowLoadStatus(p.show_load_status), @@ -824,19 +825,24 @@ BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* accept, std::string& tooltip_msg) { - BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + BOOL handled = FALSE; - // If folder view is empty the (x, y) point won't be in its rect - // so the handler must be called explicitly. - // but only if was not handled before. See EXT-6746. - if (!handled && !mFolderRoot->hasVisibleChildren()) + if (mAcceptsDragAndDrop) { - handled = mFolderRoot->handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - } + handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - if (handled) - { - mFolderRoot->setDragAndDropThisFrame(); + // If folder view is empty the (x, y) point won't be in its rect + // so the handler must be called explicitly. + // but only if was not handled before. See EXT-6746. + if (!handled && !mFolderRoot->hasVisibleChildren()) + { + handled = mFolderRoot->handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + + if (handled) + { + mFolderRoot->setDragAndDropThisFrame(); + } } return handled; diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index cfb84bf4b7..8635ebc5c8 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -86,6 +86,7 @@ public: Optional<bool> use_label_suffix; Optional<bool> show_load_status; Optional<LLScrollContainer::Params> scroll; + Optional<bool> accepts_drag_and_drop; Params() : sort_order_setting("sort_order_setting"), @@ -96,7 +97,8 @@ public: start_folder("start_folder"), use_label_suffix("use_label_suffix", true), show_load_status("show_load_status"), - scroll("scroll") + scroll("scroll"), + accepts_drag_and_drop("accepts_drag_and_drop") {} }; @@ -181,6 +183,7 @@ protected: LLInventoryModel* mInventory; LLInventoryObserver* mInventoryObserver; LLInvPanelComplObserver* mCompletionObserver; + BOOL mAcceptsDragAndDrop; BOOL mAllowMultiSelect; BOOL mShowItemLinkOverlays; // Shows link graphic over inventory item icons BOOL mShowLoadStatus; diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 1576ccccdf..bc594b5517 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -579,6 +579,11 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) } + // After role member data was changed in Roles->Members + // need to update role titles. See STORM-918. + if (gc == GC_ROLE_MEMBER_DATA) + LLGroupMgr::getInstance()->sendGroupTitlesRequest(mGroupID); + // If this was just a titles update, we are done. if (gc == GC_TITLES) return; diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index 2cb91f771f..0579ecbb90 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -97,6 +97,7 @@ LLInventoryPanel * LLPanelMarketplaceInbox::setupInventoryPanel() // Set the sort order newest to oldest mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE); + mInventoryPanel->getFilter()->markDefault(); // Set selection callback for proper update of inventory status buttons mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceInbox::onSelectionChange, this)); @@ -116,7 +117,7 @@ void LLPanelMarketplaceInbox::onFocusReceived() sidepanel_inventory->clearSelections(true, false, true); - gSavedPerAccountSettings.setString("LastInventoryInboxActivity", LLDate::now().asString()); + gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); } BOOL LLPanelMarketplaceInbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg) diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index d51aa73c93..faba6dc0cf 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -192,20 +192,19 @@ void LLInboxFolderViewFolder::draw() void LLInboxFolderViewFolder::computeFreshness() { - const std::string& last_expansion = gSavedPerAccountSettings.getString("LastInventoryInboxActivity"); + const U32 last_expansion_utc = gSavedPerAccountSettings.getU32("LastInventoryInboxActivity"); - if (!last_expansion.empty()) + if (last_expansion_utc > 0) { - // Inventory DB timezone is hardcoded to PDT or GMT-7, which is 7 hours behind GMT - const F64 SEVEN_HOURS_IN_SECONDS = 7 * 60 * 60; - const F64 saved_freshness_inventory_db_timezone = LLDate(last_expansion).secondsSinceEpoch() - SEVEN_HOURS_IN_SECONDS; + const U32 time_offset_for_pdt = 7 * 60 * 60; + const U32 last_expansion = last_expansion_utc - time_offset_for_pdt; - mFresh = (mCreationDate > saved_freshness_inventory_db_timezone); + mFresh = (mCreationDate > last_expansion); #if DEBUGGING_FRESHNESS if (mFresh) { - llinfos << "Item is fresh! -- creation " << mCreationDate << ", saved_freshness_date " << saved_freshness_inventory_db_timezone << llendl; + llinfos << "Item is fresh! -- creation " << mCreationDate << ", saved_freshness_date " << last_expansion << llendl; } #endif } @@ -219,7 +218,7 @@ void LLInboxFolderViewFolder::deFreshify() { mFresh = false; - gSavedPerAccountSettings.setString("LastInventoryInboxActivity", LLDate::now().asString()); + gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); } void LLInboxFolderViewFolder::selectItem() diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp index 839369bffe..73fb92ff72 100644 --- a/indra/newview/llpanelmarketplaceoutbox.cpp +++ b/indra/newview/llpanelmarketplaceoutbox.cpp @@ -117,8 +117,11 @@ LLInventoryPanel * LLPanelMarketplaceOutbox::setupInventoryPanel() LLRect inventory_placeholder_rect = outbox_inventory_placeholder->getRect(); mInventoryPanel->setShape(inventory_placeholder_rect); - // Set the sort order newest to oldest, and a selection change callback + // Set the sort order newest to oldest mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE); + mInventoryPanel->getFilter()->markDefault(); + + // Set selection callback for proper update of inventory status buttons mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceOutbox::onSelectionChange, this)); // Set up the note to display when the outbox is empty diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 9814e5b81a..bd62b5c101 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -539,7 +539,7 @@ void LLSidepanelInventory::onToggleInboxBtn() if (inbox_expanded && inboxPanel->isInVisibleChain()) { - gSavedPerAccountSettings.setString("LastInventoryInboxActivity", LLDate::now().asString()); + gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); } } @@ -568,7 +568,7 @@ void LLSidepanelInventory::onOpen(const LLSD& key) #else if (mInboxEnabled && getChild<LLButton>(INBOX_BUTTON_NAME)->getToggleState()) { - gSavedPerAccountSettings.setString("LastInventoryInboxActivity", LLDate::now().asString()); + gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); } #endif diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index f53b08a4bc..55d6378ad8 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -62,6 +62,8 @@ using namespace std; using namespace LLNotificationsUI; +class LLSideTrayButton; + static LLRootViewRegistry::Register<LLSideTray> t1("side_tray"); static LLDefaultChildRegistry::Register<LLSideTrayTab> t2("sidetray_tab"); @@ -168,8 +170,131 @@ private: bool mHasBadge; LLBadge::Params mBadgeParams; + LLSideTrayButton* mSideTrayButton; +}; + +////////////////////////////////////////////////////////////////////////////// +// LLSideTrayButton +// Side Tray tab button with "tear off" handling. +////////////////////////////////////////////////////////////////////////////// + +class LLSideTrayButton : public LLButton +{ +public: + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) + { + // Route future Mouse messages here preemptively. (Release on mouse up.) + // No handler needed for focus lost since this class has no state that depends on it. + gFocusMgr.setMouseCapture(this); + + localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY); + + // Note: don't pass on to children + return TRUE; + } + + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) + { + // We only handle the click if the click both started and ended within us + if( !hasMouseCapture() ) return FALSE; + + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y); + + S32 delta_x = screen_x - mDragLastScreenX; + S32 delta_y = screen_y - mDragLastScreenY; + + LLSideTray* side_tray = LLSideTray::getInstance(); + + // Check if the tab we are dragging is docked. + if (!side_tray->isTabAttached(mTabName)) return FALSE; + + // Same value is hardcoded in LLDragHandle::handleHover(). + const S32 undock_threshold = 12; + + // Detach a tab if it has been pulled further than undock_threshold. + if (delta_x <= -undock_threshold || delta_x >= undock_threshold || + delta_y <= -undock_threshold || delta_y >= undock_threshold) + { + LLSideTrayTab* tab = side_tray->getTab(mTabName); + if (!tab) return FALSE; + + tab->setDocked(false); + + LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", tab->getName()); + if (!floater_tab) return FALSE; + + LLRect original_rect = floater_tab->getRect(); + S32 header_snap_y = floater_tab->getHeaderHeight() / 2; + S32 snap_x = screen_x - original_rect.mLeft - original_rect.getWidth() / 2; + S32 snap_y = screen_y - original_rect.mTop + header_snap_y; + + // Move the floater to appear "under" the mouse pointer. + floater_tab->setRect(original_rect.translate(snap_x, snap_y)); + + // Snap the mouse pointer to the center of the floater header + // and call 'mouse down' event handler to begin dragging. + floater_tab->handleMouseDown(original_rect.getWidth() / 2, + original_rect.getHeight() - header_snap_y, + mask); + + return TRUE; + } + + return FALSE; + } + + void setBadgeDriver(LLSideTrayTabBadgeDriver* driver) + { + mBadgeDriver = driver; + } + + void setVisible(BOOL visible) + { + setBadgeVisibility(visible); + + LLButton::setVisible(visible); + } + +protected: + LLSideTrayButton(const LLButton::Params& p) + : LLButton(p) + , mDragLastScreenX(0) + , mDragLastScreenY(0) + , mBadgeDriver(NULL) + { + // Find out the tab name to use in handleHover(). + size_t pos = getName().find("_button"); + llassert(pos != std::string::npos); + mTabName = getName().substr(0, pos); + } + + friend class LLUICtrlFactory; + + void draw() + { + if (mBadgeDriver) + { + setBadgeLabel(mBadgeDriver->getBadgeString()); + } + + LLButton::draw(); + } + +private: + S32 mDragLastScreenX; + S32 mDragLastScreenY; + + std::string mTabName; + LLSideTrayTabBadgeDriver* mBadgeDriver; }; + +//////////////////////////////////////////////////// +// LLSideTrayTab implementation +//////////////////////////////////////////////////// + LLSideTrayTab::LLSideTrayTab(const Params& p) : LLPanel(), mTabTitle(p.tab_title), @@ -177,7 +302,8 @@ LLSideTrayTab::LLSideTrayTab(const Params& p) mImageSelected(p.image_selected), mDescription(p.description), mMainPanel(NULL), - mBadgeParams(p.badge) + mBadgeParams(p.badge), + mSideTrayButton(NULL) { mHasBadge = p.badge.isProvided(); } @@ -271,6 +397,11 @@ void LLSideTrayTab::toggleTabDocked(bool toggle_floater /* = true */) bool docking = !isDocked(); + if (mSideTrayButton) + { + mSideTrayButton->setVisible(docking); + } + // Hide the "Tear Off" button when a tab gets undocked // and show "Dock" button instead. getChild<LLButton>("undock")->setVisible(docking); @@ -462,116 +593,6 @@ template <> LLPanel* tab_cast<LLPanel*>(LLSideTrayTab* tab) { return tab; } ////////////////////////////////////////////////////////////////////////////// -// LLSideTrayButton -// Side Tray tab button with "tear off" handling. -////////////////////////////////////////////////////////////////////////////// - -class LLSideTrayButton : public LLButton -{ -public: - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) - { - // Route future Mouse messages here preemptively. (Release on mouse up.) - // No handler needed for focus lost since this class has no state that depends on it. - gFocusMgr.setMouseCapture(this); - - localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY); - - // Note: don't pass on to children - return TRUE; - } - - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) - { - // We only handle the click if the click both started and ended within us - if( !hasMouseCapture() ) return FALSE; - - S32 screen_x; - S32 screen_y; - localPointToScreen(x, y, &screen_x, &screen_y); - - S32 delta_x = screen_x - mDragLastScreenX; - S32 delta_y = screen_y - mDragLastScreenY; - - LLSideTray* side_tray = LLSideTray::getInstance(); - - // Check if the tab we are dragging is docked. - if (!side_tray->isTabAttached(mTabName)) return FALSE; - - // Same value is hardcoded in LLDragHandle::handleHover(). - const S32 undock_threshold = 12; - - // Detach a tab if it has been pulled further than undock_threshold. - if (delta_x <= -undock_threshold || delta_x >= undock_threshold || - delta_y <= -undock_threshold || delta_y >= undock_threshold) - { - LLSideTrayTab* tab = side_tray->getTab(mTabName); - if (!tab) return FALSE; - - tab->setDocked(false); - - LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", tab->getName()); - if (!floater_tab) return FALSE; - - LLRect original_rect = floater_tab->getRect(); - S32 header_snap_y = floater_tab->getHeaderHeight() / 2; - S32 snap_x = screen_x - original_rect.mLeft - original_rect.getWidth() / 2; - S32 snap_y = screen_y - original_rect.mTop + header_snap_y; - - // Move the floater to appear "under" the mouse pointer. - floater_tab->setRect(original_rect.translate(snap_x, snap_y)); - - // Snap the mouse pointer to the center of the floater header - // and call 'mouse down' event handler to begin dragging. - floater_tab->handleMouseDown(original_rect.getWidth() / 2, - original_rect.getHeight() - header_snap_y, - mask); - - return TRUE; - } - - return FALSE; - } - - void setBadgeDriver(LLSideTrayTabBadgeDriver* driver) - { - mBadgeDriver = driver; - } - -protected: - LLSideTrayButton(const LLButton::Params& p) - : LLButton(p) - , mDragLastScreenX(0) - , mDragLastScreenY(0) - , mBadgeDriver(NULL) - { - // Find out the tab name to use in handleHover(). - size_t pos = getName().find("_button"); - llassert(pos != std::string::npos); - mTabName = getName().substr(0, pos); - } - - friend class LLUICtrlFactory; - - void draw() - { - if (mBadgeDriver) - { - setBadgeLabel(mBadgeDriver->getBadgeString()); - } - - LLButton::draw(); - } - -private: - S32 mDragLastScreenX; - S32 mDragLastScreenY; - - std::string mTabName; - LLSideTrayTabBadgeDriver* mBadgeDriver; -}; - -////////////////////////////////////////////////////////////////////////////// // LLSideTray ////////////////////////////////////////////////////////////////////////////// @@ -786,7 +807,7 @@ bool LLSideTray::selectTabByName(const std::string& name, bool keep_prev_visible { // Keep previously active tab visible if requested. if (keep_prev_visible) tab_to_keep_visible = mActiveTab; - toggleTabButton(mActiveTab); + toggleTabButton(mActiveTab); } //select new tab @@ -794,9 +815,9 @@ bool LLSideTray::selectTabByName(const std::string& name, bool keep_prev_visible if (mActiveTab) { - toggleTabButton(mActiveTab); - LLSD key;//empty - mActiveTab->onOpen(key); + toggleTabButton(mActiveTab); + LLSD key;//empty + mActiveTab->onOpen(key); } //arrange(); @@ -976,7 +997,9 @@ LLButton* LLSideTrayTab::createButton(bool allowTearOff, LLUICtrl::commit_callba LLButton* button; if (allowTearOff) { - button = LLUICtrlFactory::create<LLSideTrayButton>(bparams); + mSideTrayButton = LLUICtrlFactory::create<LLSideTrayButton>(bparams); + + button = mSideTrayButton; } else { diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index fecc6d91bd..4af5fdd9f3 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -33,6 +33,7 @@ #include "llcompilequeue.h" #include "llcallfloater.h" +#include "llfasttimerview.h" #include "llfloaterabout.h" #include "llfloateranimpreview.h" #include "llfloaterauction.h" @@ -159,6 +160,7 @@ void LLViewerFloaterReg::registerFloaters() // *NOTE: Please keep these alphabetized for easier merges LLFloaterAboutUtil::registerFloater(); + LLFloaterReg::add("fast_timers", "floater_fast_timers.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFastTimerView>); LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLand>); LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAuction>); LLFloaterReg::add("avatar_picker", "floater_avatar_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarPicker>); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 26599f557e..754731b290 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -523,7 +523,7 @@ class LLAdvancedToggleConsole : public view_listener_t } else if ("fast timers" == console_type) { - toggle_visibility( (void*)gDebugView->mFastTimerView ); + LLFloaterReg::toggleInstance("fast_timers"); } else if ("scene view" == console_type) { @@ -563,7 +563,7 @@ class LLAdvancedCheckConsole : public view_listener_t } else if ("fast timers" == console_type) { - new_value = get_visibility( (void*)gDebugView->mFastTimerView ); + new_value = LLFloaterReg::instanceVisible("fast_timers"); } else if ("scene view" == console_type) { diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 68745d5aeb..6435904fee 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1299,29 +1299,12 @@ bool highlight_offered_object(const LLUUID& obj_id) void inventory_offer_mute_callback(const LLUUID& blocked_id, const std::string& full_name, - bool is_group, - boost::shared_ptr<LLNotificationResponderInterface> offer_ptr) + bool is_group) { - LLOfferInfo* offer = dynamic_cast<LLOfferInfo*>(offer_ptr.get()); - - std::string from_name = full_name; - LLMute::EType type; - if (is_group) - { - type = LLMute::GROUP; - } - else if(offer && offer->mFromObject) - { - //we have to block object by name because blocked_id is an id of owner - type = LLMute::BY_NAME; - } - else - { - type = LLMute::AGENT; - } + // *NOTE: blocks owner if the offer came from an object + LLMute::EType mute_type = is_group ? LLMute::GROUP : LLMute::AGENT; - // id should be null for BY_NAME mute, see LLMuteList::add for details - LLMute mute(type == LLMute::BY_NAME ? LLUUID::null : blocked_id, from_name, type); + LLMute mute(blocked_id, full_name, mute_type); if (LLMuteList::getInstance()->add(mute)) { LLPanelBlockedList::showPanelAndSelect(blocked_id); @@ -1335,6 +1318,7 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, bool matches(const LLNotificationPtr notification) const { if(notification->getName() == "ObjectGiveItem" + || notification->getName() == "OwnObjectGiveItem" || notification->getName() == "UserGiveItem") { return (notification->getPayload()["from_id"].asUUID() == blocked_id); @@ -1495,7 +1479,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& llassert(notification_ptr != NULL); if (notification_ptr != NULL) { - gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,notification_ptr->getResponderPtr())); + gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3)); } } @@ -1640,7 +1624,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const llassert(notification_ptr != NULL); if (notification_ptr != NULL) { - gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,notification_ptr->getResponderPtr())); + gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3)); } } @@ -1818,6 +1802,7 @@ void LLOfferInfo::initRespondFunctionMap() if(mRespondFunctions.empty()) { mRespondFunctions["ObjectGiveItem"] = boost::bind(&LLOfferInfo::inventory_task_offer_callback, this, _1, _2); + mRespondFunctions["OwnObjectGiveItem"] = boost::bind(&LLOfferInfo::inventory_task_offer_callback, this, _1, _2); mRespondFunctions["UserGiveItem"] = boost::bind(&LLOfferInfo::inventory_offer_callback, this, _1, _2); } } @@ -1905,7 +1890,7 @@ void inventory_offer_handler(LLOfferInfo* info) std::string verb = "select?name=" + LLURI::escape(msg); args["ITEM_SLURL"] = LLSLURL("inventory", info->mObjectID, verb.c_str()).getSLURLString(); - LLNotification::Params p("ObjectGiveItem"); + LLNotification::Params p; // Object -> Agent Inventory Offer if (info->mFromObject) @@ -1915,7 +1900,10 @@ void inventory_offer_handler(LLOfferInfo* info) // Note: sets inventory_task_offer_callback as the callback p.substitutions(args).payload(payload).functor.responder(LLNotificationResponderPtr(info)); info->mPersist = true; - p.name = "ObjectGiveItem"; + + // Offers from your own objects need a special notification template. + p.name = info->mFromID == gAgentID ? "OwnObjectGiveItem" : "ObjectGiveItem"; + // Pop up inv offer chiclet and let the user accept (keep), or reject (and silently delete) the inventory. LLPostponedNotification::add<LLPostponedOfferNotification>(p, info->mFromID, info->mFromGroup == TRUE); } @@ -2594,8 +2582,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0]; info->mType = (LLAssetType::EType) bucketp->asset_type; info->mObjectID = bucketp->object_id; + info->mFromObject = FALSE; } - else + else // IM_TASK_INVENTORY_OFFERED { if (sizeof(S8) != binary_bucket_size) { @@ -2605,6 +2594,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } info->mType = (LLAssetType::EType) binary_bucket[0]; info->mObjectID = LLUUID::null; + info->mFromObject = TRUE; } info->mIM = dialog; @@ -2613,14 +2603,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) info->mTransactionID = session_id; info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType)); - if (dialog == IM_TASK_INVENTORY_OFFERED) - { - info->mFromObject = TRUE; - } - else - { - info->mFromObject = FALSE; - } info->mFromName = name; info->mDesc = message; info->mHost = msg->getSender(); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 8b942fbc6a..90a05cd9e5 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -4498,17 +4498,25 @@ bool LLVivoxVoiceClient::parcelVoiceInfoReceived(state requesting_state) bool LLVivoxVoiceClient::requestParcelVoiceInfo() { - LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL; - - // grab the cap for parcel voice info from the region. LLViewerRegion * region = gAgent.getRegion(); - if (region == NULL) + if (region == NULL || !region->capabilitiesReceived()) { + // we don't have the cap yet, so return false so the caller can try again later. + + LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest capability not yet available, deferring" << LL_ENDL; return false; } + // grab the cap. std::string url = gAgent.getRegion()->getCapability("ParcelVoiceInfoRequest"); - if (!url.empty()) + if (url.empty()) + { + // Region dosn't have the cap. Stop probing. + LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest capability not available in this region" << LL_ENDL; + setState(stateDisableCleanup); + return false; + } + else { // if we've already retrieved the cap from the region, go ahead and make the request, // and return true so we can go into the state that waits for the response. @@ -4517,18 +4525,11 @@ bool LLVivoxVoiceClient::requestParcelVoiceInfo() LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL; LLHTTPClient::post( - url, - data, - new LLVivoxVoiceClientCapResponder(getState())); + url, + data, + new LLVivoxVoiceClientCapResponder(getState())); return true; } - else - { - - // we don't have the cap yet, so return false so the caller can try again later. - LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest cap not yet available, deferring" << LL_ENDL; - return false; - } } void LLVivoxVoiceClient::switchChannel( diff --git a/indra/newview/skins/default/xui/en/floater_fast_timers.xml b/indra/newview/skins/default/xui/en/floater_fast_timers.xml new file mode 100644 index 0000000000..49aa8f3840 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_fast_timers.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_minimize="false" + can_tear_off="false" + can_resize="true" + can_drag_on_left="false" + can_close="true" + height="500" + layout="topleft" + name="fast_timers" + save_rect="true" + save_visibility="false" + single_instance="true" + min_width="400" + width="700"> + <string name="pause" >Pause</string> + <string name="run">Run</string> + <button follows="top|right" + name="pause_btn" + left="-200" + top="5" + width="180" + height="40" + pad_bottom="-5" + label="Pause" + font="SansSerifHuge"/> +</floater> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index a9ae4475b6..41a90f5984 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2297,8 +2297,8 @@ Would you be my friend? icon="alertmodal.tga" label="Save Outfit" name="SaveOutfitAs" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> Save what I'm wearing as a new Outfit: <tag>confirm</tag> <form name="form"> @@ -4611,8 +4611,8 @@ Go to your [http://secondlife.com/account/ Dashboard] to see your account histor <notification icon="alertmodal.tga" name="ConfirmQuit" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> Are you sure you want to quit? <tag>confirm</tag> <usetemplate @@ -4625,8 +4625,8 @@ Are you sure you want to quit? <notification icon="alertmodal.tga" name="DeleteItems" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> [QUESTION] <tag>confirm</tag> <usetemplate @@ -4639,8 +4639,9 @@ Are you sure you want to quit? <notification icon="alertmodal.tga" name="HelpReportAbuseEmailLL" - type="alert" - unique="true"> + type="alert"> + <unique/> + Use this tool to report violations of the [http://secondlife.com/corporate/tos.php Terms of Service] and [http://secondlife.com/corporate/cs.php Community Standards]. All reported abuses are investigated and resolved. @@ -5615,8 +5616,8 @@ Message from [NAME]: icon="notify.tga" name="NotSafe" persist="true" - type="notify" - unique="true"> + type="notify"> + <unique/> This land has damage enabled. You can be hurt here. If you die, you will be teleported to your home location. </notification> @@ -5625,8 +5626,8 @@ You can be hurt here. If you die, you will be teleported to your home location. icon="notify.tga" name="NoFly" persist="true" - type="notify" - unique="true"> + type="notify"> + <unique/> <tag>fail</tag> This area has flying disabled. You can't fly here. @@ -5636,8 +5637,8 @@ You can't fly here. icon="notify.tga" name="PushRestricted" persist="true" - type="notify" - unique="true"> + type="notify"> + <unique/> This area does not allow pushing. You can't push others here unless you own the land. </notification> @@ -5645,8 +5646,8 @@ This area does not allow pushing. You can't push others here unless you own icon="notify.tga" name="NoVoice" persist="true" - type="notify" - unique="true"> + type="notify"> + <unique/> This area has voice chat disabled. You won't be able to hear anyone talking. <tag>voice</tag> </notification> @@ -5655,8 +5656,8 @@ This area has voice chat disabled. You won't be able to hear anyone talking icon="notify.tga" name="NoBuild" persist="true" - type="notify" - unique="true"> + type="notify"> + <unique/> This area has building disabled. You can't build or rez objects here. </notification> @@ -5664,8 +5665,8 @@ This area has building disabled. You can't build or rez objects here. icon="notify.tga" name="SeeAvatars" persist="true" - type="notify" - unique="true"> + type="notify"> + <unique/> This parcel hides avatars and text chat from another parcel. You can't see other residents outside the parcel, and those outside are not able to see you. Regular text chat on channel 0 is also blocked. </notification> @@ -5950,7 +5951,25 @@ An object named <nolink>[OBJECTFROMNAME]</nolink> owned by [NAME_SLU <button index="2" name="Mute" - text="Block"/> + text="Block Owner"/> + </form> + </notification> + + <notification + icon="notify.tga" + name="OwnObjectGiveItem" + type="offer"> +Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you this [OBJECTTYPE]: +<nolink>[ITEM_SLURL]</nolink> + <form name="form"> + <button + index="0" + name="Keep" + text="Keep"/> + <button + index="1" + name="Discard" + text="Discard"/> </form> </notification> @@ -5962,7 +5981,7 @@ An object named <nolink>[OBJECTFROMNAME]</nolink> owned by [NAME_SLU [ITEM_SLURL] <form name="form"> <button - index="4" + index="3" name="Show" text="Show"/> <button @@ -6535,8 +6554,8 @@ The voice call you are trying to join, [VOICE_CHANNEL_NAME], has reached maximum <notification icon="notifytip.tga" name="ProximalVoiceChannelFull" - type="notifytip" - unique="true"> + type="notifytip"> + <unique/> We're sorry. This area has reached maximum capacity for voice conversations. Please try to use voice in another area. <tag>fail</tag> <tag>voice</tag> @@ -6604,8 +6623,8 @@ Failed to connect to [VOICE_CHANNEL_NAME], please try again later. You will now duration="10" icon="notifytip.tga" name="VoiceLoginRetry" - type="notifytip" - unique="true"> + type="notifytip"> + <unique/> We are creating a voice channel for you. This may take up to one minute. <tag>status</tag> <tag>voice</tag> @@ -6616,8 +6635,8 @@ We are creating a voice channel for you. This may take up to one minute. name="VoiceEffectsExpired" sound="UISndAlert" persist="true" - type="notify" - unique="true"> + type="notify"> + <unique/> One or more of your subscribed Voice Morphs has expired. [[URL] Click here] to renew your subscription. <tag>fail</tag> @@ -6629,8 +6648,8 @@ One or more of your subscribed Voice Morphs has expired. name="VoiceEffectsExpiredInUse" sound="UISndAlert" persist="true" - type="notify" - unique="true"> + type="notify"> + <unique/> The active Voice Morph has expired, your normal voice settings have been applied. [[URL] Click here] to renew your subscription. <tag>fail</tag> @@ -6642,8 +6661,8 @@ The active Voice Morph has expired, your normal voice settings have been applied name="VoiceEffectsWillExpire" sound="UISndAlert" persist="true" - type="notify" - unique="true"> + type="notify"> + <unique/> One or more of your Voice Morphs will expire in less than [INTERVAL] days. [[URL] Click here] to renew your subscription. <tag>fail</tag> @@ -6655,8 +6674,8 @@ One or more of your Voice Morphs will expire in less than [INTERVAL] days. name="VoiceEffectsNew" sound="UISndAlert" persist="true" - type="notify" - unique="true"> + type="notify"> + <unique/> New Voice Morphs are available! <tag>voice</tag> </notification> @@ -7057,8 +7076,9 @@ Are you sure you want to leave this call? ignoretext="Confirm before I leave call" name="okcancelignore" notext="No" - yestext="Yes" - unique="true"/> + yestext="Yes"> + <unique/> + </usetemplate> </notification> <notification @@ -7077,31 +7097,31 @@ Mute everyone? ignoretext="Confirm before I mute all participants in a group call" name="okcancelignore" yestext="Ok" - notext="Cancel" - unique="true"/> + notext="Cancel"> + <unique/> + </usetemplate> </notification> <notification name="HintChat" label="Chat" - type="hint" - unique="true"> + type="hint"> + <unique/> To join the conversation, type into the chat field below. </notification> <notification name="HintSit" - label="Stand" - type="hint" - unique="true"> + type="hint"> + <unique/> To stand up and exit the sitting position, click the Stand button. </notification> <notification name="HintSpeak" label="Speak" - type="hint" - unique="true"> + type="hint"> + <unique/> Click the Speak button to turn your microphone on and off. Click on the up arrow to see the voice control panel. @@ -7112,32 +7132,32 @@ Hiding the Speak button will disable the voice feature. <notification name="HintDestinationGuide" label="Explore the World" - type="hint" - unique="true"> + type="hint"> + <unique/> The Destination Guide contains thousands of new places to discover. Select a location and choose Teleport to start exploring. </notification> <notification name="HintSidePanel" label="Side Panel" - type="hint" - unique="true"> + type="hint"> + <unique/> Get quick access to your inventory, outfits, profiles and more in the side panel. </notification> <notification name="HintMove" label="Move" - type="hint" - unique="true"> + type="hint"> + <unique/> To walk or run, open the Move Panel and use the directional arrows to navigate. You can also use the directional keys on your keyboard. </notification> <notification name="HintMoveClick" label="" - type="hint" - unique="true"> + type="hint"> + <unique/> 1. Click to Walk Click anywhere on the ground to walk to that spot. @@ -7149,8 +7169,8 @@ Click and drag anywhere on the world to rotate your view <notification name="HintDisplayName" label="Display Name" - type="hint" - unique="true"> + type="hint"> + <unique/> Set your customizable display name here. This is in addition to your unique username, which can't be changed. You can change how you see other people's names in your preferences. </notification> @@ -7158,8 +7178,8 @@ Click and drag anywhere on the world to rotate your view <notification name="HintView" label="View" - type="hint" - unique="true"> + type="hint"> + <unique/> To change your camera view, use the Orbit and Pan controls. Reset your view by pressing Escape or walking. <tag>custom_skin</tag> </notification> @@ -7167,16 +7187,16 @@ Click and drag anywhere on the world to rotate your view <notification name="HintInventory" label="Inventory" - type="hint" - unique="true"> + type="hint"> + <unique/> Check your inventory to find items. Newest items can be easily found in the Recent tab. </notification> <notification name="HintLindenDollar" label="You've got Linden Dollars!" - type="hint" - unique="true"> + type="hint"> + <unique/> Here's your current balance of L$. Click Buy L$ to purchase more Linden Dollars. <tag>funds</tag> </notification> @@ -7365,8 +7385,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' <notification name="ModeChange" label="" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> Changing modes requires you to quit and restart. <tag>confirm</tag> <usetemplate @@ -7378,8 +7398,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' <notification name="NoClassifieds" label="" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> <tag>fail</tag> <tag>confirm</tag> Creation and editing of Classifieds is only available in Advanced mode. Would you like to quit and change modes? The mode selector can be found on the login screen. @@ -7392,8 +7412,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' <notification name="NoGroupInfo" label="" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> <tag>fail</tag> <tag>confirm</tag> Creation and editing of Groups is only available in Advanced mode. Would you like to quit and change modes? The mode selector can be found on the login screen. @@ -7406,8 +7426,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' <notification name="NoPlaceInfo" label="" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> <tag>fail</tag> <tag>confirm</tag> Viewing place profile is only available in Advanced mode. Would you like to quit and change modes? The mode selector can be found on the login screen. @@ -7420,8 +7440,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' <notification name="NoPicks" label="" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> <tag>fail</tag> <tag>confirm</tag> Creation and editing of Picks is only available in Advanced mode. Would you like to quit and change modes? The mode selector can be found on the login screen. @@ -7434,8 +7454,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' <notification name="NoWorldMap" label="" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> <tag>fail</tag> <tag>confirm</tag> Viewing of the world map is only available in Advanced mode. Would you like to quit and change modes? The mode selector can be found on the login screen. @@ -7448,8 +7468,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' <notification name="NoVoiceCall" label="" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> <tag>fail</tag> <tag>confirm</tag> Voice calls are only available in Advanced mode. Would you like to logout and change modes? @@ -7462,8 +7482,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' <notification name="NoAvatarShare" label="" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> <tag>fail</tag> <tag>confirm</tag> Sharing is only available in Advanced mode. Would you like to logout and change modes? @@ -7476,8 +7496,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' <notification name="NoAvatarPay" label="" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> <tag>fail</tag> <tag>confirm</tag> Paying other residents is only available in Advanced mode. Would you like to logout and change modes? @@ -7490,8 +7510,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' <notification name="NoInventory" label="" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> <tag>fail</tag> <tag>confirm</tag> Viewing inventory is only available in Advanced mode. Would you like to logout and change modes? @@ -7504,8 +7524,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' <notification name="NoAppearance" label="" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> <tag>fail</tag> <tag>confirm</tag> The appearance editor is only available in Advanced mode. Would you like to logout and change modes? @@ -7518,8 +7538,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm ' <notification name="NoSearch" label="" - type="alertmodal" - unique="true"> + type="alertmodal"> + <unique/> <tag>fail</tag> <tag>confirm</tag> Search is only available in Advanced mode. Would you like to logout and change modes? diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index c8f8d07701..ec5853649e 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -47,13 +47,13 @@ mouse_opaque="false" name="chat_bar_layout_panel" user_resize="true" - width="310" > + width="250" > <panel name="chat_bar" filename="panel_nearby_chat_bar.xml" left="0" height="28" - width="308" + width="248" top="0" mouse_opaque="false" follows="left|right" @@ -341,7 +341,7 @@ Disabled for now. height="28" layout="topleft" min_height="28" - min_width="52" + min_width="62" mouse_opaque="false" name="mini_map_btn_panel" user_resize="false" diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index 888230a00e..e6c5110999 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -82,10 +82,11 @@ left="0" name="All Items" sort_order_setting="InventorySortOrder" - show_item_link_overlays="true" + show_item_link_overlays="true" top="16" width="288" /> <recent_inventory_panel + accepts_drag_and_drop="false" bg_opaque_color="DkGray2" bg_alpha_color="DkGray2" background_visible="true" @@ -99,7 +100,7 @@ layout="topleft" left_delta="0" name="Recent Items" - show_item_link_overlays="true" + show_item_link_overlays="true" width="290" /> </tab_container> <layout_stack diff --git a/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml index 00f4c43915..eaf148c5e4 100644 --- a/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml +++ b/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml @@ -4,11 +4,12 @@ background_visible="true" background_opaque="true" show_load_status="true" + accepts_drag_and_drop="true" > <scroll - name="Inventory Scroller" - follows="all" - reserve_scroll_corner="true" - tab_stop="true" - /> + name="Inventory Scroller" + follows="all" + reserve_scroll_corner="true" + tab_stop="true" + /> </panel> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 0a21d8714c..f0bee2bfee 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -66,12 +66,14 @@ class ViewerManifest(LLManifest): # include the extracted list of contributors contributor_names = self.extract_names("../../doc/contributions.txt") self.put_in_file(contributor_names, "contributors.txt") + self.file_list.append(["../../doc/contributions.txt",self.dst_path_of("contributors.txt")]) # include the extracted list of translators translator_names = self.extract_names("../../doc/translations.txt") self.put_in_file(translator_names, "translators.txt") + self.file_list.append(["../../doc/translations.txt",self.dst_path_of("translators.txt")]) # include the list of Lindens (if any) # see https://wiki.lindenlab.com/wiki/Generated_Linden_Credits - linden_names_path = os.getenv("linden_credits") + linden_names_path = os.getenv("LINDEN_CREDITS") if linden_names_path : try: linden_file = open(linden_names_path,'r') @@ -79,9 +81,13 @@ class ViewerManifest(LLManifest): linden_names = ', '.join(linden_file.readlines()) self.put_in_file(linden_names, "lindens.txt") linden_file.close() + print "Linden names extracted from '%s'" % linden_names_path + self.file_list.append([linden_names_path,self.dst_path_of("lindens.txt")]) except IOError: print "No Linden names found at '%s', using built-in list" % linden_names_path pass + else : + print "No 'LINDEN_CREDITS' specified in environment, using built-in list" # ... and the entire windlight directory self.path("windlight") diff --git a/scripts/templates/template-cpp.cpp b/scripts/templates/template-cpp.cpp new file mode 100644 index 0000000000..35d8441c87 --- /dev/null +++ b/scripts/templates/template-cpp.cpp @@ -0,0 +1,30 @@ +/** +* @file #filename#.cpp +* @brief Implementation of #filename# +* @author #getpass.getuser()#@lindenlab.com +* +* $LicenseInfo:firstyear=#datetime.datetime.now().year#&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) #datetime.datetime.now().year#, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + + +#'' if ( skip_h ) else '%cinclude "%s.h"' % (35,filename)# + diff --git a/scripts/templates/template-h.h b/scripts/templates/template-h.h new file mode 100644 index 0000000000..ce7b4ddc87 --- /dev/null +++ b/scripts/templates/template-h.h @@ -0,0 +1,31 @@ +/** +* @file #filename#.h +* @brief Header file for #filename# +* @author #getpass.getuser()#@lindenlab.com +* +* $LicenseInfo:firstyear=#datetime.datetime.now().year#&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) #datetime.datetime.now().year#, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#'%c'%35#ifndef LL_#filename.upper().replace('-','_')#_H +#'%c'%35#define LL_#filename.upper().replace('-','_')#_H + + +#'%c'%35#endif // LL_#filename.upper().replace('-','_')#_H |