diff --git a/autobuild.xml b/autobuild.xml
index 88db33e3176a2767d77c08b4fbaa752049c27be8..b182b7ae5d6d35b7efe02e461b6d92f5ab1d80fd 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>42066e2447c7a3359784438d16510992</string>
+              <string>c5ab9d9d7482e48cd76f4bf391900a8c</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/40539/348124/viewer_manager-2.0.529188-darwin64-529188.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/43369/385585/viewer_manager-2.0.531000-darwin64-531000.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>ca230428635ce13cb7ace0f9522f8546</string>
+              <string>6b10d7407686d9e12e63576256581e3e</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/40538/348130/viewer_manager-2.0.529188-windows-529188.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/43370/385592/viewer_manager-2.0.531000-windows-531000.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
         <key>source_type</key>
         <string>hg</string>
         <key>version</key>
-        <string>2.0.529188</string>
+        <string>2.0.531000</string>
       </map>
       <key>vlc-bin</key>
       <map>
diff --git a/doc/contributions.txt b/doc/contributions.txt
index ca2e63cf9f8b6c73802bc00a596340e1ebc1ef75..c6ad23dc2c117dead9661ef346962959b832de50 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -347,6 +347,7 @@ Charles Courtois
 Charlie Sazaland
 Chaser Zaks
     BUG-225599
+    BUG-227485
 Cherry Cheevers
 ChickyBabes Zuzu
 Christopher  Organiser
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index 2b54cd41552485e882411ad79608b2b8b4933057..a5770c5528dd38ed50af1c45ae1e109f18788af7 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -186,12 +186,17 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
   list(GET LL_BUILD_LIST "${sysroot_idx}" CMAKE_OSX_SYSROOT)
   message(STATUS "CMAKE_OSX_SYSROOT = '${CMAKE_OSX_SYSROOT}'")
 
-  set(XCODE_VERSION 7.0)
-
   set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0")
   set(CMAKE_XCODE_ATTRIBUTE_GCC_STRICT_ALIASING NO)
   set(CMAKE_XCODE_ATTRIBUTE_GCC_FAST_MATH NO)
   set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS ssse3)
+  # we must hard code this to off for now.  xcode's built in signing does not
+  # handle embedded app bundles such as CEF and others. Any signing for local
+  # development must be done after the build as we do in viewer_manifest.py for
+  # released builds
+  # https://stackoverflow.com/a/54296008
+  # "-" represents "Sign to Run Locally" and empty string represents "Do Not Sign"
+  set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "")
 
   set(CMAKE_OSX_ARCHITECTURES "${ARCH}")
   string(REPLACE "i686"  "i386"   CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}")
diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index 6ab61689fd0532a8f67c65576ed2cd0c7bfcda94..e7db84f6ab2783b048a778ae5f1ef551bfa012cd 100644
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -271,7 +271,7 @@ BOOL LLVorbisDecodeState::initDecode()
 		mWAVBuffer.reserve(size_guess);
 		mWAVBuffer.resize(WAV_HEADER_SIZE);
 	}
-	catch (std::bad_alloc)
+	catch (std::bad_alloc&)
 	{
 		LL_WARNS("AudioEngine") << "Out of memory when trying to alloc buffer: " << size_guess << LL_ENDL;
 		delete mInFilep;
diff --git a/indra/llcharacter/llgesture.cpp b/indra/llcharacter/llgesture.cpp
index 1549c41e624e87b9f7a6b2a07d9501fbed7750d9..37904936d86a9eba74b76a7c2fbca6332ffd9f9d 100644
--- a/indra/llcharacter/llgesture.cpp
+++ b/indra/llcharacter/llgesture.cpp
@@ -107,11 +107,11 @@ BOOL LLGesture::trigger(const std::string& trigger_string)
 // NOT endian-neutral
 U8 *LLGesture::serialize(U8 *buffer) const
 {
-	htonmemcpy(buffer, &mKey, MVT_S8, 1);
+	htolememcpy(buffer, &mKey, MVT_S8, 1);
 	buffer += sizeof(mKey);
-	htonmemcpy(buffer, &mMask, MVT_U32, 4);
+	htolememcpy(buffer, &mMask, MVT_U32, 4);
 	buffer += sizeof(mMask);
-	htonmemcpy(buffer, mSoundItemID.mData, MVT_LLUUID, 16);
+	htolememcpy(buffer, mSoundItemID.mData, MVT_LLUUID, 16);
 	buffer += 16;
 	
 	memcpy(buffer, mTrigger.c_str(), mTrigger.length() + 1);		/* Flawfinder: ignore */
@@ -134,11 +134,11 @@ U8 *LLGesture::deserialize(U8 *buffer, S32 max_size)
 		return buffer;
 	}
 
-	htonmemcpy(&mKey, tmp, MVT_S8, 1);
+	htolememcpy(&mKey, tmp, MVT_S8, 1);
 	tmp += sizeof(mKey);
-	htonmemcpy(&mMask, tmp, MVT_U32, 4);
+	htolememcpy(&mMask, tmp, MVT_U32, 4);
 	tmp += sizeof(mMask);
-	htonmemcpy(mSoundItemID.mData, tmp, MVT_LLUUID, 16);
+	htolememcpy(mSoundItemID.mData, tmp, MVT_LLUUID, 16);
 	tmp += 16;
 	
 	mTrigger.assign((char *)tmp);
@@ -284,7 +284,7 @@ U8 *LLGestureList::serialize(U8 *buffer) const
 {
 	// a single S32 serves as the header that tells us how many to read
 	U32 count = mList.size();
-	htonmemcpy(buffer, &count, MVT_S32, 4);
+	htolememcpy(buffer, &count, MVT_S32, 4);
 	buffer += sizeof(count);
 
 	for (S32 i = 0; i < count; i++)
@@ -310,7 +310,7 @@ U8 *LLGestureList::deserialize(U8 *buffer, S32 max_size)
 		return buffer;
 	}
 
-	htonmemcpy(&count, tmp, MVT_S32, 4);
+	htolememcpy(&count, tmp, MVT_S32, 4);
 
 	if (count > MAX_GESTURES)
 	{
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index af41b9e460c75a609d213eae4f808734a9c4f80b..7e52a620dbcc899cf42fe3cd702fe22a027430b1 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -73,6 +73,7 @@ set(llcommon_SOURCE_FILES
     llinitparam.cpp
     llinitdestroyclass.cpp
     llinstancetracker.cpp
+    llkeybind.cpp
     llleap.cpp
     llleaplistener.cpp
     llliveappconfig.cpp
@@ -183,6 +184,7 @@ set(llcommon_HEADER_FILES
     llinitdestroyclass.h
     llinitparam.h
     llinstancetracker.h
+    llkeybind.h
     llkeythrottle.h
     llleap.h
     llleaplistener.h
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index 0fbf4b966b2becc9e4a68ec57e48c92b64d5abb0..ef29e7e5cd2460ca8634768a89543a389fb672c3 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -54,6 +54,17 @@ enum ETerrainBrushType
 	E_LANDBRUSH_INVALID = 6
 };
 
+enum EMouseClickType{
+    CLICK_NONE = -1,
+    CLICK_LEFT = 0,
+    CLICK_MIDDLE,
+    CLICK_RIGHT,
+    CLICK_BUTTON4,
+    CLICK_BUTTON5,
+    CLICK_DOUBLELEFT,
+    CLICK_COUNT // 'size', CLICK_NONE does not counts
+};
+
 // keys
 // Bit masks for various keyboard modifier keys.
 const MASK MASK_NONE =			0x0000;
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 29f0c7da9a39ee1ac9d6906a51519cf621dc44a3..984e90f37627116b3f7eb9f2b7ad132c280d830a 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -240,6 +240,64 @@ void _ll_apr_assert_status(apr_status_t status, const char* file, int line)
 	llassert(! _ll_apr_warn_status(status, file, line));
 }
 
+//---------------------------------------------------------------------
+//
+// Scope based pool access
+//
+//---------------------------------------------------------------------
+
+class LLAPRFilePoolScope
+{
+public:
+    LLAPRFilePoolScope() : pPool(NULL), mInitialized(false) {}
+    LLAPRFilePoolScope(LLVolatileAPRPool* poolp) : mInitialized(false)
+    { 
+        setFilePool(poolp);
+    }
+    ~LLAPRFilePoolScope()
+    {
+        reset();
+    }
+    apr_pool_t* getVolatileAPRPool(LLVolatileAPRPool* poolp = NULL)
+    {
+        if (!pPool)
+        {
+            setFilePool(poolp);
+        }
+        if (mInitialized)
+        {
+            // We need one clear per one get
+            // At the moment no need to support multiple calls
+            LL_ERRS() << "LLAPRFilePoolScope is not supposed to be initialized twice" << LL_ENDL;
+        }
+        mInitialized = true;
+        return pPool->getVolatileAPRPool();
+    }
+    void reset()
+    {
+        if (mInitialized)
+        {
+            pPool->clearVolatileAPRPool();
+        }
+    }
+
+private:
+    void setFilePool(LLVolatileAPRPool* poolp = NULL)
+    {
+        if (poolp)
+        {
+            pPool = poolp;
+        }
+        else
+        {
+            pPool = LLAPRFile::sAPRFilePoolp;
+        }
+    }
+
+    LLVolatileAPRPool *pPool;
+    bool mInitialized;
+};
+
 //---------------------------------------------------------------------
 //
 // LLAPRFile functions
@@ -287,9 +345,10 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLV
 	//check if already open some file
 	llassert_always(!mFile) ;
 	llassert_always(!mCurrentFilePoolp) ;
-	
-	apr_pool_t* apr_pool = pool ? pool->getVolatileAPRPool() : NULL ;
-	s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(apr_pool));
+
+	mCurrentFilePoolp = pool ? pool : sAPRFilePoolp;
+	apr_pool_t* apr_pool = mCurrentFilePoolp->getVolatileAPRPool(); //paired with clear in close()
+	s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool);
 
 	if (s != APR_SUCCESS || !mFile)
 	{
@@ -314,14 +373,10 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLV
 		*sizep = file_size;
 	}
 
-	if(!mCurrentFilePoolp)
+	if (!mFile)
 	{
-		mCurrentFilePoolp = pool ;
-
-		if(!mFile)
-		{
-			close() ;
-		}
+		// It will clean pool
+		close() ;
 	}
 
 	return s ;
@@ -348,17 +403,6 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOO
 	return s;
 }
 
-apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool)
-{	
-	if(!pool)
-	{
-		mCurrentFilePoolp = sAPRFilePoolp ;
-		return mCurrentFilePoolp->getVolatileAPRPool() ;
-	}
-
-	return pool ;
-}
-
 // File I/O
 S32 LLAPRFile::read(void *buf, S32 nbytes)
 {
@@ -415,7 +459,7 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
 //
 
 //static
-apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool) 
+apr_status_t LLAPRFile::close(apr_file_t* file_handle) 
 {
 	apr_status_t ret = APR_SUCCESS ;
 	if(file_handle)
@@ -424,29 +468,23 @@ apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool)
 		file_handle = NULL ;
 	}
 
-	if(pool)
-	{
-		pool->clearVolatileAPRPool() ;
-	}
-
 	return ret ;
 }
 
 //static
-apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
+apr_file_t* LLAPRFile::open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags)
 {
 	apr_status_t s;
 	apr_file_t* file_handle ;
 
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
 
-	s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());
+	s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool);
 	if (s != APR_SUCCESS || !file_handle)
 	{
 		ll_apr_warn_status(s);
 		LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL;
 		file_handle = NULL ;
-		close(file_handle, pool) ;
+		close(file_handle) ;
 		return NULL;
 	}
 
@@ -489,8 +527,9 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
 S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
 {
 	//*****************************************
-	apr_file_t* file_handle = open(filename, pool, APR_READ|APR_BINARY); 
-	//*****************************************	
+	LLAPRFilePoolScope scope(pool);
+	apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), APR_READ|APR_BINARY); 
+	//*****************************************
 	if (!file_handle)
 	{
 		return 0;
@@ -523,7 +562,7 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb
 	}
 	
 	//*****************************************
-	close(file_handle, pool) ; 
+	close(file_handle) ; 
 	//*****************************************
 	return (S32)bytes_read;
 }
@@ -537,9 +576,10 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
 		flags |= APR_APPEND;
 		offset = 0;
 	}
-	
+
 	//*****************************************
-	apr_file_t* file_handle = open(filename, pool, flags);
+	LLAPRFilePoolScope scope(pool);
+	apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), flags);
 	//*****************************************
 	if (!file_handle)
 	{
@@ -573,7 +613,7 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
 	}
 
 	//*****************************************
-	LLAPRFile::close(file_handle, pool);
+	LLAPRFile::close(file_handle);
 	//*****************************************
 
 	return (S32)bytes_written;
@@ -584,9 +624,8 @@ bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)
 {
 	apr_status_t s;
 
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-	s = apr_file_remove(filename.c_str(), pool->getVolatileAPRPool());
-	pool->clearVolatileAPRPool() ;
+	LLAPRFilePoolScope scope(pool);
+	s = apr_file_remove(filename.c_str(), scope.getVolatileAPRPool());
 
 	if (s != APR_SUCCESS)
 	{
@@ -602,9 +641,8 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname,
 {
 	apr_status_t s;
 
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-	s = apr_file_rename(filename.c_str(), newname.c_str(), pool->getVolatileAPRPool());
-	pool->clearVolatileAPRPool() ;
+	LLAPRFilePoolScope scope(pool);
+	s = apr_file_rename(filename.c_str(), newname.c_str(), scope.getVolatileAPRPool());
 	
 	if (s != APR_SUCCESS)
 	{
@@ -621,18 +659,16 @@ bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, ap
 	apr_file_t* apr_file;
 	apr_status_t s;
 
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-	s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());	
+	LLAPRFilePoolScope scope(pool);
+	s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, scope.getVolatileAPRPool());	
 
 	if (s != APR_SUCCESS || !apr_file)
 	{
-		pool->clearVolatileAPRPool() ;
 		return false;
 	}
 	else
 	{
 		apr_file_close(apr_file) ;
-		pool->clearVolatileAPRPool() ;
 		return true;
 	}
 }
@@ -643,14 +679,12 @@ S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
 	apr_file_t* apr_file;
 	apr_finfo_t info;
 	apr_status_t s;
-	
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-	s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool->getVolatileAPRPool());
+
+	LLAPRFilePoolScope scope(pool);
+	s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, scope.getVolatileAPRPool());
 	
 	if (s != APR_SUCCESS || !apr_file)
-	{		
-		pool->clearVolatileAPRPool() ;
-		
+	{				
 		return 0;
 	}
 	else
@@ -658,7 +692,6 @@ S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
 		apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file);		
 
 		apr_file_close(apr_file) ;
-		pool->clearVolatileAPRPool() ;
 		
 		if (s == APR_SUCCESS)
 		{
@@ -676,9 +709,8 @@ bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool)
 {
 	apr_status_t s;
 
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-	s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool->getVolatileAPRPool());
-	pool->clearVolatileAPRPool() ;
+	LLAPRFilePoolScope scope(pool);
+	s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, scope.getVolatileAPRPool());
 		
 	if (s != APR_SUCCESS)
 	{
@@ -694,9 +726,8 @@ bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool)
 {
 	apr_status_t s;
 
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-	s = apr_file_remove(dirname.c_str(), pool->getVolatileAPRPool());
-	pool->clearVolatileAPRPool() ;
+	LLAPRFilePoolScope scope(pool);
+	s = apr_file_remove(dirname.c_str(), scope.getVolatileAPRPool());
 	
 	if (s != APR_SUCCESS)
 	{
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index da50dda103084fbd7d881459a12774a3ff36d264..0d6637f999539629468ea42c2fc7377195a9f065 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -180,9 +180,6 @@ class LL_COMMON_API LLAPRFile : boost::noncopyable
 	S32 write(const void* buf, S32 nbytes);
 	
 	apr_file_t* getFileHandle() {return mFile;}	
-
-private:
-	apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;	
 	
 //
 //*******************************************************************************************************************************
@@ -192,8 +189,8 @@ class LL_COMMON_API LLAPRFile : boost::noncopyable
 	static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist.
 
 private:
-	static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags);
-	static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ;
+	static apr_file_t* open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags);
+	static apr_status_t close(apr_file_t* file) ;
 	static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);
 public:
 	// returns false if failure:
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 67e9fad1abf2b14e890624dfaee349f33ccd9350..cc775775bf26d357d32c6642ff9957fec51ba26d 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -347,7 +347,7 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla
     // run the code the caller actually wants in the coroutine
     try
     {
-#if LL_WINDOWS
+#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD
         winlevel(callable);
 #else
         callable();
diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ecfc289cb34270c8dd9eae5bf4b67b0890c78ce8
--- /dev/null
+++ b/indra/llcommon/llkeybind.cpp
@@ -0,0 +1,395 @@
+/** 
+ * @file llkeybind.cpp
+ * @brief Information about key combinations.
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, 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 "llkeybind.h"
+
+#include "llsd.h"
+#include "llsdutil.h"
+
+LLKeyData::LLKeyData()
+    :
+    mMouse(CLICK_NONE),
+    mKey(KEY_NONE),
+    mMask(MASK_NONE),
+    mIgnoreMasks(false)
+{
+}
+
+LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, MASK mask)
+    :
+    mMouse(mouse),
+    mKey(key),
+    mMask(mask),
+    mIgnoreMasks(false)
+{
+}
+
+LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, bool ignore_mask)
+    :
+    mMouse(mouse),
+    mKey(key),
+    mMask(MASK_NONE),
+    mIgnoreMasks(ignore_mask)
+{
+}
+
+LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask)
+    :
+    mMouse(mouse),
+    mKey(key),
+    mMask(mask),
+    mIgnoreMasks(ignore_mask)
+{
+}
+
+LLKeyData::LLKeyData(const LLSD &key_data)
+{
+    if (key_data.has("mouse"))
+    {
+        mMouse = (EMouseClickType)key_data["mouse"].asInteger();
+    }
+    if (key_data.has("key"))
+    {
+        mKey = key_data["key"].asInteger();
+    }
+    if (key_data.has("ignore_accelerators"))
+    {
+        mIgnoreMasks = key_data["ignore_accelerators"];
+    }
+    if (key_data.has("mask"))
+    {
+        mMask = key_data["mask"].asInteger();
+    }
+}
+
+LLSD LLKeyData::asLLSD() const
+{
+    LLSD data;
+    data["mouse"] = (LLSD::Integer)mMouse;
+    data["key"] = (LLSD::Integer)mKey;
+    data["mask"] = (LLSD::Integer)mMask;
+    if (mIgnoreMasks)
+    {
+        data["ignore_accelerators"] = (LLSD::Boolean)mIgnoreMasks;
+    }
+    return data;
+}
+
+bool LLKeyData::isEmpty() const
+{
+    return mMouse == CLICK_NONE && mKey == KEY_NONE;
+}
+
+void LLKeyData::reset()
+{
+    mMouse = CLICK_NONE;
+    mKey = KEY_NONE;
+    mMask = MASK_NONE;
+    mIgnoreMasks = false;
+}
+
+LLKeyData& LLKeyData::operator=(const LLKeyData& rhs)
+{
+    mMouse = rhs.mMouse;
+    mKey = rhs.mKey;
+    mMask = rhs.mMask;
+    mIgnoreMasks = rhs.mIgnoreMasks;
+    return *this;
+}
+
+bool LLKeyData::operator==(const LLKeyData& rhs)
+{
+    if (mMouse != rhs.mMouse) return false;
+    if (mKey != rhs.mKey) return false;
+    if (mMask != rhs.mMask) return false;
+    if (mIgnoreMasks != rhs.mIgnoreMasks) return false;
+    return true;
+}
+
+bool LLKeyData::operator!=(const LLKeyData& rhs)
+{
+    if (mMouse != rhs.mMouse) return true;
+    if (mKey != rhs.mKey) return true;
+    if (mMask != rhs.mMask) return true;
+    if (mIgnoreMasks != rhs.mIgnoreMasks) return true;
+    return false;
+}
+
+bool LLKeyData::canHandle(const LLKeyData& data) const
+{
+    if (data.mKey == mKey
+        && data.mMouse == mMouse
+        && ((mIgnoreMasks && (data.mMask & mMask) == data.mMask) || data.mMask == mMask))
+    {
+        return true;
+    }
+    return false;
+}
+
+bool LLKeyData::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
+{
+    if (mouse == mMouse
+        && key == mKey
+        && ((mIgnoreMasks && (mask & mMask) == mask) || mask == mMask))
+    {
+        return true;
+    }
+    return false;
+}
+
+// LLKeyBind
+
+LLKeyBind::LLKeyBind(const LLSD &key_bind)
+{
+    if (key_bind.isArray())
+    {
+        for (LLSD::array_const_iterator data = key_bind.beginArray(), endLists = key_bind.endArray();
+            data != endLists;
+            data++
+            )
+        {
+            mData.push_back(LLKeyData(*data));
+        }
+    }
+}
+
+bool LLKeyBind::operator==(const LLKeyBind& rhs)
+{
+    U32 size = mData.size();
+    if (size != rhs.mData.size()) return false;
+
+    for (U32 i = 0; i < size; i++)
+    {
+        if (mData[i] != rhs.mData[i]) return false;
+    }
+
+    return true;
+}
+
+bool LLKeyBind::operator!=(const LLKeyBind& rhs)
+{
+    U32 size = mData.size();
+    if (size != rhs.mData.size()) return true;
+
+    for (U32 i = 0; i < size; i++)
+    {
+        if (mData[i] != rhs.mData[i]) return true;
+    }
+
+    return false;
+}
+
+bool LLKeyBind::isEmpty() const
+{
+    for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
+    {
+        if (!iter->isEmpty()) return false;
+    }
+    return true;
+}
+
+LLSD LLKeyBind::asLLSD() const
+{
+    S32 last = mData.size() - 1;
+    while (mData[last].empty())
+    {
+        last--;
+    }
+
+    LLSD data;
+    for (S32 i = 0; i <= last; ++i)
+    {
+        // append even if empty to not affect visual representation
+        data.append(mData[i].asLLSD());
+    }
+    return data;
+}
+
+bool LLKeyBind::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
+{
+    if (mouse == CLICK_NONE && key == KEY_NONE)
+    {
+        // assume placeholder
+        return false;
+    }
+
+    for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
+    {
+        if (iter->canHandle(mouse, key, mask))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool LLKeyBind::canHandleKey(KEY key, MASK mask) const
+{
+    return canHandle(CLICK_NONE, key, mask);
+}
+
+bool LLKeyBind::canHandleMouse(EMouseClickType mouse, MASK mask) const
+{
+    return canHandle(mouse, KEY_NONE, mask);
+}
+
+bool LLKeyBind::hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const
+{
+    if (mouse != CLICK_NONE || key != KEY_NONE)
+    {
+        for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
+        {
+            if (iter->mKey == key
+                && iter->mMask == mask
+                && iter->mMouse == mouse
+                && iter->mIgnoreMasks == ignore)
+            {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool LLKeyBind::hasKeyData(const LLKeyData& data) const
+{
+    return hasKeyData(data.mMouse, data.mKey, data.mMask, data.mIgnoreMasks);
+}
+
+bool LLKeyBind::hasKeyData(U32 index) const
+{
+    return mData.size() > index;
+}
+
+S32 LLKeyBind::findKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const
+{
+    if (mouse != CLICK_NONE || key != KEY_NONE)
+    {
+        for (S32 i = 0; i < mData.size(); ++i)
+        {
+            if (mData[i].mKey == key
+                && mData[i].mMask == mask
+                && mData[i].mMouse == mouse
+                && mData[i].mIgnoreMasks == ignore)
+            {
+                return i;
+            }
+        }
+    }
+    return -1;
+}
+
+S32 LLKeyBind::findKeyData(const LLKeyData& data) const
+{
+    return findKeyData(data.mMouse, data.mKey, data.mMask, data.mIgnoreMasks);
+}
+
+LLKeyData LLKeyBind::getKeyData(U32 index) const
+{
+    if (mData.size() > index)
+    {
+        return mData[index];
+    }
+    return LLKeyData();
+}
+
+bool LLKeyBind::addKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore)
+{
+    if (!hasKeyData(mouse, key, mask, ignore))
+    {
+        mData.push_back(LLKeyData(mouse, key, mask, ignore));
+        return true;
+    }
+    return false;
+}
+
+bool LLKeyBind::addKeyData(const LLKeyData& data)
+{
+    if (!hasKeyData(data))
+    {
+        mData.push_back(data);
+        return true;
+    }
+    return false;
+}
+
+void LLKeyBind::replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index)
+{
+    replaceKeyData(LLKeyData(mouse, key, mask, ignore), index);
+}
+
+void LLKeyBind::replaceKeyData(const LLKeyData& data, U32 index)
+{
+    if (!data.isEmpty())
+    {
+        // if both click and key are none (isEmpty()), we are inserting a placeholder, we don't want to reset anything
+        // otherwise reset identical key
+        for (data_vector_t::iterator iter = mData.begin(); iter != mData.end(); iter++)
+        {
+            if (iter->mKey == data.mKey
+                && iter->mMouse == data.mMouse
+                && iter->mIgnoreMasks == data.mIgnoreMasks
+                && iter->mMask == data.mMask)
+            {
+                // Replacing only fully equal combinations even in case 'ignore' is set
+                // Reason: Simplicity and user might decide to do a 'move' command as W and Shift+Ctrl+W, and 'run' as Shift+W
+                iter->reset();
+                break;
+            }
+        }
+    }
+    if (mData.size() <= index)
+    {
+        mData.resize(index + 1);
+    }
+    mData[index] = data;
+}
+
+void LLKeyBind::resetKeyData(S32 index)
+{
+    if (mData.size() > index)
+    {
+        mData[index].reset();
+    }
+}
+
+void LLKeyBind::trimEmpty()
+{
+    S32 last = mData.size() - 1;
+    while (last >= 0 && mData[last].empty())
+    {
+        mData.erase(mData.begin() + last);
+        last--;
+    }
+}
+
+U32 LLKeyBind::getDataCount()
+{
+    return mData.size();
+}
+
diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h
new file mode 100644
index 0000000000000000000000000000000000000000..ad0ebec67cdbb0596e8ae993f78580c106fdc1ed
--- /dev/null
+++ b/indra/llcommon/llkeybind.h
@@ -0,0 +1,106 @@
+/** 
+ * @file llkeybind.h
+ * @brief Information about key combinations.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+#ifndef LL_KEYBIND_H
+#define LL_KEYBIND_H
+
+#include "indra_constants.h"
+
+// KeyData - single key combination (mouse/mask/keyboard)
+class LL_COMMON_API LLKeyData
+{
+public:
+    LLKeyData();
+    LLKeyData(EMouseClickType mouse, KEY key, MASK mask);
+    LLKeyData(EMouseClickType mouse, KEY key, bool ignore_mask);
+    LLKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask);
+    LLKeyData(const LLSD &key_data);
+
+    LLSD asLLSD() const;
+    bool isEmpty() const;
+    bool empty() const { return isEmpty(); };
+    void reset();
+    LLKeyData& operator=(const LLKeyData& rhs);
+    bool operator==(const LLKeyData& rhs);
+    bool operator!=(const LLKeyData& rhs);
+
+    bool canHandle(const LLKeyData& data) const;
+    bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const;
+
+    EMouseClickType mMouse;
+    KEY mKey;
+    MASK mMask;
+    // Either to expect exact match or ignore not expected masks
+    bool mIgnoreMasks; 
+};
+
+// One function can bind to multiple Key options
+class LLKeyBind
+{
+public:
+    LLKeyBind() {}
+    LLKeyBind(const LLSD &key_bind);
+
+    bool operator==(const LLKeyBind& rhs);
+    bool operator!=(const LLKeyBind& rhs);
+    bool isEmpty() const;
+    bool empty() const { return isEmpty(); };
+
+    LLSD asLLSD() const;
+
+    bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const;
+    bool canHandleKey(KEY key, MASK mask) const;
+    bool canHandleMouse(EMouseClickType mouse, MASK mask) const;
+
+    // contains specified combination
+    bool hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const;
+    bool hasKeyData(const LLKeyData& data) const;
+    bool hasKeyData(U32 index) const;
+
+    // index of contained LLKeyData
+    S32 findKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const;
+    S32 findKeyData(const LLKeyData& data) const;
+
+    LLKeyData getKeyData(U32 index) const;
+
+    // these methods enshure there will be no repeats
+    bool addKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore);
+    bool addKeyData(const LLKeyData& data);
+    void replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index);
+    void replaceKeyData(const LLKeyData& data, U32 index);
+    void resetKeyData(S32 index);
+    void clear() { mData.clear(); }
+    // if there any empty LLKeyData in the end of the array, remove them
+    void trimEmpty();
+    U32 getDataCount();
+
+private:
+    typedef std::vector<LLKeyData> data_vector_t;
+    data_vector_t mData;
+};
+
+
+#endif // LL_KEYBIND_H
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 1aaff5628f2658ab89e9d733b2b6dc5bbb1b6b7c..0bae59ef4c76538197772d2d41db9d10e1748089 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -2241,7 +2241,7 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,
 			return ZR_SIZE_ERROR;
 		}
 #endif
-		catch (std::bad_alloc)
+		catch (std::bad_alloc&)
 		{
 			free(result);
 			return ZR_MEM_ERROR;
diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp
index 0b72b5318601f92834dadb93df0cfd968838576e..34268d94f64969b4746f302530a14e196fe3c72d 100644
--- a/indra/llcorehttp/_httpservice.cpp
+++ b/indra/llcorehttp/_httpservice.cpp
@@ -318,7 +318,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread)
         {
             LOG_UNHANDLED_EXCEPTION("");
         }
-        catch (std::bad_alloc)
+        catch (std::bad_alloc&)
         {
             LLMemory::logMemoryInfo(TRUE);
 
diff --git a/indra/llcorehttp/bufferarray.cpp b/indra/llcorehttp/bufferarray.cpp
index be534b3ce4f2fd67d11ef9158bf1f076e1565c8f..e0b2876a0016167b6dc007da55e8eef869f54287 100644
--- a/indra/llcorehttp/bufferarray.cpp
+++ b/indra/llcorehttp/bufferarray.cpp
@@ -147,7 +147,7 @@ size_t BufferArray::append(const void * src, size_t len)
         {
             block = Block::alloc(BLOCK_ALLOC_SIZE);
         }
-        catch (std::bad_alloc)
+        catch (std::bad_alloc&)
         {
             LLMemory::logMemoryInfo(TRUE);
 
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 9dea87611423e5ccfdeac6ac7354cd1df4f4f230..7a0c8cd8f57eab57ec105a6b208dc22fffc7b5a7 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -2168,19 +2168,27 @@ bool LLImageFormatted::load(const std::string &filename, int load_size)
 	}
 	bool res;
 	U8 *data = allocateData(load_size);
-	apr_size_t bytes_read = load_size;
-	apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
-	if (s != APR_SUCCESS || (S32) bytes_read != load_size)
+	if (data)
 	{
-		deleteData();
-		setLastError("Unable to read file",filename);
-		res = false;
+		apr_size_t bytes_read = load_size;
+		apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
+		if (s != APR_SUCCESS || (S32) bytes_read != load_size)
+		{
+			deleteData();
+			setLastError("Unable to read file",filename);
+			res = false;
+		}
+		else
+		{
+			res = updateData();
+		}
 	}
 	else
 	{
-		res = updateData();
+		setLastError("Allocation failure", filename);
+		res = false;
 	}
-	
+
 	return res;
 }
 
diff --git a/indra/llimage/llimagejpeg.cpp b/indra/llimage/llimagejpeg.cpp
index 3b1b060c023b4ffe4146bcb8f972bf20644d5852..ead9a37fb89592633c24079c908e79e3063dc5e1 100644
--- a/indra/llimage/llimagejpeg.cpp
+++ b/indra/llimage/llimagejpeg.cpp
@@ -315,7 +315,7 @@ bool LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
 		jpeg_destroy_decompress(&cinfo);
 	}
 
-	catch (std::bad_alloc)
+	catch (std::bad_alloc&)
 	{
 		setLastError( "Out of memory");
 		jpeg_destroy_decompress(&cinfo);
diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp
index f298764cc0743a8a5856c741a7645673e920961f..f7dc6272cf94cc7c5ad4319669781eb7f63f9080 100644
--- a/indra/llimage/llpngwrapper.cpp
+++ b/indra/llimage/llpngwrapper.cpp
@@ -210,7 +210,7 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
 		releaseResources();
 		return (FALSE);
 	}
-	catch (std::bad_alloc)
+	catch (std::bad_alloc&)
 	{
 		mErrorMessage = "LLPngWrapper";
 		releaseResources();
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index e7a8ca2f9d79221b48d495cede4db11e408a03ac..ac02364a67be6dd6e412aadc4bbdff13d5746f77 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2400,9 +2400,9 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
 			{ //face has no geometry, continue
 				face.resizeIndices(3);
 				face.resizeVertices(1);
-				memset(face.mPositions, 0, sizeof(LLVector4a));
-				memset(face.mNormals, 0, sizeof(LLVector4a));
-				memset(face.mTexCoords, 0, sizeof(LLVector2));
+				face.mPositions->clear();
+				face.mNormals->clear();
+				face.mTexCoords->setZero();
 				memset(face.mIndices, 0, sizeof(U16)*3);
 				continue;
 			}
@@ -2490,7 +2490,11 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
 				}
 				else
 				{
-					memset(norm_out, 0, sizeof(LLVector4a)*num_verts);
+					for (U32 j = 0; j < num_verts; ++j)
+					{
+						norm_out->clear();
+						norm_out++; // or just norm_out[j].clear();
+					}
 				}
 			}
 
@@ -2520,7 +2524,11 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
 				}
 				else
 				{
-					memset(tc_out, 0, sizeof(LLVector2)*num_verts);
+					for (U32 j = 0; j < num_verts; j += 2)
+					{
+						tc_out->clear();
+						tc_out++;
+					}
 				}
 			}
 
@@ -5252,7 +5260,7 @@ bool LLVolumeFace::cacheOptimize()
 		triangle_data.resize(mNumIndices / 3);
 		vertex_data.resize(mNumVertices);
 	}
-	catch (std::bad_alloc)
+	catch (std::bad_alloc&)
 	{
 		LL_WARNS("LLVOLUME") << "Resize failed" << LL_ENDL;
 		return false;
@@ -5406,7 +5414,7 @@ bool LLVolumeFace::cacheOptimize()
 	{
 		new_idx.resize(mNumVertices, -1);
 	}
-	catch (std::bad_alloc)
+	catch (std::bad_alloc&)
 	{
 		ll_aligned_free<64>(pos);
 		ll_aligned_free_16(wght);
@@ -6914,11 +6922,16 @@ void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVe
 {
     //LLVector4a *tan1 = new LLVector4a[vertexCount * 2];
 	LLVector4a* tan1 = (LLVector4a*) ll_aligned_malloc_16(vertexCount*2*sizeof(LLVector4a));
+	// new(tan1) LLVector4a;
 
     LLVector4a* tan2 = tan1 + vertexCount;
 
-	memset(tan1, 0, vertexCount*2*sizeof(LLVector4a));
-        
+    U32 count = vertexCount * 2;
+    for (U32 i = 0; i < count; i++)
+    {
+        tan1[i].clear();
+    }
+
     for (U32 a = 0; a < triangleCount; a++)
     {
         U32 i1 = *index_array++;
diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp
index 24387fbffd7bf869175b098557e94594eaac696b..0eae6d98263a30f27e51febc085c8ae4210759f0 100644
--- a/indra/llmessage/llcorehttputil.cpp
+++ b/indra/llmessage/llcorehttputil.cpp
@@ -597,7 +597,7 @@ LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore:
     {
         bas >> jsonRoot;
     }
-    catch (std::runtime_error e)
+    catch (std::runtime_error& e)
     {   // deserialization failed.  Record the reason and pass back an empty map for markup.
         status = LLCore::HttpStatus(499, std::string(e.what()));
         return result;
@@ -625,7 +625,7 @@ LLSD HttpCoroJSONHandler::parseBody(LLCore::HttpResponse *response, bool &succes
     {
         bas >> jsonRoot;
     }
-    catch (std::runtime_error e)
+    catch (std::runtime_error&)
     {   
         success = false;
         return LLSD();
diff --git a/indra/llmessage/lldatapacker.cpp b/indra/llmessage/lldatapacker.cpp
index 3510f93805daa66c2ad0ac724c16217e7ce1b5dd..6cf6af6437df9eab442b324a2c2e0306404ec62b 100644
--- a/indra/llmessage/lldatapacker.cpp
+++ b/indra/llmessage/lldatapacker.cpp
@@ -186,7 +186,7 @@ BOOL LLDataPackerBinaryBuffer::packString(const std::string& value, const char *
 
 	if (mWriteEnabled) 
 	{
-		htonmemcpy(mCurBufferp, value.c_str(), MVT_VARIABLE, length);  
+		htolememcpy(mCurBufferp, value.c_str(), MVT_VARIABLE, length);  
 	}
 	mCurBufferp += length;
 	return success;
@@ -213,12 +213,12 @@ BOOL LLDataPackerBinaryBuffer::packBinaryData(const U8 *value, S32 size, const c
 
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, &size, MVT_S32, 4);  
+		htolememcpy(mCurBufferp, &size, MVT_S32, 4);  
 	}
 	mCurBufferp += 4;
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, value, MVT_VARIABLE, size);  
+		htolememcpy(mCurBufferp, value, MVT_VARIABLE, size);  
 	}
 	mCurBufferp += size;
 	return success;
@@ -229,12 +229,12 @@ BOOL LLDataPackerBinaryBuffer::unpackBinaryData(U8 *value, S32 &size, const char
 {
 	BOOL success = TRUE;
 	success &= verifyLength(4, name);
-	htonmemcpy(&size, mCurBufferp, MVT_S32, 4);
+	htolememcpy(&size, mCurBufferp, MVT_S32, 4);
 	mCurBufferp += 4;
 	success &= verifyLength(size, name);
 	if (success)
 	{
-		htonmemcpy(value, mCurBufferp, MVT_VARIABLE, size);
+		htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);
 		mCurBufferp += size;
 	}
 	else
@@ -253,7 +253,7 @@ BOOL LLDataPackerBinaryBuffer::packBinaryDataFixed(const U8 *value, S32 size, co
 
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, value, MVT_VARIABLE, size);  
+		htolememcpy(mCurBufferp, value, MVT_VARIABLE, size);  
 	}
 	mCurBufferp += size;
 	return success;
@@ -264,7 +264,7 @@ BOOL LLDataPackerBinaryBuffer::unpackBinaryDataFixed(U8 *value, S32 size, const
 {
 	BOOL success = TRUE;
 	success &= verifyLength(size, name);
-	htonmemcpy(value, mCurBufferp, MVT_VARIABLE, size);
+	htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);
 	mCurBufferp += size;
 	return success;
 }
@@ -302,7 +302,7 @@ BOOL LLDataPackerBinaryBuffer::packU16(const U16 value, const char *name)
 
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, &value, MVT_U16, 2);  
+		htolememcpy(mCurBufferp, &value, MVT_U16, 2);  
 	}
 	mCurBufferp += 2;
 	return success;
@@ -314,7 +314,7 @@ BOOL LLDataPackerBinaryBuffer::unpackU16(U16 &value, const char *name)
 	BOOL success = TRUE;
 	success &= verifyLength(sizeof(U16), name);
 
-	htonmemcpy(&value, mCurBufferp, MVT_U16, 2);
+	htolememcpy(&value, mCurBufferp, MVT_U16, 2);
 	mCurBufferp += 2;
 	return success;
 }
@@ -327,7 +327,7 @@ BOOL LLDataPackerBinaryBuffer::packU32(const U32 value, const char *name)
 
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, &value, MVT_U32, 4);  
+		htolememcpy(mCurBufferp, &value, MVT_U32, 4);  
 	}
 	mCurBufferp += 4;
 	return success;
@@ -339,7 +339,7 @@ BOOL LLDataPackerBinaryBuffer::unpackU32(U32 &value, const char *name)
 	BOOL success = TRUE;
 	success &= verifyLength(sizeof(U32), name);
 
-	htonmemcpy(&value, mCurBufferp, MVT_U32, 4);
+	htolememcpy(&value, mCurBufferp, MVT_U32, 4);
 	mCurBufferp += 4;
 	return success;
 }
@@ -352,7 +352,7 @@ BOOL LLDataPackerBinaryBuffer::packS32(const S32 value, const char *name)
 
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, &value, MVT_S32, 4); 
+		htolememcpy(mCurBufferp, &value, MVT_S32, 4); 
 	}
 	mCurBufferp += 4;
 	return success;
@@ -364,7 +364,7 @@ BOOL LLDataPackerBinaryBuffer::unpackS32(S32 &value, const char *name)
 	BOOL success = TRUE;
 	success &= verifyLength(sizeof(S32), name);
 
-	htonmemcpy(&value, mCurBufferp, MVT_S32, 4);
+	htolememcpy(&value, mCurBufferp, MVT_S32, 4);
 	mCurBufferp += 4;
 	return success;
 }
@@ -377,7 +377,7 @@ BOOL LLDataPackerBinaryBuffer::packF32(const F32 value, const char *name)
 
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, &value, MVT_F32, 4); 
+		htolememcpy(mCurBufferp, &value, MVT_F32, 4); 
 	}
 	mCurBufferp += 4;
 	return success;
@@ -389,7 +389,7 @@ BOOL LLDataPackerBinaryBuffer::unpackF32(F32 &value, const char *name)
 	BOOL success = TRUE;
 	success &= verifyLength(sizeof(F32), name);
 
-	htonmemcpy(&value, mCurBufferp, MVT_F32, 4);
+	htolememcpy(&value, mCurBufferp, MVT_F32, 4);
 	mCurBufferp += 4;
 	return success;
 }
@@ -402,7 +402,7 @@ BOOL LLDataPackerBinaryBuffer::packColor4(const LLColor4 &value, const char *nam
 
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, value.mV, MVT_LLVector4, 16); 
+		htolememcpy(mCurBufferp, value.mV, MVT_LLVector4, 16); 
 	}
 	mCurBufferp += 16;
 	return success;
@@ -414,7 +414,7 @@ BOOL LLDataPackerBinaryBuffer::unpackColor4(LLColor4 &value, const char *name)
 	BOOL success = TRUE;
 	success &= verifyLength(16, name);
 
-	htonmemcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
+	htolememcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
 	mCurBufferp += 16;
 	return success;
 }
@@ -427,7 +427,7 @@ BOOL LLDataPackerBinaryBuffer::packColor4U(const LLColor4U &value, const char *n
 
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, value.mV, MVT_VARIABLE, 4);  
+		htolememcpy(mCurBufferp, value.mV, MVT_VARIABLE, 4);  
 	}
 	mCurBufferp += 4;
 	return success;
@@ -439,7 +439,7 @@ BOOL LLDataPackerBinaryBuffer::unpackColor4U(LLColor4U &value, const char *name)
 	BOOL success = TRUE;
 	success &= verifyLength(4, name);
 
-	htonmemcpy(value.mV, mCurBufferp, MVT_VARIABLE, 4);
+	htolememcpy(value.mV, mCurBufferp, MVT_VARIABLE, 4);
 	mCurBufferp += 4;
 	return success;
 }
@@ -453,8 +453,8 @@ BOOL LLDataPackerBinaryBuffer::packVector2(const LLVector2 &value, const char *n
 
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, &value.mV[0], MVT_F32, 4);  
-		htonmemcpy(mCurBufferp+4, &value.mV[1], MVT_F32, 4);  
+		htolememcpy(mCurBufferp, &value.mV[0], MVT_F32, 4);  
+		htolememcpy(mCurBufferp+4, &value.mV[1], MVT_F32, 4);  
 	}
 	mCurBufferp += 8;
 	return success;
@@ -466,8 +466,8 @@ BOOL LLDataPackerBinaryBuffer::unpackVector2(LLVector2 &value, const char *name)
 	BOOL success = TRUE;
 	success &= verifyLength(8, name);
 
-	htonmemcpy(&value.mV[0], mCurBufferp, MVT_F32, 4);
-	htonmemcpy(&value.mV[1], mCurBufferp+4, MVT_F32, 4);
+	htolememcpy(&value.mV[0], mCurBufferp, MVT_F32, 4);
+	htolememcpy(&value.mV[1], mCurBufferp+4, MVT_F32, 4);
 	mCurBufferp += 8;
 	return success;
 }
@@ -480,7 +480,7 @@ BOOL LLDataPackerBinaryBuffer::packVector3(const LLVector3 &value, const char *n
 
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, value.mV, MVT_LLVector3, 12);  
+		htolememcpy(mCurBufferp, value.mV, MVT_LLVector3, 12);  
 	}
 	mCurBufferp += 12;
 	return success;
@@ -492,7 +492,7 @@ BOOL LLDataPackerBinaryBuffer::unpackVector3(LLVector3 &value, const char *name)
 	BOOL success = TRUE;
 	success &= verifyLength(12, name);
 
-	htonmemcpy(value.mV, mCurBufferp, MVT_LLVector3, 12);
+	htolememcpy(value.mV, mCurBufferp, MVT_LLVector3, 12);
 	mCurBufferp += 12;
 	return success;
 }
@@ -504,7 +504,7 @@ BOOL LLDataPackerBinaryBuffer::packVector4(const LLVector4 &value, const char *n
 
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);  
+		htolememcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);  
 	}
 	mCurBufferp += 16;
 	return success;
@@ -516,7 +516,7 @@ BOOL LLDataPackerBinaryBuffer::unpackVector4(LLVector4 &value, const char *name)
 	BOOL success = TRUE;
 	success &= verifyLength(16, name);
 
-	htonmemcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
+	htolememcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
 	mCurBufferp += 16;
 	return success;
 }
@@ -528,7 +528,7 @@ BOOL LLDataPackerBinaryBuffer::packUUID(const LLUUID &value, const char *name)
 
 	if (mWriteEnabled) 
 	{ 
-		htonmemcpy(mCurBufferp, value.mData, MVT_LLUUID, 16);  
+		htolememcpy(mCurBufferp, value.mData, MVT_LLUUID, 16);  
 	}
 	mCurBufferp += 16;
 	return success;
@@ -540,7 +540,7 @@ BOOL LLDataPackerBinaryBuffer::unpackUUID(LLUUID &value, const char *name)
 	BOOL success = TRUE;
 	success &= verifyLength(16, name);
 
-	htonmemcpy(value.mData, mCurBufferp, MVT_LLUUID, 16);
+	htolememcpy(value.mData, mCurBufferp, MVT_LLUUID, 16);
 	mCurBufferp += 16;
 	return success;
 }
diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp
index 04b34a296c13c4961498a4f58f6dccdf014689f2..6fd17c91549b59adce034624f8b9f4f25fb15c70 100644
--- a/indra/llmessage/llhttpnode.cpp
+++ b/indra/llmessage/llhttpnode.cpp
@@ -125,7 +125,7 @@ void LLHTTPNode::get(LLHTTPNode::ResponsePtr response, const LLSD& context) cons
 	{
 		response->result(simpleGet());
 	}
-	catch (NotImplemented)
+	catch (NotImplemented&)
 	{
 		response->methodNotAllowed();
 	}
@@ -138,7 +138,7 @@ void LLHTTPNode::put(LLHTTPNode::ResponsePtr response, const LLSD& context, cons
 	{
 		response->result(simplePut(input));
 	}
-	catch (NotImplemented)
+	catch (NotImplemented&)
 	{
 		response->methodNotAllowed();
 	}
@@ -151,7 +151,7 @@ void LLHTTPNode::post(LLHTTPNode::ResponsePtr response, const LLSD& context, con
 	{
 		response->result(simplePost(input));
 	}
-	catch (NotImplemented)
+	catch (NotImplemented&)
 	{
 		response->methodNotAllowed();
 	}
@@ -164,7 +164,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons
     {
 	response->result(simpleDel(context));
     }
-    catch (NotImplemented)
+    catch (NotImplemented&)
     {
 	response->methodNotAllowed();
     }
diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp
index 134154aa6ce900d52e73dee372052801a060c55b..fcda2a85f622bd51d09f41f90881b7da9196fccb 100644
--- a/indra/llmessage/llmail.cpp
+++ b/indra/llmessage/llmail.cpp
@@ -373,7 +373,7 @@ std::string LLMail::encryptIMEmailAddress(const LLUUID& from_agent_id,
 	// Convert input data into a binary blob
 	std::vector<U8> data;
 	data.resize(data_size);
-	// *NOTE: This may suffer from endian issues.  Could be htonmemcpy.
+	// *NOTE: This may suffer from endian issues.  Could be htolememcpy.
 	memcpy(&data[0], &time, 4);
 	memcpy(&data[4], &from_agent_id.mData[0], UUID_BYTES);
 	memcpy(&data[4 + UUID_BYTES], &to_agent_id.mData[0], UUID_BYTES);
diff --git a/indra/llmessage/llmessagetemplate.cpp b/indra/llmessage/llmessagetemplate.cpp
index c4c7e667034b24003bf0ea57000d16724bb0daae..e70e25943644f748e314007295ae5538ae828953 100644
--- a/indra/llmessage/llmessagetemplate.cpp
+++ b/indra/llmessage/llmessagetemplate.cpp
@@ -47,7 +47,7 @@ void LLMsgVarData::addData(const void *data, S32 size, EMsgVariableType type, S3
 	{
 		delete[] mData; // Delete it if it already exists
 		mData = new U8[size];
-		htonmemcpy(mData, data, mType, size);
+		htolememcpy(mData, data, mType, size);
 	}
 }
 
diff --git a/indra/llmessage/lltemplatemessagebuilder.cpp b/indra/llmessage/lltemplatemessagebuilder.cpp
index 8d7c4c028268a85ff185a4aff5a771c52bb7c746..5ac5f6c580305aff5db5e7074929d79dc117a90e 100644
--- a/indra/llmessage/lltemplatemessagebuilder.cpp
+++ b/indra/llmessage/lltemplatemessagebuilder.cpp
@@ -689,14 +689,14 @@ static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* templat
 					{
 					case 1:
 						sizeb = size;
-						htonmemcpy(&buffer[result], &sizeb, MVT_U8, 1);
+						htolememcpy(&buffer[result], &sizeb, MVT_U8, 1);
 						break;
 					case 2:
 						sizeh = size;
-						htonmemcpy(&buffer[result], &sizeh, MVT_U16, 2);
+						htolememcpy(&buffer[result], &sizeh, MVT_U16, 2);
 						break;
 					case 4:
-						htonmemcpy(&buffer[result], &size, MVT_S32, 4);
+						htolememcpy(&buffer[result], &size, MVT_S32, 4);
 						break;
 					default:
 						LL_ERRS() << "Attempting to build variable field with unknown size of " << size << LL_ENDL;
diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp
index 4e0c53c37e3b23ca3a1fe607feb33e02caf44e21..6d5ad0ba089a30324f517b91acfaf9c379f36752 100644
--- a/indra/llmessage/lltemplatemessagereader.cpp
+++ b/indra/llmessage/lltemplatemessagereader.cpp
@@ -645,15 +645,15 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
 						switch(data_size)
 						{
 						case 1:
-							htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1);
+							htolememcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1);
 							tsize = tsizeb;
 							break;
 						case 2:
-							htonmemcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2);
+							htolememcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2);
 							tsize = tsizeh;
 							break;
 						case 4:
-							htonmemcpy(&tsize, &buffer[decode_pos], MVT_U32, 4);
+							htolememcpy(&tsize, &buffer[decode_pos], MVT_U32, 4);
 							break;
 						default:
 							LL_ERRS() << "Attempting to read variable field with unknown size of " << data_size << LL_ENDL;
diff --git a/indra/llmessage/llxfer.cpp b/indra/llmessage/llxfer.cpp
index c8b9d5d19fad4971547c52632fc4236951a78614..32e0e2cc3b2b8da4045c78c86c32da39c5e93d03 100644
--- a/indra/llmessage/llxfer.cpp
+++ b/indra/llmessage/llxfer.cpp
@@ -245,7 +245,7 @@ void LLXfer::sendPacket(S32 packet_num)
 				num_copy);
 		}
 		fdata_size += sizeof(S32);
-		htonmemcpy(fdata_buf,&mXferSize, MVT_S32, sizeof(S32));
+		htolememcpy(fdata_buf,&mXferSize, MVT_S32, sizeof(S32));
 	}
 
 	S32 encoded_packetnum = encodePacketNum(packet_num,last_packet);
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index f6c5d9e228d8087ddbb0f985aa18f895d91b2973..0af5a1b96dba0bf0b3a61f8c148c1e65708af023 100644
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -860,10 +860,10 @@ void null_message_callback(LLMessageSystem *msg, void **data);
 //
 
 #if !defined( LL_BIG_ENDIAN ) && !defined( LL_LITTLE_ENDIAN )
-#error Unknown endianness for htonmemcpy. Did you miss a common include?
+#error Unknown endianness for htolememcpy. Did you miss a common include?
 #endif
 
-static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type, size_t n)
+static inline void *htolememcpy(void *vs, const void *vct, EMsgVariableType type, size_t n)
 {
 	char *s = (char *)vs;
 	const char *ct = (const char *)vct;
@@ -886,7 +886,7 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
 	case MVT_S16:
 		if (n != 2)
 		{
-			LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
+			LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
 		}
 #ifdef LL_BIG_ENDIAN
 		*(s + 1) = *(ct);
@@ -901,7 +901,7 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
 	case MVT_F32:
 		if (n != 4)
 		{
-			LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
+			LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
 		}
 #ifdef LL_BIG_ENDIAN
 		*(s + 3) = *(ct);
@@ -918,7 +918,7 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
 	case MVT_F64:
 		if (n != 8)
 		{
-			LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
+			LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
 		}
 #ifdef LL_BIG_ENDIAN
 		*(s + 7) = *(ct);
@@ -938,12 +938,12 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
 	case MVT_LLQuaternion:  // We only send x, y, z and infer w (we set x, y, z to ensure that w >= 0)
 		if (n != 12)
 		{
-			LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
+			LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
 		}
 #ifdef LL_BIG_ENDIAN
-		htonmemcpy(s + 8, ct + 8, MVT_F32, 4);
-		htonmemcpy(s + 4, ct + 4, MVT_F32, 4);
-		return(htonmemcpy(s, ct, MVT_F32, 4));
+		htolememcpy(s + 8, ct + 8, MVT_F32, 4);
+		htolememcpy(s + 4, ct + 4, MVT_F32, 4);
+		return(htolememcpy(s, ct, MVT_F32, 4));
 #else
 		return(memcpy(s,ct,n));	/* Flawfinder: ignore */ 
 #endif
@@ -951,12 +951,12 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
 	case MVT_LLVector3d:
 		if (n != 24)
 		{
-			LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
+			LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
 		}
 #ifdef LL_BIG_ENDIAN
-		htonmemcpy(s + 16, ct + 16, MVT_F64, 8);
-		htonmemcpy(s + 8, ct + 8, MVT_F64, 8);
-		return(htonmemcpy(s, ct, MVT_F64, 8));
+		htolememcpy(s + 16, ct + 16, MVT_F64, 8);
+		htolememcpy(s + 8, ct + 8, MVT_F64, 8);
+		return(htolememcpy(s, ct, MVT_F64, 8));
 #else
 		return(memcpy(s,ct,n));	/* Flawfinder: ignore */ 
 #endif
@@ -964,13 +964,13 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
 	case MVT_LLVector4:
 		if (n != 16)
 		{
-			LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
+			LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
 		}
 #ifdef LL_BIG_ENDIAN
-		htonmemcpy(s + 12, ct + 12, MVT_F32, 4);
-		htonmemcpy(s + 8, ct + 8, MVT_F32, 4);
-		htonmemcpy(s + 4, ct + 4, MVT_F32, 4);
-		return(htonmemcpy(s, ct, MVT_F32, 4));
+		htolememcpy(s + 12, ct + 12, MVT_F32, 4);
+		htolememcpy(s + 8, ct + 8, MVT_F32, 4);
+		htolememcpy(s + 4, ct + 4, MVT_F32, 4);
+		return(htolememcpy(s, ct, MVT_F32, 4));
 #else
 		return(memcpy(s,ct,n));	/* Flawfinder: ignore */ 
 #endif
@@ -978,12 +978,12 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
 	case MVT_U16Vec3:
 		if (n != 6)
 		{
-			LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
+			LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
 		}
 #ifdef LL_BIG_ENDIAN
-		htonmemcpy(s + 4, ct + 4, MVT_U16, 2);
-		htonmemcpy(s + 2, ct + 2, MVT_U16, 2);
-		return(htonmemcpy(s, ct, MVT_U16, 2));
+		htolememcpy(s + 4, ct + 4, MVT_U16, 2);
+		htolememcpy(s + 2, ct + 2, MVT_U16, 2);
+		return(htolememcpy(s, ct, MVT_U16, 2));
 #else
 		return(memcpy(s,ct,n));	/* Flawfinder: ignore */ 
 #endif
@@ -991,13 +991,13 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
 	case MVT_U16Quat:
 		if (n != 8)
 		{
-			LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
+			LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
 		}
 #ifdef LL_BIG_ENDIAN
-		htonmemcpy(s + 6, ct + 6, MVT_U16, 2);
-		htonmemcpy(s + 4, ct + 4, MVT_U16, 2);
-		htonmemcpy(s + 2, ct + 2, MVT_U16, 2);
-		return(htonmemcpy(s, ct, MVT_U16, 2));
+		htolememcpy(s + 6, ct + 6, MVT_U16, 2);
+		htolememcpy(s + 4, ct + 4, MVT_U16, 2);
+		htolememcpy(s + 2, ct + 2, MVT_U16, 2);
+		return(htolememcpy(s, ct, MVT_U16, 2));
 #else
 		return(memcpy(s,ct,n));	/* Flawfinder: ignore */ 
 #endif
@@ -1005,15 +1005,15 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
 	case MVT_S16Array:
 		if (n % 2)
 		{
-			LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
+			LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
 		}
 #ifdef LL_BIG_ENDIAN
 		length = n % 2;
 		for (i = 1; i < length; i++)
 		{
-			htonmemcpy(s + i*2, ct + i*2, MVT_S16, 2);
+			htolememcpy(s + i*2, ct + i*2, MVT_S16, 2);
 		}
-		return(htonmemcpy(s, ct, MVT_S16, 2));
+		return(htolememcpy(s, ct, MVT_S16, 2));
 #else
 		return(memcpy(s,ct,n));
 #endif
@@ -1025,7 +1025,7 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
 
 inline void *ntohmemcpy(void *s, const void *ct, EMsgVariableType type, size_t n)
 {
-	return(htonmemcpy(s,ct,type, n));
+	return(htolememcpy(s,ct,type, n));
 }
 
 inline const LLHost& LLMessageSystem::getReceivingInterface() const {return mLastReceivingIF;}
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 78b148381025a9c0c18ac9af79bb8edff91d8ffd..85197d1272713a88e34f0058443a133241bf0705 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -664,12 +664,14 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie
 	return result;
 }
 
-void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
+void LLPluginClassMedia::scrollEvent(int x, int y, int clicks_x, int clicks_y, MASK modifiers)
 {
 	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
 
 	message.setValueS32("x", x);
 	message.setValueS32("y", y);
+	message.setValueS32("clicks_x", clicks_x);
+	message.setValueS32("clicks_y", clicks_y);
 	message.setValue("modifiers", translateModifiers(modifiers));
 
 	sendMessage(message);
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 4f52afb31741dd72712014b0c8522b8a277b6f8c..9d11ee0421d92f4b2efdaa28a8f800195be9aaa4 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -118,7 +118,7 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 	
 	bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
 
-	void scrollEvent(int x, int y, MASK modifiers);
+	void scrollEvent(int x, int y, int clicks_x, int clicks_y, MASK modifiers);
 
 	// enable/disable media plugin debugging messages and info spam
 	void enableMediaPluginDebugging( bool enable );
diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp
index e24d222cb66e8eaf7063e1a4c785c74dcf7f7544..8fb3054eacec737720154e1c58190d45d8c58074 100644
--- a/indra/llplugin/llpluginprocesschild.cpp
+++ b/indra/llplugin/llpluginprocesschild.cpp
@@ -33,7 +33,7 @@
 #include "llpluginmessagepipe.h"
 #include "llpluginmessageclasses.h"
 
-static const F32 GOODBYE_SECONDS = 20.0f;
+static const F32 GOODBYE_SECONDS = 12.0f; // Do not set it to be bigger than mPluginLockupTimeout or parent will kill LLPluginProcessChild
 static const F32 HEARTBEAT_SECONDS = 1.0f;
 static const F32 PLUGIN_IDLE_SECONDS = 1.0f / 100.0f;  // Each call to idle will give the plugin this much time.
 
@@ -218,6 +218,11 @@ void LLPluginProcessChild::idle(void)
 			if (mWaitGoodbye.hasExpired())
 			{
 				LL_WARNS() << "Wait for goodbye expired.  Advancing to UNLOADED" << LL_ENDL;
+				if (mInstance != NULL)
+				{
+					// Something went wrong, at least make sure plugin will terminate
+					sendMessageToPlugin(LLPluginMessage("base", "force_exit"));
+				}
 				setState(STATE_UNLOADED);
 			}
 			break;
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index a0987b35d86270d3d86a62da71a7e567e424d40e..bc5dd62f457f69e6c25d8b25fe043aa62e3b5d10 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -1013,7 +1013,7 @@ S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_fa
 	U64 exception_faces;
 	U8 *start_loc = cur_ptr;
 
-	htonmemcpy(cur_ptr,data_ptr + (last_face_index * data_size), type, data_size);
+	htolememcpy(cur_ptr,data_ptr + (last_face_index * data_size), type, data_size);
 	cur_ptr += data_size;
 	
 	for (face_index = last_face_index-1; face_index >= 0; face_index--)
@@ -1072,7 +1072,7 @@ S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_fa
 			
 			*cur_ptr++ = (U8)(exception_faces & 0x7F);
 			
-			htonmemcpy(cur_ptr,data_ptr + (face_index * data_size), type, data_size);
+			htolememcpy(cur_ptr,data_ptr + (face_index * data_size), type, data_size);
 			cur_ptr += data_size;
    		}
 	}
@@ -1083,7 +1083,7 @@ S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 dat
 {
 	U8 *start_loc = cur_ptr;
 	U64 i;
-	htonmemcpy(data_ptr,cur_ptr, type,data_size);
+	htolememcpy(data_ptr,cur_ptr, type,data_size);
 	cur_ptr += data_size;
 
 	for (i = 1; i < face_count; i++)
@@ -1108,7 +1108,7 @@ S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 dat
 		{
 			if (i & 0x01)
 			{
-				htonmemcpy(data_ptr+(j*data_size),cur_ptr,type,data_size);
+				htolememcpy(data_ptr+(j*data_size),cur_ptr,type,data_size);
 				LL_DEBUGS("TEFieldDecode") << "Assigning " ;
 				char foo[64];
 				sprintf(foo,"%x %x",*(data_ptr+(j*data_size)), *(data_ptr+(j*data_size)+1));
diff --git a/indra/llprimitive/lltextureanim.cpp b/indra/llprimitive/lltextureanim.cpp
index 031a315d62273bf3c08fccc586b9e8a6d7ef4ca0..7c48e57a1a1a2eac954782bc624430df324e632f 100644
--- a/indra/llprimitive/lltextureanim.cpp
+++ b/indra/llprimitive/lltextureanim.cpp
@@ -94,9 +94,9 @@ void LLTextureAnim::packTAMessage(LLMessageSystem *mesgsys) const
 	data[1] = mFace;
 	data[2] = mSizeX;
 	data[3] = mSizeY;
-	htonmemcpy(data + 4, &mStart, MVT_F32, sizeof(F32));
-	htonmemcpy(data + 8, &mLength, MVT_F32, sizeof(F32));
-	htonmemcpy(data + 12, &mRate, MVT_F32, sizeof(F32));
+	htolememcpy(data + 4, &mStart, MVT_F32, sizeof(F32));
+	htolememcpy(data + 8, &mLength, MVT_F32, sizeof(F32));
+	htolememcpy(data + 12, &mRate, MVT_F32, sizeof(F32));
 
 	mesgsys->addBinaryDataFast(_PREHASH_TextureAnim, data, TA_BLOCK_SIZE);
 }
@@ -109,9 +109,9 @@ void LLTextureAnim::packTAMessage(LLDataPacker &dp) const
 	data[1] = mFace;
 	data[2] = mSizeX;
 	data[3] = mSizeY;
-	htonmemcpy(data + 4, &mStart, MVT_F32, sizeof(F32));
-	htonmemcpy(data + 8, &mLength, MVT_F32, sizeof(F32));
-	htonmemcpy(data + 12, &mRate, MVT_F32, sizeof(F32));
+	htolememcpy(data + 4, &mStart, MVT_F32, sizeof(F32));
+	htolememcpy(data + 8, &mLength, MVT_F32, sizeof(F32));
+	htolememcpy(data + 12, &mRate, MVT_F32, sizeof(F32));
 
 	dp.packBinaryData(data, TA_BLOCK_SIZE, "TextureAnimation");
 }
@@ -146,9 +146,9 @@ void LLTextureAnim::unpackTAMessage(LLMessageSystem *mesgsys, const S32 block_nu
 		mSizeX = llmax((U8)1, data[2]);
 		mSizeY = llmax((U8)1, data[3]);
 	}
-	htonmemcpy(&mStart, data + 4, MVT_F32, sizeof(F32));
-	htonmemcpy(&mLength, data + 8, MVT_F32, sizeof(F32));
-	htonmemcpy(&mRate, data + 12, MVT_F32, sizeof(F32));
+	htolememcpy(&mStart, data + 4, MVT_F32, sizeof(F32));
+	htolememcpy(&mLength, data + 8, MVT_F32, sizeof(F32));
+	htolememcpy(&mRate, data + 12, MVT_F32, sizeof(F32));
 }
 
 void LLTextureAnim::unpackTAMessage(LLDataPacker &dp)
@@ -170,9 +170,9 @@ void LLTextureAnim::unpackTAMessage(LLDataPacker &dp)
 	mFace = data[1];
 	mSizeX = data[2];
 	mSizeY = data[3];
-	htonmemcpy(&mStart, data + 4, MVT_F32, sizeof(F32));
-	htonmemcpy(&mLength, data + 8, MVT_F32, sizeof(F32));
-	htonmemcpy(&mRate, data + 12, MVT_F32, sizeof(F32));
+	htolememcpy(&mStart, data + 4, MVT_F32, sizeof(F32));
+	htolememcpy(&mLength, data + 8, MVT_F32, sizeof(F32));
+	htolememcpy(&mRate, data + 12, MVT_F32, sizeof(F32));
 }
 
 LLSD LLTextureAnim::asLLSD() const
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index c0f0cec80b2c5e9fc6d84a7d6b0113f980d7784e..bcc702d31f1590b03c7c3d495258276480f00e8e 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -49,6 +49,10 @@
 #include "llglheaders.h"
 #include "llglslshader.h"
 
+#if LL_WINDOWS
+#include "lldxhardware.h"
+#endif
+
 #ifdef _DEBUG
 //#define GL_STATE_VERIFY
 #endif
@@ -394,6 +398,8 @@ PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB = NULL;
 PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL;
 
 #if LL_WINDOWS
+PFNWGLGETGPUIDSAMDPROC				wglGetGPUIDsAMD = NULL;
+PFNWGLGETGPUINFOAMDPROC				wglGetGPUInfoAMD = NULL;
 PFNWGLSWAPINTERVALEXTPROC			wglSwapIntervalEXT = NULL;
 #endif
 
@@ -413,6 +419,7 @@ LLGLManager::LLGLManager() :
 
 	mHasMultitexture(FALSE),
 	mHasATIMemInfo(FALSE),
+	mHasAMDAssociations(FALSE),
 	mHasNVXMemInfo(FALSE),
 	mNumTextureUnits(1),
 	mHasMipMapGeneration(FALSE),
@@ -497,7 +504,16 @@ void LLGLManager::initWGL()
 	{
 		LL_WARNS("RenderInit") << "No ARB create context extensions" << LL_ENDL;
 	}
-	
+
+	// For retreiving information per AMD adapter, 
+	// because we can't trust curently selected/default one when there are multiple
+	mHasAMDAssociations = ExtensionExists("WGL_AMD_gpu_association", gGLHExts.mSysExts);
+	if (mHasAMDAssociations)
+	{
+		GLH_EXT_NAME(wglGetGPUIDsAMD) = (PFNWGLGETGPUIDSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUIDsAMD");
+		GLH_EXT_NAME(wglGetGPUInfoAMD) = (PFNWGLGETGPUINFOAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUInfoAMD");
+	}
+
 	if (ExtensionExists("WGL_EXT_swap_control", gGLHExts.mSysExts))
 	{
         GLH_EXT_NAME(wglSwapIntervalEXT) = (PFNWGLSWAPINTERVALEXTPROC)GLH_EXT_GET_PROC_ADDRESS("wglSwapIntervalEXT");
@@ -683,23 +699,78 @@ bool LLGLManager::initGL()
 	stop_glerror();
 
 	S32 old_vram = mVRAM;
+	mVRAM = 0;
 
-	if (mHasATIMemInfo)
+#if LL_WINDOWS
+	if (mHasAMDAssociations)
+	{
+		GLuint gl_gpus_count = wglGetGPUIDsAMD(0, 0);
+		if (gl_gpus_count > 0)
+		{
+			GLuint* ids = new GLuint[gl_gpus_count];
+			wglGetGPUIDsAMD(gl_gpus_count, ids);
+
+			GLuint mem_mb = 0;
+			for (U32 i = 0; i < gl_gpus_count; i++)
+			{
+				wglGetGPUInfoAMD(ids[i],
+					WGL_GPU_RAM_AMD,
+					GL_UNSIGNED_INT,
+					sizeof(GLuint),
+					&mem_mb);
+				if (mVRAM < mem_mb)
+				{
+					// basically pick the best AMD and trust driver/OS to know to switch
+					mVRAM = mem_mb;
+				}
+			}
+		}
+		if (mVRAM != 0)
+		{
+			LL_WARNS("RenderInit") << "VRAM Detected (AMDAssociations):" << mVRAM << LL_ENDL;
+		}
+	}
+#endif
+
+	if (mHasATIMemInfo && mVRAM == 0)
 	{ //ask the gl how much vram is free at startup and attempt to use no more than half of that
 		S32 meminfo[4];
 		glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
 
-		mVRAM = meminfo[0]/1024;
+		mVRAM = meminfo[0] / 1024;
+		LL_WARNS("RenderInit") << "VRAM Detected (ATIMemInfo):" << mVRAM << LL_ENDL;
 	}
-	else if (mHasNVXMemInfo)
+
+	if (mHasNVXMemInfo && mVRAM == 0)
 	{
 		S32 dedicated_memory;
 		glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &dedicated_memory);
 		mVRAM = dedicated_memory/1024;
+		LL_WARNS("RenderInit") << "VRAM Detected (NVXMemInfo):" << mVRAM << LL_ENDL;
 	}
 
+#if LL_WINDOWS
 	if (mVRAM < 256)
-	{ //something likely went wrong using the above extensions, fall back to old method
+	{
+		// Something likely went wrong using the above extensions
+		// try WMI first and fall back to old method (from dxdiag) if all else fails
+		// Function will check all GPUs WMI knows of and will pick up the one with most
+		// memory. We need to check all GPUs because system can switch active GPU to
+		// weaker one, to preserve power when not under load.
+		S32 mem = LLDXHardware::getMBVideoMemoryViaWMI();
+		if (mem != 0)
+		{
+			mVRAM = mem;
+			LL_WARNS("RenderInit") << "VRAM Detected (WMI):" << mVRAM<< LL_ENDL;
+		}
+	}
+#endif
+
+	if (mVRAM < 256 && old_vram > 0)
+	{
+		// fall back to old method
+		// Note: on Windows value will be from LLDXHardware.
+		// Either received via dxdiag or via WMI by id from dxdiag.
 		mVRAM = old_vram;
 	}
 
@@ -961,7 +1032,7 @@ void LLGLManager::initExtensions()
 	mHasTextureRectangle = FALSE;
 #else // LL_MESA_HEADLESS //important, gGLHExts.mSysExts is uninitialized until after glh_init_extensions is called
 	mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");
-	mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts);
+	mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts); //Basic AMD method, also see mHasAMDAssociations
 	mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts);
 	mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color");
 	mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic");
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 4c4302d05ba3e101c2cc6081ebe69b6fc428648a..6db1fe9c90a783120b64e4c5235257d0828bc4a4 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -78,6 +78,7 @@ class LLGLManager
 	// Extensions used by everyone
 	BOOL mHasMultitexture;
 	BOOL mHasATIMemInfo;
+	BOOL mHasAMDAssociations;
 	BOOL mHasNVXMemInfo;
 	S32	 mNumTextureUnits;
 	BOOL mHasMipMapGeneration;
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index 722dd9050bc1819fb31c72382226805e04f5593b..36fbb381bb13425096a5713b1e692298f96d6879 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -618,6 +618,8 @@ extern PFNGLVARIANTARRAYOBJECTATIPROC		glVariantObjectArrayATI;
 extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC	glGetVariantArrayObjectfvATI;
 extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC	glGetVariantArrayObjectivATI;
 
+extern PFNWGLGETGPUIDSAMDPROC				wglGetGPUIDsAMD;
+extern PFNWGLGETGPUINFOAMDPROC				wglGetGPUInfoAMD;
 extern PFNWGLSWAPINTERVALEXTPROC			wglSwapIntervalEXT;
 
 // GL_ARB_occlusion_query
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 42802cd339cfece764cf1f62079919bcef0ebb86..e3bb36192c907c3b1efed33ee4442b84d6b52d06 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -37,6 +37,7 @@
 #include "lluictrlfactory.h"
 #include "llbutton.h"
 #include "llcheckboxctrl.h"
+#include "llcriticaldamp.h" // LLSmoothInterpolation
 #include "lldir.h"
 #include "lldraghandle.h"
 #include "llfloaterreg.h"
@@ -64,6 +65,10 @@
 // use this to control "jumping" behavior when Ctrl-Tabbing
 const S32 TABBED_FLOATER_OFFSET = 0;
 
+const F32 LLFloater::CONTEXT_CONE_IN_ALPHA = 0.0f;
+const F32 LLFloater::CONTEXT_CONE_OUT_ALPHA = 1.f;
+const F32 LLFloater::CONTEXT_CONE_FADE_TIME = 0.08f;
+
 namespace LLInitParam
 {
 	void TypeValues<LLFloaterEnums::EOpenPositioning>::declareValues()
@@ -2116,6 +2121,70 @@ void LLFloater::updateTitleButtons()
 	}
 }
 
+void LLFloater::drawConeToOwner(F32 &context_cone_opacity,
+                                F32 max_cone_opacity,
+                                LLView *owner_view,
+                                F32 fade_time,
+                                F32 contex_cone_in_alpha,
+                                F32 contex_cone_out_alpha)
+{
+    if (owner_view
+        && owner_view->isInVisibleChain()
+        && hasFocus()
+        && context_cone_opacity > 0.001f
+        && gFocusMgr.childHasKeyboardFocus(this))
+    {
+        // draw cone of context pointing back to owner (e.x. texture swatch)
+        LLRect owner_rect;
+        owner_view->localRectToOtherView(owner_view->getLocalRect(), &owner_rect, this);
+        LLRect local_rect = getLocalRect();
+
+        gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+        LLGLEnable(GL_CULL_FACE);
+        gGL.begin(LLRender::QUADS);
+        {
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+            gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
+            gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+            gGL.vertex2i(local_rect.mRight, local_rect.mTop);
+            gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
+
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+            gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
+            gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+            gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
+            gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
+
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+            gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
+            gGL.vertex2i(local_rect.mRight, local_rect.mTop);
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+            gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
+            gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
+
+
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+            gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
+            gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+            gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
+            gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
+        }
+        gGL.end();
+    }
+
+    if (gFocusMgr.childHasMouseCapture(getDragHandle()))
+    {
+        context_cone_opacity = lerp(context_cone_opacity, max_cone_opacity, LLSmoothInterpolation::getInterpolant(fade_time));
+    }
+    else
+    {
+        context_cone_opacity = lerp(context_cone_opacity, 0.f, LLSmoothInterpolation::getInterpolant(fade_time));
+    }
+}
+
 void LLFloater::buildButtons(const Params& floater_params)
 {
 	static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0);
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 165f67499be11baeb175569e05c1c41e32599046..f8c04e8a2fc18c5e1a5d462c5edccfda12d2006c 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -395,6 +395,15 @@ class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater>
 
 	virtual void	updateTitleButtons();
 
+	// Draws a cone from this floater to parent floater or view (owner)
+	// Modifies context_cone_opacity (interpolates according to fade time and returns new value)
+	void			drawConeToOwner(F32 &context_cone_opacity,
+									F32 max_cone_opacity,
+									LLView *owner_view,
+									F32 context_fade_time = CONTEXT_CONE_FADE_TIME,
+									F32 contex_cone_in_alpha = CONTEXT_CONE_IN_ALPHA,
+									F32 contex_cone_out_alpha = CONTEXT_CONE_OUT_ALPHA);
+
 private:
 	void			setForeground(BOOL b);	// called only by floaterview
 	void			cleanupHandles(); // remove handles to dead floaters
@@ -424,6 +433,10 @@ class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater>
 	void			updateTransparency(LLView* view, ETypeTransparency transparency_type);
 
 public:
+	static const F32 CONTEXT_CONE_IN_ALPHA;
+	static const F32 CONTEXT_CONE_OUT_ALPHA;
+	static const F32 CONTEXT_CONE_FADE_TIME;
+
 	// Called when floater is opened, passes mKey
 	// Public so external views or floaters can watch for this floater opening
 	commit_signal_t mOpenSignal;
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 200dd2fdca6498230d441daad8aa5f1aa5ce1c6f..1e18396184162cc4d7f806df470e6bcc6efc2496 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -212,6 +212,12 @@ LLSD LLMenuItemGL::getValue() const
 	return getLabel();
 }
 
+//virtual
+bool LLMenuItemGL::hasAccelerator(const KEY &key, const MASK &mask) const
+{
+	return (mAcceleratorKey == key) && (mAcceleratorMask == mask);
+}
+
 //virtual
 BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)
 {
@@ -263,13 +269,13 @@ BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask)
 
 // This function checks to see if the accelerator key is already in use;
 // if not, it will be added to the list
-BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp)
+BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *listp)
 {
-	LLKeyBinding *accelerator = NULL;
+	LLMenuKeyboardBinding *accelerator = NULL;
 
 	if (mAcceleratorKey != KEY_NONE)
 	{
-		std::list<LLKeyBinding*>::iterator list_it;
+		std::list<LLMenuKeyboardBinding*>::iterator list_it;
 		for (list_it = listp->begin(); list_it != listp->end(); ++list_it)
 		{
 			accelerator = *list_it;
@@ -293,7 +299,7 @@ BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp)
 		}
 		if (!accelerator)
 		{				
-			accelerator = new LLKeyBinding;
+			accelerator = new LLMenuKeyboardBinding;
 			if (accelerator)
 			{
 				accelerator->mKey = mAcceleratorKey;
@@ -788,6 +794,12 @@ void LLMenuItemCallGL::initFromParams(const Params& p)
 			{
 				setEnabledControlVariable(control);
 			}
+			else
+			{
+				LL_WARNS() << "Failed to assign 'enabled' control variable to menu " << getName()
+							<< ": control " << p.on_enable.control_name()
+							<< " does not exist." << LL_ENDL;
+			}
 		}
 	}
 	if (p.on_click.isProvided())
@@ -1011,6 +1023,11 @@ BOOL LLMenuItemBranchGL::handleMouseUp(S32 x, S32 y, MASK mask)
 	return TRUE;
 }
 
+bool LLMenuItemBranchGL::hasAccelerator(const KEY &key, const MASK &mask) const
+{
+	return getBranch() && getBranch()->hasAccelerator(key, mask);
+}
+
 BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)
 {
 	return getBranch() && getBranch()->handleAcceleratorKey(key, mask);
@@ -1018,7 +1035,7 @@ BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)
 
 // This function checks to see if the accelerator key is already in use;
 // if not, it will be added to the list
-BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list<LLKeyBinding*> *listp)
+BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list<LLMenuKeyboardBinding*> *listp)
 {
 	LLMenuGL* branch = getBranch();
 	if (!branch)
@@ -2995,6 +3012,27 @@ void LLMenuGL::updateParent(LLView* parentp)
 	}
 }
 
+bool LLMenuGL::hasAccelerator(const KEY &key, const MASK &mask) const
+{
+	if (key == KEY_NONE)
+	{
+		return false;
+	}
+	// Note: checking this way because mAccelerators seems to be broken
+	// mAccelerators probably needs to be cleaned up or fixed
+	// It was used for dupplicate accelerator avoidance.
+	item_list_t::const_iterator item_iter;
+	for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
+	{
+		LLMenuItemGL* itemp = *item_iter;
+		if (itemp->hasAccelerator(key, mask))
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
 BOOL LLMenuGL::handleAcceleratorKey(KEY key, MASK mask)
 {
 	// don't handle if not enabled
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 78f688642ea5d0a57b746b21811abe7c1a11b7ca..f3844af507439bf6f699e310c6050e86f3f2a341 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -42,6 +42,13 @@
 extern S32 MENU_BAR_HEIGHT;
 extern S32 MENU_BAR_WIDTH;
 
+class LLMenuKeyboardBinding
+{
+public:
+    KEY				mKey;
+    MASK			mMask;
+};
+
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLMenuItemGL
 //
@@ -91,6 +98,7 @@ class LLMenuItemGL: public LLUICtrl, public ll::ui::SearchableControl
 	/*virtual*/ void setValue(const LLSD& value);
 	/*virtual*/ LLSD getValue() const;
 
+	virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
 	virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
 
 	LLColor4 getHighlightBgColor() { return mHighlightBackground.get(); }
@@ -109,7 +117,7 @@ class LLMenuItemGL: public LLUICtrl, public ll::ui::SearchableControl
 	virtual void setBriefItem(BOOL brief);
 	virtual BOOL isBriefItem() const;
 
-	virtual BOOL addToAcceleratorList(std::list<LLKeyBinding*> *listp);
+	virtual BOOL addToAcceleratorList(std::list<LLMenuKeyboardBinding*> *listp);
 	void setAllowKeyRepeat(BOOL allow) { mAllowKeyRepeat = allow; }
 	BOOL getAllowKeyRepeat() const { return mAllowKeyRepeat; }
 
@@ -436,7 +444,8 @@ class LLMenuGL
 	/*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
 	/*virtual*/ void removeChild( LLView* ctrl);
 	/*virtual*/ BOOL postBuild();
-
+	
+	virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
 	virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
 
 	LLMenuGL* findChildMenuByName(const std::string& name, BOOL recurse) const;
@@ -625,10 +634,11 @@ class LLMenuItemBranchGL : public LLMenuItemGL
 	
 	virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
 
+	virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
 	virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
 
 	// check if we've used these accelerators already
-	virtual BOOL addToAcceleratorList(std::list <LLKeyBinding*> *listp);
+	virtual BOOL addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *listp);
 
 	// called to rebuild the draw label
 	virtual void buildDrawLabel( void );
@@ -794,7 +804,7 @@ class LLMenuBarGL : public LLMenuGL
 
 	void checkMenuTrigger();
 
-	std::list <LLKeyBinding*>	mAccelerators;
+	std::list <LLMenuKeyboardBinding*>	mAccelerators;
 	BOOL						mAltKeyTrigger;
 };
 
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 9fc6c05ead9d5a70dcf1a52ff6c396432e2c1826..6a7075301bea873a472c71d21fb0538d79ae1d49 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -68,7 +68,8 @@ LLNotificationForm::FormIgnore::FormIgnore()
 	control("control"),
 	invert_control("invert_control", false),
 	save_option("save_option", false),
-	session_only("session_only", false)
+	session_only("session_only", false),
+	checkbox_only("checkbox_only", false)
 {}
 
 LLNotificationForm::FormButton::FormButton()
@@ -195,10 +196,15 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica
 {
 	if (p.ignore.isProvided())
 	{
+		// For all cases but IGNORE_CHECKBOX_ONLY this is name for use in preferences
 		mIgnoreMsg = p.ignore.text;
 
 		LLUI *ui_inst = LLUI::getInstance();
-		if (!p.ignore.save_option)
+		if (p.ignore.checkbox_only)
+		{
+			mIgnore = IGNORE_CHECKBOX_ONLY;
+		}
+		else if (!p.ignore.save_option)
 		{
 			mIgnore = p.ignore.session_only ? IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY : IGNORE_WITH_DEFAULT_RESPONSE;
 		}
@@ -215,7 +221,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica
 			mIgnoreSetting = ui_inst->mSettingGroups["config"]->getControl(p.ignore.control);
 			mInvertSetting = p.ignore.invert_control;
 		}
-		else
+		else if (mIgnore > IGNORE_NO)
 		{
 			ui_inst->mSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", LLControlVariable::PERSIST_NONDFT);
 			mIgnoreSetting = ui_inst->mSettingGroups["ignores"]->getControl(name);
@@ -389,13 +395,12 @@ LLControlVariablePtr LLNotificationForm::getIgnoreSetting()
 bool LLNotificationForm::getIgnored()
 {
 	bool show = true;
-	if (mIgnore != LLNotificationForm::IGNORE_NO
+	if (mIgnore > LLNotificationForm::IGNORE_NO
 		&& mIgnoreSetting) 
 	{
 		show = mIgnoreSetting->getValue().asBoolean();
 		if (mInvertSetting) show = !show;
 	}
-
 	return !show;
 }
 
@@ -696,7 +701,7 @@ void LLNotification::respond(const LLSD& response)
 		mTemporaryResponder = false;
 	}
 
-	if (mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
+	if (mForm->getIgnoreType() > LLNotificationForm::IGNORE_NO)
 	{
 		mForm->setIgnored(mIgnored);
 		if (mIgnored && mForm->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 15094469208151af209dd380ae03503842edc111..62cf41256bfd3984837f2ab7252114fd3df77158 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -180,6 +180,7 @@ class LLNotificationForm
 		Optional<std::string>	control;
 		Optional<bool>			invert_control;
 		Optional<bool>			session_only;
+		Optional<bool>			checkbox_only;
 
 		FormIgnore();
 	};
@@ -232,7 +233,8 @@ class LLNotificationForm
 
 	typedef enum e_ignore_type
 	{ 
-		IGNORE_NO,
+		IGNORE_CHECKBOX_ONLY = -1, // ignore won't be handled, will set value/checkbox only
+		IGNORE_NO = 0,
 		IGNORE_WITH_DEFAULT_RESPONSE,
 		IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY,
 		IGNORE_WITH_LAST_RESPONSE, 
diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp
index b3a79bc1ebf4475549c522d1c26a92aaed4f2a2d..fde6de49219bc6acc031d1293bf462ac054651fd 100644
--- a/indra/llui/llscrollbar.cpp
+++ b/indra/llui/llscrollbar.cpp
@@ -408,6 +408,16 @@ BOOL LLScrollbar::handleScrollWheel(S32 x, S32 y, S32 clicks)
 	return handled;
 }
 
+BOOL LLScrollbar::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+	BOOL handled = FALSE;
+	if (LLScrollbar::HORIZONTAL == mOrientation)
+	{
+		handled = changeLine(clicks * mStepSize, TRUE);
+	}
+	return handled;
+}
+
 BOOL LLScrollbar::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/llui/llscrollbar.h b/indra/llui/llscrollbar.h
index e2bf52c14bce6463fef574a699f73b324a2a81e2..5f2f490d811884d2b3d6fe14bd5151dd5312d0d9 100644
--- a/indra/llui/llscrollbar.h
+++ b/indra/llui/llscrollbar.h
@@ -88,6 +88,7 @@ class LLScrollbar
 	virtual BOOL	handleDoubleClick(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleHover(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleScrollWheel(S32 x, S32 y, S32 clicks);
+	virtual BOOL	handleScrollHWheel(S32 x, S32 y, S32 clicks);
 	virtual BOOL	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/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index 6135cc56ad76197ed382d254134293613f25ac60..3db38bbfacf56e2bb6bee810757771fd7041427f 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -272,6 +272,25 @@ BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks )
 	return FALSE;
 }
 
+BOOL LLScrollContainer::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+	if (LLUICtrl::handleScrollHWheel(x,y,clicks))
+	{
+		return TRUE;
+	}
+
+	LLScrollbar* horizontal = mScrollbar[HORIZONTAL];
+	if (horizontal->getVisible()
+		&& horizontal->getEnabled()
+		&& horizontal->handleScrollHWheel( 0, 0, clicks ) )
+	{
+		updateScroll();
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
 BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask,
 												  BOOL drop,
 												  EDragAndDropType cargo_type,
diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h
index e6c78913975c706a80e40e4fe22dec603c1ef354..c14099dbd5361f409905827eb5269396f72d37e2 100644
--- a/indra/llui/llscrollcontainer.h
+++ b/indra/llui/llscrollcontainer.h
@@ -107,6 +107,7 @@ class LLScrollContainer : public LLUICtrl
 	virtual BOOL	handleKeyHere(KEY key, MASK mask);
 	virtual BOOL	handleUnicodeCharHere(llwchar uni_char);
 	virtual BOOL	handleScrollWheel( S32 x, S32 y, S32 clicks );
+	virtual BOOL	handleScrollHWheel( S32 x, S32 y, S32 clicks );
 	virtual BOOL	handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 								   EDragAndDropType cargo_type,
 								   void* cargo_data,
diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp
index 8000efad0e2c31927092168f7c90e283707b66bf..13839da400e504f3e369d034cf916e9d6c163eec 100644
--- a/indra/llui/llscrolllistcell.cpp
+++ b/indra/llui/llscrolllistcell.cpp
@@ -50,6 +50,10 @@ LLScrollListCell* LLScrollListCell::create(const LLScrollListCell::Params& cell_
 	{
 		cell = new LLScrollListDate(cell_p);
 	}
+	else if (cell_p.type() == "icontext")
+	{
+		cell = new LLScrollListIconText(cell_p);
+	}
 	else	// default is "text"
 	{
 		cell = new LLScrollListText(cell_p);
@@ -168,7 +172,7 @@ U32 LLScrollListText::sCount = 0;
 
 LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
 :	LLScrollListCell(p),
-	mText(p.value().asString()),
+	mText(p.label.isProvided() ? p.label() : p.value().asString()),
 	mFont(p.font),
 	mColor(p.color),
 	mUseColor(p.color.isProvided()),
@@ -192,7 +196,7 @@ LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
 void LLScrollListText::highlightText(S32 offset, S32 num_chars)
 {
 	mHighlightOffset = offset;
-	mHighlightCount = num_chars;
+	mHighlightCount = llmax(0, num_chars);
 }
 
 //virtual 
@@ -292,11 +296,12 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
 
 	if (mHighlightCount > 0)
 	{
+		// Highlight text
 		S32 left = 0;
 		switch(mFontAlignment)
 		{
 		case LLFontGL::LEFT:
-			left = mFont->getWidth(mText.getString(), 0, mHighlightOffset);
+			left = mFont->getWidth(mText.getString(), 1, mHighlightOffset);
 			break;
 		case LLFontGL::RIGHT:
 			left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX);
@@ -319,7 +324,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
 	switch(mFontAlignment)
 	{
 	case LLFontGL::LEFT:
-		start_x = 0.f;
+		start_x = 1.f;
 		break;
 	case LLFontGL::RIGHT:
 		start_x = (F32)getWidth();
@@ -435,3 +440,139 @@ const LLSD LLScrollListDate::getValue() const
 {
 	return mDate;
 }
+
+//
+// LLScrollListIconText
+//
+LLScrollListIconText::LLScrollListIconText(const LLScrollListCell::Params& p)
+    : LLScrollListText(p),
+    mIcon(p.value().isUUID() ? LLUI::getUIImageByID(p.value().asUUID()) : LLUI::getUIImage(p.value().asString())),
+    mPad(4)
+{
+    mTextWidth = getWidth() - mPad /*padding*/ - mFont->getLineHeight();
+}
+
+LLScrollListIconText::~LLScrollListIconText()
+{
+}
+
+const LLSD LLScrollListIconText::getValue() const
+{
+    if (mIcon.isNull())
+    {
+        return LLStringUtil::null;
+    }
+    return mIcon->getName();
+}
+
+void LLScrollListIconText::setValue(const LLSD& value)
+{
+    if (value.isUUID())
+    {
+        // don't use default image specified by LLUUID::null, use no image in that case
+        LLUUID image_id = value.asUUID();
+        mIcon = image_id.notNull() ? LLUI::getUIImageByID(image_id) : LLUIImagePtr(NULL);
+    }
+    else
+    {
+        std::string value_string = value.asString();
+        if (LLUUID::validate(value_string))
+        {
+            setValue(LLUUID(value_string));
+        }
+        else if (!value_string.empty())
+        {
+            mIcon = LLUI::getUIImage(value.asString());
+        }
+        else
+        {
+            mIcon = NULL;
+        }
+    }
+}
+
+void LLScrollListIconText::setWidth(S32 width)
+{
+    LLScrollListCell::setWidth(width);
+    // Assume that iamge height and width is identical to font height and width
+    mTextWidth = width - mPad /*padding*/ - mFont->getLineHeight();
+}
+
+
+void LLScrollListIconText::draw(const LLColor4& color, const LLColor4& highlight_color)	 const
+{
+    LLColor4 display_color;
+    if (mUseColor)
+    {
+        display_color = mColor;
+    }
+    else
+    {
+        display_color = color;
+    }
+
+    S32 icon_height = mFont->getLineHeight();
+    S32 icon_space = mIcon ? (icon_height + mPad) : 0;
+
+    if (mHighlightCount > 0)
+    {
+        S32 left = 0;
+        switch (mFontAlignment)
+        {
+        case LLFontGL::LEFT:
+            left = mFont->getWidth(mText.getString(), icon_space + 1, mHighlightOffset);
+            break;
+        case LLFontGL::RIGHT:
+            left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX) - icon_space;
+            break;
+        case LLFontGL::HCENTER:
+            left = (getWidth() - mFont->getWidth(mText.getString()) - icon_space) / 2;
+            break;
+        }
+        LLRect highlight_rect(left - 2,
+            mFont->getLineHeight() + 1,
+            left + mFont->getWidth(mText.getString(), mHighlightOffset, mHighlightCount) + 1,
+            1);
+        mRoundedRectImage->draw(highlight_rect, highlight_color);
+    }
+
+    // Try to draw the entire string
+    F32 right_x;
+    U32 string_chars = mText.length();
+    F32 start_text_x = 0.f;
+    S32 start_icon_x = 0;
+    switch (mFontAlignment)
+    {
+    case LLFontGL::LEFT:
+        start_text_x = icon_space + 1;
+        start_icon_x = 1;
+        break;
+    case LLFontGL::RIGHT:
+        start_text_x = (F32)getWidth();
+        start_icon_x = getWidth() - mFont->getWidth(mText.getString()) - icon_space;
+        break;
+    case LLFontGL::HCENTER:
+        F32 center = (F32)getWidth()* 0.5f;
+        start_text_x = center + ((F32)icon_space * 0.5f);
+        start_icon_x = center - (((F32)icon_space + mFont->getWidth(mText.getString())) * 0.5f);
+        break;
+    }
+    mFont->render(mText.getWString(), 0,
+        start_text_x, 0.f,
+        display_color,
+        mFontAlignment,
+        LLFontGL::BOTTOM,
+        0,
+        LLFontGL::NO_SHADOW,
+        string_chars,
+        getTextWidth(),
+        &right_x,
+        TRUE);
+
+    if (mIcon)
+    {
+        mIcon->draw(start_icon_x, 0, icon_height, icon_height, mColor);
+    }
+}
+
+
diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h
index d625ebddccacc025f33671fe40a765ac32c22b73..19576fb247adf131a06e44c6e34cb06dbf74f368 100644
--- a/indra/llui/llscrolllistcell.h
+++ b/indra/llui/llscrolllistcell.h
@@ -59,7 +59,8 @@ class LLScrollListCell
 									visible;
 
 		Optional<void*>				userdata;
-		Optional<LLSD>				value;
+		Optional<LLSD>				value; // state of checkbox, icon id/name, date
+		Optional<std::string>		label; // description or text
 		Optional<std::string>		tool_tip;
 
 		Optional<const LLFontGL*>	font;
@@ -75,6 +76,7 @@ class LLScrollListCell
 			enabled("enabled", true),
 			visible("visible", true),
 			value("value"),
+			label("label"),
 			tool_tip("tool_tip", ""),
 			font("font", LLFontGL::getFontSansSerifSmall()),
 			font_color("font_color", LLColor4::black),
@@ -152,11 +154,12 @@ class LLScrollListText : public LLScrollListCell
 	void			setText(const LLStringExplicit& text);
 	void			setFontStyle(const U8 font_style);
 
-private:
+protected:
 	LLUIString		mText;
 	S32				mTextWidth;
 	const LLFontGL*	mFont;
 	LLColor4		mColor;
+	LLColor4		mHighlightColor;
 	U8				mUseColor;
 	LLFontGL::HAlign mFontAlignment;
 	BOOL			mVisible;
@@ -169,7 +172,7 @@ class LLScrollListText : public LLScrollListCell
 };
 
 /*
- * Cell displaying an image.
+ * Cell displaying an image. AT the moment, this is specifically UI image
  */
 class LLScrollListIcon : public LLScrollListCell
 {
@@ -223,4 +226,26 @@ class LLScrollListDate : public LLScrollListText
 	LLDate		mDate;
 };
 
+/*
+* Cell displaying icon and text.
+*/
+
+class LLScrollListIconText : public LLScrollListText
+{
+public:
+    LLScrollListIconText(const LLScrollListCell::Params& p);
+    /*virtual*/ ~LLScrollListIconText();
+    /*virtual*/ void	draw(const LLColor4& color, const LLColor4& highlight_color) const;
+    /*virtual*/ const LLSD		getValue() const;
+    /*virtual*/ void	setValue(const LLSD& value);
+
+
+    S32					getIconWidth() const;
+    /*virtual*/ void	setWidth(S32 width);/* { LLScrollListCell::setWidth(width); mTextWidth = width - ; }*/
+
+private:
+    LLPointer<LLUIImage>	mIcon;
+    S32						mPad;
+};
+
 #endif
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index f4028057e8565b66078f4b9abc706c30910923e4..94b130e28d6fcd17d4d0ad75e8043633333c4ed2 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -115,6 +115,13 @@ struct SortScrollListItem
 // LLScrollListCtrl
 //---------------------------------------------------------------------------
 
+void LLScrollListCtrl::SelectionTypeNames::declareValues()
+{
+    declare("row", LLScrollListCtrl::ROW);
+    declare("cell", LLScrollListCtrl::CELL);
+    declare("header", LLScrollListCtrl::HEADER);
+}
+
 LLScrollListCtrl::Contents::Contents()
 :	columns("column"),
 	rows("row")
@@ -128,8 +135,10 @@ LLScrollListCtrl::Params::Params()
 	has_border("draw_border"),
 	draw_heading("draw_heading"),
 	search_column("search_column", 0),
+	selection_type("selection_type", ROW),
 	sort_column("sort_column", -1),
 	sort_ascending("sort_ascending", true),
+	can_sort("can_sort", true),
 	mouse_wheel_opaque("mouse_wheel_opaque", false),
 	commit_on_keyboard_movement("commit_on_keyboard_movement", true),
 	heading_height("heading_height"),
@@ -163,8 +172,10 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
 	mCommitOnKeyboardMovement(p.commit_on_keyboard_movement),
 	mCommitOnSelectionChange(false),
 	mSelectionChanged(false),
+	mSelectionType(p.selection_type),
 	mNeedsScroll(false),
 	mCanSelect(true),
+	mCanSort(p.can_sort),
 	mColumnsDirty(false),
 	mMaxItemCount(INT_MAX), 
 	mBorderThickness( 2 ),
@@ -819,7 +830,15 @@ BOOL LLScrollListCtrl::selectFirstItem()
 		{
 			if (!itemp->getSelected())
 			{
-				selectItem(itemp);
+                switch (mSelectionType)
+                {
+                case CELL:
+                    selectItem(itemp, 0);
+                    break;
+                case HEADER:
+                case ROW:
+                    selectItem(itemp, -1);
+                }
 			}
 			success = TRUE;
 			mOriginalSelection = 0;
@@ -878,7 +897,8 @@ BOOL LLScrollListCtrl::selectItemRange( S32 first_index, S32 last_index )
 		{
 			if( itemp->getEnabled() )
 			{
-				selectItem(itemp, FALSE);
+				// TODO: support range selection for cells
+				selectItem(itemp, -1, FALSE);
 				success = TRUE;				
 			}
 		}
@@ -1004,10 +1024,14 @@ void LLScrollListCtrl::clearHighlightedItems()
 
 void LLScrollListCtrl::mouseOverHighlightNthItem(S32 target_index)
 {
-	if (mHighlightedItem != target_index)
-	{
-		mHighlightedItem = target_index;
-	}
+    if (mHighlightedItem != target_index)
+    {
+        if (mHighlightedItem >= 0 && mHighlightedItem < mItemList.size())
+        {
+            mItemList[mHighlightedItem]->setHoverCell(-1);
+        }
+        mHighlightedItem = target_index;
+    }
 }
 
 S32	LLScrollListCtrl::selectMultiple( uuid_vec_t ids )
@@ -1022,7 +1046,8 @@ S32	LLScrollListCtrl::selectMultiple( uuid_vec_t ids )
 		{
 			if (item->getEnabled() && (item->getUUID() == (*iditr)))
 			{
-				selectItem(item,FALSE);
+				// TODO: support multiple selection for cells
+				selectItem(item, -1, FALSE);
 				++count;
 				break;
 			}
@@ -1095,7 +1120,7 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection)
 			{
 				if (prev_item)
 				{
-					selectItem(prev_item, !extend_selection);
+					selectItem(prev_item, cur_item->getSelectedCell(), !extend_selection);
 				}
 				else
 				{
@@ -1139,7 +1164,7 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection)
 			{
 				if (next_item)
 				{
-					selectItem(next_item, !extend_selection);
+					selectItem(next_item, cur_item->getSelectedCell(), !extend_selection);
 				}
 				else
 				{
@@ -1210,7 +1235,7 @@ BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sen
 	bool found = NULL != item;
 	if(found)
 	{
-		selectItem(item);
+		selectItem(item, -1);
 	}
 
 	if (mCommitOnSelectionChange)
@@ -1278,7 +1303,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
 			BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE;
 			if (select)
 			{
-				selectItem(item);
+				selectItem(item, -1);
 				found = TRUE;
 				break;
 			}
@@ -1318,7 +1343,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
 				// find offset of matching text (might have leading whitespace)
 				S32 offset = item_label.find(target_trimmed);
 				cellp->highlightText(offset, target_trimmed.size());
-				selectItem(item);
+				selectItem(item, -1);
 				found = TRUE;
 				break;
 			}
@@ -1384,7 +1409,7 @@ BOOL LLScrollListCtrl::setSelectedByValue(const LLSD& value, BOOL selected)
 		{
 			if (selected)
 			{
-				selectItem(item);
+				selectItem(item, -1);
 			}
 			else
 			{
@@ -1464,7 +1489,7 @@ void LLScrollListCtrl::drawItems()
 		
 		S32 max_columns = 0;
 
-		LLColor4 highlight_color = LLColor4::white;
+		LLColor4 highlight_color = LLColor4::white; // ex: text inside cells
 		static LLUICachedControl<F32> type_ahead_timeout ("TypeAheadTimeout", 0);
 		highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout(), 0.4f, 0.f);
 
@@ -1490,7 +1515,8 @@ void LLScrollListCtrl::drawItems()
 			max_columns = llmax(max_columns, item->getNumColumns());
 
 			LLColor4 fg_color;
-			LLColor4 bg_color(LLColor4::transparent);
+			LLColor4 hover_color(LLColor4::transparent);
+			LLColor4 select_color(LLColor4::transparent);
 
 			if( mScrollLines <= line && line < mScrollLines + num_page_lines )
 			{
@@ -1499,44 +1525,44 @@ void LLScrollListCtrl::drawItems()
 				{
 					if(item->getHighlighted())	// if it's highlighted, average the colors
 					{
-						bg_color = lerp(mBgSelectedColor.get(), mHighlightedColor.get(), 0.5f);
+						select_color = lerp(mBgSelectedColor.get(), mHighlightedColor.get(), 0.5f);
 					}
 					else						// otherwise just select-highlight it
 					{
-						bg_color = mBgSelectedColor.get();
+						select_color = mBgSelectedColor.get();
 					}
 
 					fg_color = (item->getEnabled() ? mFgSelectedColor.get() : mFgDisabledColor.get());
 				}
-				else if (mHighlightedItem == line && mCanSelect)
+				if (mHighlightedItem == line && mCanSelect)
 				{
 					if(item->getHighlighted())	// if it's highlighted, average the colors
 					{
-						bg_color = lerp(mHoveredColor.get(), mHighlightedColor.get(), 0.5f);
+						hover_color = lerp(mHoveredColor.get(), mHighlightedColor.get(), 0.5f);
 					}
 					else						// otherwise just hover-highlight it
 					{
-						bg_color = mHoveredColor.get();
+						hover_color = mHoveredColor.get();
 					}
 				}
 				else if (item->getHighlighted())
 				{
-					bg_color = mHighlightedColor.get();
+					hover_color = mHighlightedColor.get();
 				}
 				else 
 				{
 					if (mDrawStripes && (line % 2 == 0) && (max_columns > 1))
 					{
-						bg_color = mBgStripeColor.get();
+						hover_color = mBgStripeColor.get();
 					}
 				}
 
 				if (!item->getEnabled())
 				{
-					bg_color = mBgReadOnlyColor.get();
+					hover_color = mBgReadOnlyColor.get();
 				}
 
-				item->draw(item_rect, fg_color % alpha, bg_color% alpha, highlight_color % alpha, mColumnPadding);
+				item->draw(item_rect, fg_color % alpha, hover_color% alpha, select_color% alpha, highlight_color % alpha, mColumnPadding);
 
 				cur_y -= mLineHeight;
 			}
@@ -1601,6 +1627,20 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks)
 	return handled;
 }
 
+BOOL LLScrollListCtrl::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+	BOOL handled = FALSE;
+	// Pretend the mouse is over the scrollbar
+	handled = mScrollbar->handleScrollHWheel( 0, 0, clicks );
+
+	if (mMouseWheelOpaque)
+	{
+		return TRUE;
+	}
+
+	return handled;
+}
+
 // *NOTE: Requires a valid row_index and column_index
 LLRect LLScrollListCtrl::getCellRect(S32 row_index, S32 column_index)
 {
@@ -1674,7 +1714,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
 			{
 				if (mLastSelected == NULL)
 				{
-					selectItem(hit_item);
+					selectItem(hit_item, getColumnIndexFromOffset(x));
 				}
 				else
 				{
@@ -1698,7 +1738,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
 						LLScrollListItem *item = *itor;
                         if (item == hit_item || item == lastSelected)
 						{
-							selectItem(item, FALSE);
+							selectItem(item, getColumnIndexFromOffset(x), FALSE);
 							selecting = !selecting;
 							if (hit_item == lastSelected)
 							{
@@ -1708,7 +1748,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
 						}
 						if (selecting)
 						{
-							selectItem(item, FALSE);
+							selectItem(item, getColumnIndexFromOffset(x), FALSE);
 						}
 					}
 				}
@@ -1723,7 +1763,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
 				{
 					if(!(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable))
 					{
-						selectItem(hit_item, FALSE);
+						selectItem(hit_item, getColumnIndexFromOffset(x), FALSE);
 					}
 					else
 					{
@@ -1737,12 +1777,12 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
 			else
 			{
 				deselectAllItems(TRUE);
-				selectItem(hit_item);
+				selectItem(hit_item, getColumnIndexFromOffset(x));
 			}
 		}
 		else
 		{
-			selectItem(hit_item);
+			selectItem(hit_item, getColumnIndexFromOffset(x));
 		}
 
 		selection_changed = mSelectionChanged;
@@ -2110,8 +2150,29 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
 	{
 		LLScrollListItem* item = hitItem(x, y);
 		if (item)
-		{
-			mouseOverHighlightNthItem(getItemIndex(item));
+        {
+            mouseOverHighlightNthItem(getItemIndex(item));
+            switch (mSelectionType)
+            {
+            case CELL:
+                item->setHoverCell(getColumnIndexFromOffset(x));
+                break;
+            case HEADER:
+                {
+                    S32 cell = getColumnIndexFromOffset(x);
+                    if (cell > 0)
+                    {
+                        item->setHoverCell(cell);
+                    }
+                    else
+                    {
+                        item->setHoverCell(-1);
+                    }
+                    break;
+                }
+            case ROW:
+                break;
+            }
 		}
 		else
 		{
@@ -2159,6 +2220,52 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask )
 					handled = TRUE;
 				}
 				break;
+            case KEY_LEFT:
+                if (mAllowKeyboardMovement || hasFocus())
+                {
+                    // TODO: support multi-select
+                    LLScrollListItem *item = getFirstSelected();
+                    S32 cell = item->getSelectedCell();
+                    switch (mSelectionType)
+                    {
+                    case CELL:
+                        if (cell < mColumns.size()) cell++;
+                        break;
+                    case HEADER:
+                        if (cell == -1) cell = 1;
+                        else if (cell > 1 && cell < mColumns.size()) cell++; // skip header
+                        break;
+                    case ROW:
+                        cell = -1;
+                        break;
+                    }
+                    item->setSelectedCell(cell);
+                    handled = TRUE;
+                }
+                break;
+            case KEY_RIGHT:
+                if (mAllowKeyboardMovement || hasFocus())
+                {
+                    // TODO: support multi-select
+                    LLScrollListItem *item = getFirstSelected();
+                    S32 cell = item->getSelectedCell();
+                    switch (mSelectionType)
+                    {
+                    case CELL:
+                        if (cell >= 0) cell--;
+                        break;
+                    case HEADER:
+                        if (cell > 1) cell--;
+                        else if (cell == 1) cell = -1; // skip header
+                        break;
+                    case ROW:
+                        cell = -1;
+                        break;
+                    }
+                    item->setSelectedCell(cell);
+                    handled = TRUE;
+                }
+                break;
 			case KEY_PAGE_UP:
 				if (mAllowKeyboardMovement || hasFocus())
 				{
@@ -2327,7 +2434,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char)
 				LLWString item_label = utf8str_to_wstring(cellp->getValue().asString());
 				if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char)
 				{
-					selectItem(item);
+					selectItem(item, -1);
 					mNeedsScroll = true;
 					cellp->highlightText(0, 1);
 					mSearchTimer.reset();
@@ -2379,7 +2486,7 @@ BOOL LLScrollListCtrl::isRepeatedChars(const LLWString& string) const
 	return TRUE;
 }
 
-void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_item)
+void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, S32 cell, BOOL select_single_item)
 {
 	if (!itemp) return;
 
@@ -2398,6 +2505,18 @@ void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_it
 			deselectAllItems(TRUE);
 		}
 		itemp->setSelected(TRUE);
+        switch (mSelectionType)
+        {
+        case CELL:
+            itemp->setSelectedCell(cell);
+            break;
+        case HEADER:
+            itemp->setSelectedCell(cell <= 0 ? -1 : cell);
+            break;
+        case ROW:
+            itemp->setSelectedCell(-1);
+            break;
+        }
 		mLastSelected = itemp;
 		mSelectionChanged = true;
 	}
@@ -2658,7 +2777,7 @@ void	LLScrollListCtrl::selectAll()
 		LLScrollListItem *itemp = *iter;
 		if( itemp->getEnabled() )
 		{
-			selectItem(itemp, FALSE);
+			selectItem(itemp, -1, FALSE);
 		}
 	}
 
@@ -2787,6 +2906,8 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
 	LLScrollListCtrl *parent = info->mParentCtrl;
 	if (!parent) return;
 
+	if (!parent->mCanSort) return;
+
 	S32 column_index = info->mIndex;
 
 	LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex];
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index b35a8608e70d82e2b9ec8f9ab7fb0d764ad329b2..bf1055c8dc07e8e5a4ed0224ac8ce349ddd20ddd 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -54,6 +54,18 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	public LLCtrlListInterface, public LLCtrlScrollInterface
 {
 public:
+    typedef enum e_selection_type
+    {
+        ROW, // default
+        CELL, // does not support multi-selection
+        HEADER, // when pointing to cells in column 0 will highlight whole row, otherwise cell, no multi-select
+    } ESelectionType;
+
+    struct SelectionTypeNames : public LLInitParam::TypeValuesHelper<LLScrollListCtrl::ESelectionType, SelectionTypeNames>
+    {
+        static void declareValues();
+    };
+
 	struct Contents : public LLInitParam::Block<Contents>
 	{
 		Multiple<LLScrollListColumn::Params>	columns;
@@ -99,6 +111,8 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 						commit_on_keyboard_movement,
 						mouse_wheel_opaque;
 
+		Optional<ESelectionType, SelectionTypeNames> selection_type;
+
 		// display flags
 		Optional<bool>	has_border,
 						draw_heading,
@@ -114,7 +128,8 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 		// sort and search behavior
 		Optional<S32>	search_column,
 						sort_column;
-		Optional<bool>	sort_ascending;
+		Optional<bool>	sort_ascending,
+						can_sort; // whether user is allowed to sort
 
 		// colors
 		Optional<LLUIColor>	fg_unselected_color,
@@ -317,6 +332,7 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	/*virtual*/ BOOL	handleKeyHere(KEY key, MASK mask);
 	/*virtual*/ BOOL	handleUnicodeCharHere(llwchar uni_char);
 	/*virtual*/ BOOL	handleScrollWheel(S32 x, S32 y, S32 clicks);
+	/*virtual*/ BOOL	handleScrollHWheel(S32 x, S32 y, S32 clicks);
 	/*virtual*/ BOOL	handleToolTip(S32 x, S32 y, MASK mask);
 	/*virtual*/ void	setEnabled(BOOL enabled);
 	/*virtual*/ void	setFocus( BOOL b );
@@ -428,7 +444,7 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	void            updateLineHeightInsert(LLScrollListItem* item);
 	void			reportInvalidInput();
 	BOOL			isRepeatedChars(const LLWString& string) const;
-	void			selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE);
+	void			selectItem(LLScrollListItem* itemp, S32 cell, BOOL single_select = TRUE);
 	void			deselectItem(LLScrollListItem* itemp);
 	void			commitIfChanged();
 	BOOL			setSort(S32 column, BOOL ascending);
@@ -453,9 +469,11 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	bool			mCommitOnKeyboardMovement;
 	bool			mCommitOnSelectionChange;
 	bool			mSelectionChanged;
+	ESelectionType	mSelectionType;
 	bool			mNeedsScroll;
 	bool			mMouseWheelOpaque;
 	bool			mCanSelect;
+    bool			mCanSort;		// Whether user is allowed to sort
 	bool			mDisplayColumnHeaders;
 	bool			mColumnsDirty;
 	bool			mColumnWidthsDirty;
diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp
index df22c88afb428ec6c21348825a24ee19adff81df..51c615dd0037e23f0f5620ee07196c8470ce95f2 100644
--- a/indra/llui/llscrolllistitem.cpp
+++ b/indra/llui/llscrolllistitem.cpp
@@ -40,6 +40,8 @@
 LLScrollListItem::LLScrollListItem( const Params& p )
 :	mSelected(FALSE),
 	mHighlighted(FALSE),
+	mHoverIndex(-1),
+	mSelectedIndex(-1),
 	mEnabled(p.enabled),
 	mUserdata(p.userdata),
 	mItemValue(p.value)
@@ -53,6 +55,28 @@ LLScrollListItem::~LLScrollListItem()
 	mColumns.clear();
 }
 
+void LLScrollListItem::setSelected(BOOL b)
+{
+    mSelected = b;
+    mSelectedIndex = -1;
+}
+
+void LLScrollListItem::setHighlighted(BOOL b)
+{
+    mHighlighted = b;
+    mHoverIndex = -1;
+}
+
+void LLScrollListItem::setHoverCell(S32 cell)
+{
+    mHoverIndex = cell;
+}
+
+void LLScrollListItem::setSelectedCell(S32 cell)
+{
+    mSelectedIndex = cell;
+}
+
 void LLScrollListItem::addColumn(const LLScrollListCell::Params& p)
 {
 	mColumns.push_back(LLScrollListCell::create(p));
@@ -120,12 +144,21 @@ std::string LLScrollListItem::getContentsCSV() const
 }
 
 
-void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
+void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& hover_color, const LLColor4& select_color, const LLColor4& highlight_color, S32 column_padding)
 {
 	// draw background rect
 	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 	LLRect bg_rect = rect;
-	gl_rect_2d( bg_rect, bg_color );
+    if (mSelectedIndex < 0 && getSelected())
+    {
+        // Whole item is highlighted/selected
+        gl_rect_2d(bg_rect, select_color);
+    }
+    else if (mHoverIndex < 0)
+    {
+        // Whole item is highlighted/selected
+        gl_rect_2d(bg_rect, hover_color);
+    }
 
 	S32 cur_x = rect.mLeft;
 	S32 num_cols = getNumColumns();
@@ -141,6 +174,25 @@ void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const
 		{
 			LLUI::translate((F32) cur_x, (F32) rect.mBottom);
 
+            if (mSelectedIndex == cur_col)
+            {
+                // select specific cell
+                LLRect highlight_rect(0,
+                    cell->getHeight(),
+                    cell->getWidth(),
+                    0);
+                gl_rect_2d(highlight_rect, select_color);
+            }
+            else if (mHoverIndex == cur_col)
+            {
+                // highlight specific cell
+                LLRect highlight_rect(0,
+                    cell->getHeight(),
+                    cell->getWidth() ,
+                    0);
+                gl_rect_2d(highlight_rect, hover_color);
+            }
+
 			cell->draw( fg_color, highlight_color );
 		}
 		LLUI::popMatrix();
diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h
index 13655b5873b9f5cf8e35938e6e0ea92442632f9b..d2c3dd7721b2c54fafd02b48cc0de7b9985f5e27 100644
--- a/indra/llui/llscrolllistitem.h
+++ b/indra/llui/llscrolllistitem.h
@@ -77,15 +77,21 @@ class LLScrollListItem
 
 	virtual ~LLScrollListItem();
 
-	void	setSelected( BOOL b )			{ mSelected = b; }
+	void	setSelected( BOOL b );
 	BOOL	getSelected() const				{ return mSelected; }
 
 	void	setEnabled( BOOL b )			{ mEnabled = b; }
 	BOOL	getEnabled() const 				{ return mEnabled; }
 
-	void	setHighlighted( BOOL b )		{ mHighlighted = b; }
+	void	setHighlighted( BOOL b );
 	BOOL	getHighlighted() const			{ return mHighlighted; }
 
+	void	setSelectedCell( S32 cell );
+	S32		getSelectedCell() const			{ return mSelectedIndex; }
+
+	void	setHoverCell( S32 cell );
+	S32		getHoverCell() const			{ return mHoverIndex; }
+
 	void	setUserdata( void* userdata )	{ mUserdata = userdata; }
 	void*	getUserdata() const 			{ return mUserdata; }
 
@@ -107,14 +113,21 @@ class LLScrollListItem
 
 	std::string getContentsCSV() const;
 
-	virtual void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
+	virtual void draw(const LLRect& rect,
+					  const LLColor4& fg_color,
+					  const LLColor4& hover_color, // highlight/hover selection of whole item or cell
+					  const LLColor4& select_color, // highlight/hover selection of whole item or cell
+					  const LLColor4& highlight_color, // highlights contents of cells (ex: text)
+					  S32 column_padding);
 
 protected:
 	LLScrollListItem( const Params& );
 
 private:
 	BOOL	mSelected;
-	BOOL	mHighlighted;
+    BOOL	mHighlighted;
+    S32		mHoverIndex;
+	S32		mSelectedIndex;
 	BOOL	mEnabled;
 	void*	mUserdata;
 	LLSD	mItemValue;
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 22635f734e6fa213dd09751a672e7b802161a1ec..e64078828b813e8a6fa0ddc3f9ecc65a2da1b9f3 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -3113,6 +3113,7 @@ BOOL LLTextSegment::handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE;
 BOOL LLTextSegment::handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; }
 BOOL LLTextSegment::handleHover(S32 x, S32 y, MASK mask) { return FALSE; }
 BOOL LLTextSegment::handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; }
+BOOL LLTextSegment::handleScrollHWheel(S32 x, S32 y, S32 clicks) { return FALSE; }
 BOOL LLTextSegment::handleToolTip(S32 x, S32 y, MASK mask) { return FALSE; }
 const std::string&	LLTextSegment::getName() const 
 {
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 9831c35858f5253d81f8f8a2f5695a575d868cbf..4239cdf43c52109c4c68974052bd03eede43d891 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -103,6 +103,7 @@ class LLTextSegment
 	/*virtual*/ BOOL			handleDoubleClick(S32 x, S32 y, MASK mask);
 	/*virtual*/ BOOL			handleHover(S32 x, S32 y, MASK mask);
 	/*virtual*/ BOOL			handleScrollWheel(S32 x, S32 y, S32 clicks);
+	/*virtual*/ BOOL			handleScrollHWheel(S32 x, S32 y, S32 clicks);
 	/*virtual*/ BOOL			handleToolTip(S32 x, S32 y, MASK mask);
 	/*virtual*/ const std::string&	getName() const;
 	/*virtual*/ void			onMouseCaptureLost();
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index df74e113e9bc954f56f526e29427cc2c34da3547..c98da0d41043dec1367871be9313a24f4b4030e8 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -137,13 +137,29 @@ void LLUICtrl::initFromParams(const Params& p)
 		{
 			LLControlVariable* control = findControl(p.enabled_controls.enabled);
 			if (control)
+			{
 				setEnabledControlVariable(control);
+			}
+			else
+			{
+				LL_WARNS() << "Failed to assign 'enabled' control variable to " << getName()
+							<< ": control " << p.enabled_controls.enabled()
+							<< " does not exist." << LL_ENDL;
+			}
 		}
 		else if(p.enabled_controls.disabled.isChosen())
 		{
 			LLControlVariable* control = findControl(p.enabled_controls.disabled);
 			if (control)
+			{
 				setDisabledControlVariable(control);
+			}
+			else
+			{
+				LL_WARNS() << "Failed to assign 'disabled' control variable to " << getName() 
+							<< ": control " << p.enabled_controls.disabled()
+							<< " does not exist." << LL_ENDL;
+			}
 		}
 	}
 	if(p.controls_visibility.isProvided())
@@ -152,13 +168,29 @@ void LLUICtrl::initFromParams(const Params& p)
 		{
 			LLControlVariable* control = findControl(p.controls_visibility.visible);
 			if (control)
+			{
 				setMakeVisibleControlVariable(control);
+			}
+			else
+			{
+				LL_WARNS() << "Failed to assign visibility control variable to " << getName()
+							<< ": control " << p.controls_visibility.visible()
+							<< " does not exist." << LL_ENDL;
+			}
 		}
 		else if (p.controls_visibility.invisible.isChosen())
 		{
 			LLControlVariable* control = findControl(p.controls_visibility.invisible);
 			if (control)
+			{
 				setMakeInvisibleControlVariable(control);
+			}
+			else
+			{
+				LL_WARNS() << "Failed to assign invisibility control variable to " << getName()
+							<< ": control " << p.controls_visibility.invisible()
+							<< " does not exist." << LL_ENDL;
+			}
 		}
 	}
 
@@ -497,6 +529,11 @@ void LLUICtrl::setControlName(const std::string& control_name, LLView *context)
 	if (!control_name.empty())
 	{
 		LLControlVariable* control = context->findControl(control_name);
+		if (!control)
+		{
+			LL_WARNS() << "Failed to assign control variable to " << getName()
+						<< ": control "<< control_name << " does not exist." << LL_ENDL;
+		}
 		setControlVariable(control);
 	}
 }
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index 03d946f1b7729e6cc9808ba78529e5abc06b0877..f740f14e4d99b0f5728c5a5c4337469fcea04e3d 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -160,8 +160,8 @@ class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory>
 			LLXMLNodePtr root_node;
 
 			if (!LLUICtrlFactory::getLayeredXMLNode(filename, root_node))
-				{							
-				LL_WARNS() << "Couldn't parse XUI file: " << instance().getCurFileName() << LL_ENDL;
+			{
+                LL_WARNS() << "Couldn't parse XUI from path: " << instance().getCurFileName() << ", from filename: " << filename << LL_ENDL;
 				goto fail;
 			}
 
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 63ed427ab582334d7c8fe2f94c1466c6ec7f1179..333d03f208da6ee44e86357946d133f40c534163 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -454,13 +454,13 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
 }
 
 //
-// LLUrlEntrySeconlifeURL Describes *secondlife.com/ and *lindenlab.com/ urls to substitute icon 'hand.png' before link
+// LLUrlEntrySeconlifeURL Describes *secondlife.com/ *lindenlab.com/ and *tilia-inc.com/ urls to substitute icon 'hand.png' before link
 //
 LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL()
 {                              
-	mPattern = boost::regex("((http://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com)"
+	mPattern = boost::regex("((http://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com)"
 							"|"
-							"(https://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?))"
+							"(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?))"
 							"\\/\\S*",
 		boost::regex::perl|boost::regex::icase);
 	
@@ -495,11 +495,11 @@ std::string LLUrlEntrySecondlifeURL::getTooltip(const std::string &url) const
 }
 
 //
-// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com and *lindenlab.com urls to substitute icon 'hand.png' before link
+// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com *lindenlab.com and *tilia-inc.com urls to substitute icon 'hand.png' before link
 //
 LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL()
   {
-	mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(?!\\S)",
+	mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(?!\\S)",
 		boost::regex::perl|boost::regex::icase);
 
 	mIcon = "Hand";
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 2a190365b3e4d94a6230af95ba6a3ebe8aa31cf4..771d32d2fcddf48c4553442c47e7c173964d274a 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -875,10 +875,16 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
 		F32 timeout = LLToolTipMgr::instance().toolTipVisible() 
 		              ? LLUI::getInstance()->mSettingGroups["config"]->getF32( "ToolTipFastDelay" )
 		              : LLUI::getInstance()->mSettingGroups["config"]->getF32( "ToolTipDelay" );
-		LLToolTipMgr::instance().show(LLToolTip::Params()
-		                              .message(tooltip)
-		                              .sticky_rect(calcScreenRect())
-		                              .delay_time(timeout));
+
+		// Even if we don't show tooltips, consume the event, nothing below should show tooltip
+		bool allow_ui_tooltips = LLUI::sSettingGroups["config"]->getBOOL( "BasicUITooltips" );
+		if (allow_ui_tooltips)
+		{
+			LLToolTipMgr::instance().show(LLToolTip::Params()
+			                              .message(tooltip)
+			                              .sticky_rect(calcScreenRect())
+			                              .delay_time(timeout));
+		}
 		handled = TRUE;
 	}
 
@@ -1054,6 +1060,11 @@ BOOL LLView::handleScrollWheel(S32 x, S32 y, S32 clicks)
 	return childrenHandleScrollWheel( x, y, clicks ) != NULL;
 }
 
+BOOL LLView::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+	return childrenHandleScrollHWheel( x, y, clicks ) != NULL;
+}
+
 BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
 	return childrenHandleRightMouseDown( x, y, mask ) != NULL;
@@ -1079,6 +1090,11 @@ LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks)
 	return childrenHandleMouseEvent(&LLView::handleScrollWheel, x, y, clicks, false);
 }
 
+LLView* LLView::childrenHandleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+	return childrenHandleMouseEvent(&LLView::handleScrollHWheel, x, y, clicks, false);
+}
+
 // Called during downward traversal
 LLView* LLView::childrenHandleKey(KEY key, MASK mask)
 {
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index e36ca7c8c691a4abb83d92677bc678d8e7012de7..db81900aaff267e0d149d76ab712159bd3edc704 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -426,6 +426,7 @@ class LLView
 	/*virtual*/ BOOL	handleMiddleMouseDown(S32 x, S32 y, MASK mask);
 	/*virtual*/ BOOL	handleDoubleClick(S32 x, S32 y, MASK mask);
 	/*virtual*/ BOOL	handleScrollWheel(S32 x, S32 y, S32 clicks);
+	/*virtual*/ BOOL	handleScrollHWheel(S32 x, S32 y, S32 clicks);
 	/*virtual*/ BOOL	handleRightMouseDown(S32 x, S32 y, MASK mask);
 	/*virtual*/ BOOL	handleRightMouseUp(S32 x, S32 y, MASK mask);	
 	/*virtual*/ BOOL	handleToolTip(S32 x, S32 y, MASK mask);
@@ -556,6 +557,7 @@ class LLView
 	LLView* childrenHandleMiddleMouseDown(S32 x, S32 y, MASK mask);
 	LLView* childrenHandleDoubleClick(S32 x, S32 y, MASK mask);
 	LLView*	childrenHandleScrollWheel(S32 x, S32 y, S32 clicks);
+	LLView*	childrenHandleScrollHWheel(S32 x, S32 y, S32 clicks);
 	LLView* childrenHandleRightMouseDown(S32 x, S32 y, MASK mask);
 	LLView* childrenHandleRightMouseUp(S32 x, S32 y, MASK mask);
 	LLView* childrenHandleToolTip(S32 x, S32 y, MASK mask);
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 119cbebc8146f693a69fcacef545605a28a9a1ff..3c34fd269eb7ef418491e14d44a9c4d7305f7609 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -36,6 +36,11 @@
 
 #include <boost/regex.hpp>
 
+#if LL_WINDOWS
+// because something pulls in window and lldxdiag dependencies which in turn need wbemuuid.lib
+    #pragma comment(lib, "wbemuuid.lib")
+#endif
+
 
 // namespace LLExperienceCache
 // {
diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp
index d4790f9f294bca55a2112b6dd50511acf6fcca4c..12a6baa3e694d57c41075d1588970768322dbbe7 100644
--- a/indra/llwindow/lldxhardware.cpp
+++ b/indra/llwindow/lldxhardware.cpp
@@ -61,7 +61,7 @@ typedef BOOL ( WINAPI* PfnCoSetProxyBlanket )( IUnknown* pProxy, DWORD dwAuthnSv
                                                OLECHAR* pServerPrincName, DWORD dwAuthnLevel, DWORD dwImpLevel,
                                                RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities );
 
-HRESULT GetVideoMemoryViaWMI( WCHAR* strInputDeviceID, DWORD* pdwAdapterRam )
+HRESULT GetVideoMemoryViaWMI(WCHAR* strInputDeviceID, DWORD* pdwAdapterRam)
 {
     HRESULT hr;
     bool bGotMemory = false;
@@ -149,21 +149,26 @@ HRESULT GetVideoMemoryViaWMI( WCHAR* strInputDeviceID, DWORD* pdwAdapterRam )
                         if ( !pVideoControllers[iController] )
                             continue;
 
-                        pPropName = SysAllocString( L"PNPDeviceID" );
-                        hr = pVideoControllers[iController]->Get( pPropName, 0L, &var, nullptr, nullptr );
+                        // if strInputDeviceID is set find this specific device and return memory or specific device
+                        // if strInputDeviceID is not set return the best device
+                        if (strInputDeviceID)
+                        {
+                            pPropName = SysAllocString( L"PNPDeviceID" );
+                            hr = pVideoControllers[iController]->Get( pPropName, 0L, &var, nullptr, nullptr );
 #ifdef PRINTF_DEBUGGING
-                        if( FAILED( hr ) )
-                            wprintf( L"WMI: pVideoControllers[iController]->Get PNPDeviceID failed: 0x%0.8x\n", hr );
+                            if( FAILED( hr ) )
+                                wprintf( L"WMI: pVideoControllers[iController]->Get PNPDeviceID failed: 0x%0.8x\n", hr );
 #endif
-                        if( SUCCEEDED( hr ) )
-                        {
-                            if( wcsstr( var.bstrVal, strInputDeviceID ) != 0 )
-                                bFound = true;
+                            if( SUCCEEDED( hr ) && strInputDeviceID)
+                            {
+                                if( wcsstr( var.bstrVal, strInputDeviceID ) != 0 )
+                                    bFound = true;
+                            }
+                            VariantClear( &var );
+                            if( pPropName ) SysFreeString( pPropName );
                         }
-                        VariantClear( &var );
-                        if( pPropName ) SysFreeString( pPropName );
 
-                        if( bFound )
+                        if( bFound || !strInputDeviceID )
                         {
                             pPropName = SysAllocString( L"AdapterRAM" );
                             hr = pVideoControllers[iController]->Get( pPropName, 0L, &var, nullptr, nullptr );
@@ -175,13 +180,18 @@ HRESULT GetVideoMemoryViaWMI( WCHAR* strInputDeviceID, DWORD* pdwAdapterRam )
                             if( SUCCEEDED( hr ) )
                             {
                                 bGotMemory = true;
-                                *pdwAdapterRam = var.ulVal;
+                                *pdwAdapterRam = llmax(var.ulVal, *pdwAdapterRam);
                             }
                             VariantClear( &var );
                             if( pPropName ) SysFreeString( pPropName );
-                            break;
                         }
+
                         SAFE_RELEASE( pVideoControllers[iController] );
+
+                        if (bFound)
+                        {
+                            break;
+                        }
                     }
                 }
             }
@@ -207,6 +217,17 @@ HRESULT GetVideoMemoryViaWMI( WCHAR* strInputDeviceID, DWORD* pdwAdapterRam )
         return E_FAIL;
 }
 
+//static
+S32 LLDXHardware::getMBVideoMemoryViaWMI()
+{
+	DWORD vram = 0;
+	if (SUCCEEDED(GetVideoMemoryViaWMI(NULL, &vram)))
+	{
+		return vram / (1024 * 1024);;
+	}
+	return 0;
+}
+
 //Getting the version of graphics controller driver via WMI
 std::string LLDXHardware::getDriverVersionWMI()
 {
@@ -613,6 +634,9 @@ BOOL LLDXHardware::getInfo(BOOL vram_only)
 	IDxDiagContainer *device_containerp = NULL;
 	IDxDiagContainer *file_containerp = NULL;
 	IDxDiagContainer *driver_containerp = NULL;
+	DWORD dw_device_count;
+
+	mVRAM = 0;
 
     // CoCreate a IDxDiagProvider*
 	LL_DEBUGS("AppInit") << "CoCreateInstance IID_IDxDiagProvider" << LL_ENDL;
@@ -663,10 +687,21 @@ BOOL LLDXHardware::getInfo(BOOL vram_only)
 		hr = dx_diag_rootp->GetChildContainer(L"DxDiag_DisplayDevices", &devices_containerp);
 		if(FAILED(hr) || !devices_containerp)
 		{
+            // do not release 'dirty' devices_containerp at this stage, only dx_diag_rootp
+            devices_containerp = NULL; 
             goto LCleanup;
 		}
 
+        // make sure there is something inside
+        hr = devices_containerp->GetNumberOfChildContainers(&dw_device_count);
+        if (FAILED(hr) || dw_device_count == 0)
+        {
+            goto LCleanup;
+        }
+
 		// Get device 0
+		// By default 0 device is the primary one, howhever in case of various hybrid graphics
+		// like itegrated AMD and PCI AMD GPUs system might switch.
 		LL_DEBUGS("AppInit") << "devices_containerp->GetChildContainer" << LL_ENDL;
 		hr = devices_containerp->GetChildContainer(L"0", &device_containerp);
 		if(FAILED(hr) || !device_containerp)
@@ -679,12 +714,27 @@ BOOL LLDXHardware::getInfo(BOOL vram_only)
 		WCHAR deviceID[512];
 
 		get_wstring(device_containerp, L"szDeviceID", deviceID, 512);
-		
+		// Example: searches id like 1F06 in pnp string (aka VEN_10DE&DEV_1F06)
+		// doesn't seem to work on some systems since format is unrecognizable
+		// but in such case keyDeviceID works
 		if (SUCCEEDED(GetVideoMemoryViaWMI(deviceID, &vram))) 
 		{
 			mVRAM = vram/(1024*1024);
 		}
 		else
+		{
+			get_wstring(device_containerp, L"szKeyDeviceID", deviceID, 512);
+			LL_WARNS() << "szDeviceID" << deviceID << LL_ENDL;
+			// '+9' to avoid ENUM\\PCI\\ prefix
+			// Returns string like Enum\\PCI\\VEN_10DE&DEV_1F06&SUBSYS...
+			// and since GetVideoMemoryViaWMI searches by PNPDeviceID it is sufficient
+			if (SUCCEEDED(GetVideoMemoryViaWMI(deviceID + 9, &vram)))
+			{
+				mVRAM = vram / (1024 * 1024);
+			}
+		}
+		
+		if (mVRAM == 0)
 		{ // Get the English VRAM string
 		  std::string ram_str = get_string(device_containerp, L"szDisplayMemoryEnglish");
 
@@ -872,6 +922,7 @@ LLSD LLDXHardware::getDisplayInfo()
 	IDxDiagContainer *device_containerp = NULL;
 	IDxDiagContainer *file_containerp = NULL;
 	IDxDiagContainer *driver_containerp = NULL;
+	DWORD dw_device_count;
 
     // CoCreate a IDxDiagProvider*
 	LL_INFOS() << "CoCreateInstance IID_IDxDiagProvider" << LL_ENDL;
@@ -922,9 +973,18 @@ LLSD LLDXHardware::getDisplayInfo()
 		hr = dx_diag_rootp->GetChildContainer(L"DxDiag_DisplayDevices", &devices_containerp);
 		if(FAILED(hr) || !devices_containerp)
 		{
+            // do not release 'dirty' devices_containerp at this stage, only dx_diag_rootp
+            devices_containerp = NULL;
             goto LCleanup;
 		}
 
+        // make sure there is something inside
+        hr = devices_containerp->GetNumberOfChildContainers(&dw_device_count);
+        if (FAILED(hr) || dw_device_count == 0)
+        {
+            goto LCleanup;
+        }
+
 		// Get device 0
 		LL_INFOS() << "devices_containerp->GetChildContainer" << LL_ENDL;
 		hr = devices_containerp->GetChildContainer(L"0", &device_containerp);
@@ -976,6 +1036,10 @@ LLSD LLDXHardware::getDisplayInfo()
     }
 
 LCleanup:
+    if (ret.emptyMap())
+    {
+        LL_INFOS() << "Failed to get data, cleaning up" << LL_ENDL;
+    }
 	SAFE_RELEASE(file_containerp);
 	SAFE_RELEASE(driver_containerp);
 	SAFE_RELEASE(device_containerp);
diff --git a/indra/llwindow/lldxhardware.h b/indra/llwindow/lldxhardware.h
index cf33db8b3726231804b4a95faf33d726e7e0b167..1cb687e3b6d5794f71c13d088eb336649688b92b 100644
--- a/indra/llwindow/lldxhardware.h
+++ b/indra/llwindow/lldxhardware.h
@@ -94,6 +94,10 @@ class LLDXHardware
 
 	LLSD getDisplayInfo();
 
+	// Will get memory of best GPU in MB, return memory on sucsess, 0 on failure
+	// Note: WMI is not accurate in some cases
+	static S32 getMBVideoMemoryViaWMI();
+
 	// Find a particular device that matches the following specs.
 	// Empty strings indicate that you don't care.
 	// You can separate multiple devices with '|' chars to indicate you want
diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp
index f6f6c3931cb16073b2c43ffb1fa9773fa2cbd404..5404ac50e5c5baefe53ec7e2f65bf6b5d0604388 100644
--- a/indra/llwindow/llkeyboard.cpp
+++ b/indra/llwindow/llkeyboard.cpp
@@ -327,7 +327,7 @@ BOOL LLKeyboard::keyFromString(const std::string& str, KEY *key)
 
 
 // static
-std::string LLKeyboard::stringFromKey(KEY key)
+std::string LLKeyboard::stringFromKey(KEY key, bool translate)
 {
 	std::string res = get_if_there(sKeysToNames, key, std::string());
 	if (res.empty())
@@ -338,16 +338,60 @@ std::string LLKeyboard::stringFromKey(KEY key)
 		res = std::string(buffer);
 	}
 
-	LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
-	if (trans != NULL)
+	if (translate)
 	{
-		res = trans(res.c_str());
+		LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
+		if (trans != NULL)
+		{
+			res = trans(res.c_str());
+		}
 	}
 
 	return res;
 }
 
+//static
+std::string LLKeyboard::stringFromAccelerator(MASK accel_mask)
+{
+    std::string res;
+
+    LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
+
+    if (trans == NULL)
+    {
+        LL_ERRS() << "No mKeyStringTranslator" << LL_ENDL;
+        return res;
+    }
 
+    // Append any masks
+#ifdef LL_DARWIN
+    // Standard Mac names for modifier keys in menu equivalents
+    // We could use the symbol characters, but they only exist in certain fonts.
+    if (accel_mask & MASK_CONTROL)
+    {
+        if (accel_mask & MASK_MAC_CONTROL)
+        {
+            res.append(trans("accel-mac-control"));
+        }
+        else
+        {
+            res.append(trans("accel-mac-command"));		// Symbol would be "\xE2\x8C\x98"
+        }
+    }
+    if (accel_mask & MASK_ALT)
+        res.append(trans("accel-mac-option"));		// Symbol would be "\xE2\x8C\xA5"
+    if (accel_mask & MASK_SHIFT)
+        res.append(trans("accel-mac-shift"));		// Symbol would be "\xE2\x8C\xA7"
+#else
+    if (accel_mask & MASK_CONTROL)
+        res.append(trans("accel-win-control"));
+    if (accel_mask & MASK_ALT)
+        res.append(trans("accel-win-alt"));
+    if (accel_mask & MASK_SHIFT)
+        res.append(trans("accel-win-shift"));
+#endif
+    return res;
+}
 //static
 std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key )
 {
@@ -359,41 +403,7 @@ std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key )
 		return res;
 	}
 	
-	LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
-	
-	if( trans == NULL )
-	{
-		LL_ERRS() << "No mKeyStringTranslator" << LL_ENDL;
-		return res;
-	}
-	
-	// Append any masks
-#ifdef LL_DARWIN
-	// Standard Mac names for modifier keys in menu equivalents
-	// We could use the symbol characters, but they only exist in certain fonts.
-	if( accel_mask & MASK_CONTROL )
-	{
-		if ( accel_mask & MASK_MAC_CONTROL )
-		{
-			res.append( trans("accel-mac-control") );
-		}
-		else
-		{
-			res.append( trans("accel-mac-command") );		// Symbol would be "\xE2\x8C\x98"
-		}
-	}
-	if( accel_mask & MASK_ALT )
-		res.append( trans("accel-mac-option") );		// Symbol would be "\xE2\x8C\xA5"
-	if( accel_mask & MASK_SHIFT )
-		res.append( trans("accel-mac-shift") );		// Symbol would be "\xE2\x8C\xA7"
-#else
-	if( accel_mask & MASK_CONTROL )
-		res.append( trans("accel-win-control") );
-	if( accel_mask & MASK_ALT )
-		res.append( trans("accel-win-alt") );
-	if( accel_mask & MASK_SHIFT )
-		res.append( trans("accel-win-shift") );
-#endif
+	res.append(stringFromAccelerator(accel_mask));
 	std::string key_string = LLKeyboard::stringFromKey(key);
 	if ((accel_mask & MASK_NORMALKEYS) &&
 		(key_string[0] == '-' || key_string[0] == '=' || key_string[0] == '+'))
diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h
index 6f2dc87317a0ed62768475182883efd347b0c625..36bd8bcbed54784c4721f793f8e05dc19aeb2313 100644
--- a/indra/llwindow/llkeyboard.h
+++ b/indra/llwindow/llkeyboard.h
@@ -38,10 +38,10 @@ enum EKeystate
 {
 	KEYSTATE_DOWN,
 	KEYSTATE_LEVEL,
-	KEYSTATE_UP 
+	KEYSTATE_UP
 };
 
-typedef boost::function<void(EKeystate keystate)> LLKeyFunc;
+typedef boost::function<bool(EKeystate keystate)> LLKeyFunc;
 typedef std::string (LLKeyStringTranslatorFunc)(const char *label);
 	
 enum EKeyboardInsertMode
@@ -50,15 +50,6 @@ enum EKeyboardInsertMode
 	LL_KIM_OVERWRITE
 };
 
-class LLKeyBinding
-{
-public:
-	KEY				mKey;
-	MASK			mMask;
-// 	const char		*mName; // unused
-	LLKeyFunc		mFunction;
-};
-
 class LLWindowCallbacks;
 
 class LLKeyboard
@@ -103,7 +94,8 @@ class LLKeyboard
 
 	static BOOL		maskFromString(const std::string& str, MASK *mask);		// False on failure
 	static BOOL		keyFromString(const std::string& str, KEY *key);			// False on failure
-	static std::string stringFromKey(KEY key);
+	static std::string stringFromKey(KEY key, bool translate = true);
+	static std::string stringFromAccelerator( MASK accel_mask ); // separated for convinience, returns with "+": "Shift+" or "Shift+Alt+"...
 	static std::string stringFromAccelerator( MASK accel_mask, KEY key );
 
 	void setCallbacks(LLWindowCallbacks *cbs) { mCallbacks = cbs; }
diff --git a/indra/llwindow/llmousehandler.cpp b/indra/llwindow/llmousehandler.cpp
index bea66e763c21cee23b736f471aa679b935f6643c..e41ebd42f352ea11dc0b7022c1715ffc4112b86d 100644
--- a/indra/llwindow/llmousehandler.cpp
+++ b/indra/llwindow/llmousehandler.cpp
@@ -27,7 +27,7 @@
 #include "llmousehandler.h"
 
 //virtual
-BOOL LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down)
+BOOL LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
 {
 	BOOL handled = FALSE;
 	if (down)
@@ -38,6 +38,10 @@ BOOL LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType cli
 		case CLICK_RIGHT: handled = handleRightMouseDown(x, y, mask); break;
 		case CLICK_MIDDLE: handled = handleMiddleMouseDown(x, y, mask); break;
 		case CLICK_DOUBLELEFT: handled = handleDoubleClick(x, y, mask); break;
+		case CLICK_BUTTON4:
+		case CLICK_BUTTON5:
+			LL_INFOS() << "Handle mouse button " << clicktype + 1 << " down." << LL_ENDL;
+			break;
 		default:
 			LL_WARNS() << "Unhandled enum." << LL_ENDL;
 		}
@@ -50,6 +54,10 @@ BOOL LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType cli
 		case CLICK_RIGHT: handled = handleRightMouseUp(x, y, mask); break;
 		case CLICK_MIDDLE: handled = handleMiddleMouseUp(x, y, mask); break;
 		case CLICK_DOUBLELEFT: handled = handleDoubleClick(x, y, mask); break;
+		case CLICK_BUTTON4:
+		case CLICK_BUTTON5:
+			LL_INFOS() << "Handle mouse button " << clicktype + 1 << " up." << LL_ENDL;
+			break;
 		default:
 			LL_WARNS() << "Unhandled enum." << LL_ENDL;
 		}
diff --git a/indra/llwindow/llmousehandler.h b/indra/llwindow/llmousehandler.h
index d825a3424c0bb2524b718ad87a75fa3fc2bccf16..d221dd117c89ff9c4183bc6193f7b69b19d0892d 100644
--- a/indra/llwindow/llmousehandler.h
+++ b/indra/llwindow/llmousehandler.h
@@ -29,6 +29,7 @@
 
 #include "linden_common.h"
 #include "llrect.h"
+#include "indra_constants.h"
 
 // Mostly-abstract interface.
 // Intended for use via multiple inheritance. 
@@ -46,14 +47,7 @@ class LLMouseHandler
 		SHOW_ALWAYS,
 	} EShowToolTip;
 
-	typedef enum {
-		CLICK_LEFT,
-		CLICK_MIDDLE,
-		CLICK_RIGHT,
-		CLICK_DOUBLELEFT
-	} EClickType;
-
-	virtual BOOL	handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
+	virtual BOOL	handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
 	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask) = 0;
 	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask) = 0;
 	virtual BOOL	handleMiddleMouseDown(S32 x, S32 y, MASK mask) = 0;
@@ -64,6 +58,7 @@ class LLMouseHandler
 
 	virtual BOOL	handleHover(S32 x, S32 y, MASK mask) = 0;
 	virtual BOOL	handleScrollWheel(S32 x, S32 y, S32 clicks) = 0;
+	virtual BOOL	handleScrollHWheel(S32 x, S32 y, S32 clicks) = 0;
 	virtual BOOL	handleToolTip(S32 x, S32 y, MASK mask) = 0;
 	virtual const std::string& getName() const = 0;
 
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm
index 1990499459d966dcea3bb2c2760354469a1f06e7..5b9dce02c4bae01ff49dd2f0e13034d51f31264e 100644
--- a/indra/llwindow/llopenglview-objc.mm
+++ b/indra/llwindow/llopenglview-objc.mm
@@ -444,7 +444,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
     NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
     mMousePos[0] = mPoint.x;
     mMousePos[1] = mPoint.y;
-	callMiddleMouseDown(mMousePos, [theEvent modifierFlags]);
+    callOtherMouseDown(mMousePos, [theEvent modifierFlags], [theEvent buttonNumber]);
 }
 
 - (void) otherMouseUp:(NSEvent *)theEvent
@@ -452,7 +452,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
     NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
     mMousePos[0] = mPoint.x;
     mMousePos[1] = mPoint.y;
-	callMiddleMouseUp(mMousePos, [theEvent modifierFlags]);
+    callOtherMouseUp(mMousePos, [theEvent modifierFlags], [theEvent buttonNumber]);
 }
 
 - (void) rightMouseDragged:(NSEvent *)theEvent
@@ -467,7 +467,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
 
 - (void) scrollWheel:(NSEvent *)theEvent
 {
-	callScrollMoved(-[theEvent deltaY]);
+	callScrollMoved(-[theEvent deltaX], -[theEvent deltaY]);
 }
 
 - (void) mouseExited:(NSEvent *)theEvent
@@ -816,7 +816,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
     [super setMarkedText:aString selectedRange:selectedRange replacementRange:replacementRange];
     if ([aString length] == 0)      // this means Input Widow becomes empty
     {
-        [_window orderOut:_window];     // Close this to avoid empty Input Window
+        [self.window orderOut:self.window];     // Close this to avoid empty Input Window
     }
 }
 
@@ -840,7 +840,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
         (mKeyPressed >= 0xF700 && mKeyPressed <= 0xF8FF))
     {
         // this is case a) of above comment
-        [_window orderOut:_window];     // to avoid empty Input Window
+        [self.window orderOut:self.window];     // to avoid empty Input Window
     }
 }
 
diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp
index 94c725fc7ebb74fc67d1c9b8d6cbbddb14f3b50d..be61e1e16c62fd4db5b04e67bb92a612fe170f3b 100644
--- a/indra/llwindow/llwindowcallbacks.cpp
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -98,6 +98,16 @@ BOOL LLWindowCallbacks::handleMiddleMouseUp(LLWindow *window, const LLCoordGL po
 	return FALSE;
 }
 
+BOOL LLWindowCallbacks::handleOtherMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask, S32 button)
+{
+    return FALSE;
+}
+
+BOOL LLWindowCallbacks::handleOtherMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask, S32 button)
+{
+    return FALSE;
+}
+
 BOOL LLWindowCallbacks::handleActivate(LLWindow *window, BOOL activated)
 {
 	return FALSE;
@@ -120,6 +130,10 @@ void LLWindowCallbacks::handleScrollWheel(LLWindow *window, S32 clicks)
 {
 }
 
+void LLWindowCallbacks::handleScrollHWheel(LLWindow *window, S32 clicks)
+{
+}
+
 void LLWindowCallbacks::handleResize(LLWindow *window, const S32 width, const S32 height)
 {
 }
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
index 4d753024fec52ff3ab07e48b2317f8bfdfa23f7c..3b186481388cc8d290a5a5a2788665b77a7a5807 100644
--- a/indra/llwindow/llwindowcallbacks.h
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -49,11 +49,14 @@ class LLWindowCallbacks
 	virtual BOOL handleRightMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask);
 	virtual BOOL handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask);
 	virtual BOOL handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask);
+	virtual BOOL handleOtherMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask, S32 button);
+	virtual BOOL handleOtherMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask, S32 button);
 	virtual BOOL handleActivate(LLWindow *window, BOOL activated);
 	virtual BOOL handleActivateApp(LLWindow *window, BOOL activating);
 	virtual void handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask);
     virtual void handleMouseDragged(LLWindow *window,  LLCoordGL pos, MASK mask);
 	virtual void handleScrollWheel(LLWindow *window,  S32 clicks);
+	virtual void handleScrollHWheel(LLWindow *window,  S32 clicks);
 	virtual void handleResize(LLWindow *window,  S32 width,  S32 height);
 	virtual void handleFocus(LLWindow *window);
 	virtual void handleFocusLost(LLWindow *window);
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index 99af16110289c47d38327994d0a095fc91b0e80f..44fd4127ce5a06b0e1694828b1eb9fe0b00c7f92 100644
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -142,7 +142,7 @@ void callDoubleClick(float *pos, unsigned int mask);
 void callResize(unsigned int width, unsigned int height);
 void callMouseMoved(float *pos, unsigned int mask);
 void callMouseDragged(float *pos, unsigned int mask);
-void callScrollMoved(float delta);
+void callScrollMoved(float deltaX, float deltaY);
 void callMouseExit();
 void callWindowFocus();
 void callWindowUnfocus();
@@ -150,8 +150,8 @@ void callWindowHide();
 void callWindowUnhide();
 void callWindowDidChangeScreen();
 void callDeltaUpdate(float *delta, unsigned int mask);
-void callMiddleMouseDown(float *pos, unsigned int mask);
-void callMiddleMouseUp(float *pos, unsigned int mask);
+void callOtherMouseDown(float *pos, unsigned int mask, int button);
+void callOtherMouseUp(float *pos, unsigned int mask, int button);
 void callFocus();
 void callFocusLost();
 void callModifier(unsigned int mask);
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 3554f90be8c558f600888849b26c2f616cfa1321..2604a23c85107a5aaffa11373938ec4c547e4275 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -356,9 +356,13 @@ void callMouseDragged(float *pos, MASK mask)
     gWindowImplementation->getCallbacks()->handleMouseDragged(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
 }
 
-void callScrollMoved(float delta)
+void callScrollMoved(float deltaX, float deltaY)
 {
-	gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, delta);
+	if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
+	{
+		gWindowImplementation->getCallbacks()->handleScrollHWheel(gWindowImplementation, deltaX);
+		gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, deltaY);
+	}
 }
 
 void callMouseExit()
@@ -417,7 +421,7 @@ void callDeltaUpdate(float *delta, MASK mask)
 	gWindowImplementation->updateMouseDeltas(delta);
 }
 
-void callMiddleMouseDown(float *pos, MASK mask)
+void callOtherMouseDown(float *pos, MASK mask, int button)
 {
 	LLCoordGL		outCoords;
 	outCoords.mX = ll_round(pos[0]);
@@ -426,10 +430,18 @@ void callMiddleMouseDown(float *pos, MASK mask)
 	gWindowImplementation->getMouseDeltas(deltas);
 	outCoords.mX += deltas[0];
 	outCoords.mY += deltas[1];
-	gWindowImplementation->getCallbacks()->handleMiddleMouseDown(gWindowImplementation, outCoords, mask);
+
+    if (button == 2)
+    {
+        gWindowImplementation->getCallbacks()->handleMiddleMouseDown(gWindowImplementation, outCoords, mask);
+    }
+    else
+    {
+        gWindowImplementation->getCallbacks()->handleOtherMouseDown(gWindowImplementation, outCoords, mask, button + 1);
+    }
 }
 
-void callMiddleMouseUp(float *pos, MASK mask)
+void callOtherMouseUp(float *pos, MASK mask, int button)
 {
 	LLCoordGL outCoords;
 	outCoords.mX = ll_round(pos[0]);
@@ -437,8 +449,15 @@ void callMiddleMouseUp(float *pos, MASK mask)
 	float deltas[2];
 	gWindowImplementation->getMouseDeltas(deltas);
 	outCoords.mX += deltas[0];
-	outCoords.mY += deltas[1];
-	gWindowImplementation->getCallbacks()->handleMiddleMouseUp(gWindowImplementation, outCoords, mask);
+    outCoords.mY += deltas[1];
+    if (button == 2)
+    {
+        gWindowImplementation->getCallbacks()->handleMiddleMouseUp(gWindowImplementation, outCoords, mask);
+    }
+    else
+    {
+        gWindowImplementation->getCallbacks()->handleOtherMouseUp(gWindowImplementation, outCoords, mask, button + 1);
+    }
 }
 
 void callModifier(MASK mask)
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index e05f5075067a406c941094a337fb8805a12b3d86..0b3936f8a5c12b805955824c31aa183d17513a14 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -741,17 +741,27 @@ void LLWindowWin32::restore()
 	SetFocus(mWindowHandle);
 }
 
+// See SL-12170
+// According to callstack "c0000005 Access violation" happened inside __try block,
+// deep in DestroyWindow and crashed viewer, which shouldn't be possible.
+// I tried manually causing this exception and it was caught without issues, so
+// I'm turning off optimizations for this part to be sure code executes as intended
+// (it is a straw, but I have no idea why else __try can get overruled)
+#pragma optimize("", off)
 bool destroy_window_handler(HWND &hWnd)
 {
+    bool res;
     __try
     {
-        return DestroyWindow(hWnd);
+        res = DestroyWindow(hWnd);
     }
     __except (EXCEPTION_EXECUTE_HANDLER)
     {
-        return false;
+        res = false;
     }
+    return res;
 }
+#pragma optimize("", on)
 
 // close() destroys all OS-specific code associated with a window.
 // Usually called from LLWindowManager::destroyWindow()
@@ -2539,6 +2549,72 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
 				}
 			}
 			break;
+		case WM_XBUTTONDOWN:
+			{
+				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN");
+				LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER);
+				S32 button = GET_XBUTTON_WPARAM(w_param);
+				if (LLWinImm::isAvailable() && window_imp->mPreeditor)
+				{
+					window_imp->interruptLanguageTextInput();
+				}
+
+				// Because we move the cursor position in tllviewerhe app, we need to query
+				// to find out where the cursor at the time the event is handled.
+				// If we don't do this, many clicks could get buffered up, and if the
+				// first click changes the cursor position, all subsequent clicks
+				// will occur at the wrong location.  JC
+				if (window_imp->mMousePositionModified)
+				{
+					LLCoordWindow cursor_coord_window;
+					window_imp->getCursorPosition(&cursor_coord_window);
+					gl_coord = cursor_coord_window.convert();
+				}
+				else
+				{
+					gl_coord = window_coord.convert();
+				}
+				MASK mask = gKeyboard->currentMask(TRUE);
+				// generate move event to update mouse coordinates
+				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
+				// Windows uses numbers 1 and 2 for buttons, remap to 4, 5
+				if (window_imp->mCallbacks->handleOtherMouseDown(window_imp, gl_coord, mask, button + 3))
+				{
+					return 0;
+				}
+			}
+			break;
+
+		case WM_XBUTTONUP:
+			{
+				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP");
+				LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER);
+				S32 button = GET_XBUTTON_WPARAM(w_param);
+				// Because we move the cursor position in the llviewer app, we need to query
+				// to find out where the cursor at the time the event is handled.
+				// If we don't do this, many clicks could get buffered up, and if the
+				// first click changes the cursor position, all subsequent clicks
+				// will occur at the wrong location.  JC
+				if (window_imp->mMousePositionModified)
+				{
+					LLCoordWindow cursor_coord_window;
+					window_imp->getCursorPosition(&cursor_coord_window);
+					gl_coord = cursor_coord_window.convert();
+				}
+				else
+				{
+					gl_coord = window_coord.convert();
+				}
+				MASK mask = gKeyboard->currentMask(TRUE);
+				// generate move event to update mouse coordinates
+				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
+				// Windows uses numbers 1 and 2 for buttons, remap to 4, 5
+				if (window_imp->mCallbacks->handleOtherMouseUp(window_imp, gl_coord, mask, button + 3))
+				{
+					return 0;
+				}
+			}
+			break;
 
 		case WM_MOUSEWHEEL:
 			{
@@ -2596,6 +2672,42 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
 			return 0;
 			}
 			*/
+		case WM_MOUSEHWHEEL:
+			{
+				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEHWHEEL");
+				static short h_delta = 0;
+
+				RECT	client_rect;
+
+				// eat scroll events that occur outside our window, since we use mouse position to direct scroll
+				// instead of keyboard focus
+				// NOTE: mouse_coord is in *window* coordinates for scroll events
+				POINT mouse_coord = {(S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)};
+
+				if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord)
+					&& GetClientRect(window_imp->mWindowHandle, &client_rect))
+				{
+					// we have a valid mouse point and client rect
+					if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x
+						|| mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y)
+					{
+						// mouse is outside of client rect, so don't do anything
+						return 0;
+					}
+				}
+
+				S16 incoming_h_delta = HIWORD(w_param);
+				h_delta += incoming_h_delta;
+
+				// If the user rapidly spins the wheel, we can get messages with
+				// large deltas, like 480 or so.  Thus we need to scroll more quickly.
+				if (h_delta <= -WHEEL_DELTA || WHEEL_DELTA <= h_delta)
+				{
+					window_imp->mCallbacks->handleScrollHWheel(window_imp, h_delta / WHEEL_DELTA);
+					h_delta = 0;
+				}
+				return 0;
+			}
 			// Handle mouse movement within the window
 		case WM_MOUSEMOVE:
 			{
diff --git a/indra/llxml/CMakeLists.txt b/indra/llxml/CMakeLists.txt
index 17400a203e8485bb46b62f4011c60e1fe93fad36..013a422d35b07863647a3d6309cc94db869e571d 100644
--- a/indra/llxml/CMakeLists.txt
+++ b/indra/llxml/CMakeLists.txt
@@ -28,7 +28,6 @@ set(llxml_HEADER_FILES
     CMakeLists.txt
 
     llcontrol.h
-    llcontrolgroupreader.h
     llxmlnode.h
     llxmlparser.h
     llxmltree.h
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index de0d366492fcf475d60695955d8976e975fdd54a..9312bbc91ac71603b7f0cc82f6221251b496fd94 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -34,8 +34,6 @@
 #include "llrefcount.h"
 #include "llinstancetracker.h"
 
-#include "llcontrolgroupreader.h"
-
 #include <vector>
 
 // *NOTE: boost::visit_each<> generates warning 4675 on .net 2003
diff --git a/indra/llxml/llcontrolgroupreader.h b/indra/llxml/llcontrolgroupreader.h
deleted file mode 100644
index 6a27a65499ba226715f610c960127fb993129a1d..0000000000000000000000000000000000000000
--- a/indra/llxml/llcontrolgroupreader.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/** 
- * @file llcontrolgroupreader.h
- * @brief Interface providing readonly access to LLControlGroup (intended for unit testing)
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#ifndef LL_LLCONTROLGROUPREADER_H
-#define LL_LLCONTROLGROUPREADER_H
-
-#include "stdtypes.h"
-#include <string>
-
-#include "v3math.h"
-#include "v3dmath.h"
-#include "v3color.h"
-#include "v4color.h"
-#include "llrect.h"
-
-class LLControlGroupReader
-{
-public:
-	LLControlGroupReader() {}
-	virtual ~LLControlGroupReader() {}
-
-	virtual std::string getString(const std::string& name) { return ""; }
-	virtual LLWString	getWString(const std::string& name) { return LLWString(); }
-	virtual std::string	getText(const std::string& name) { return ""; }
-	virtual LLVector3	getVector3(const std::string& name) { return LLVector3(); }
-	virtual LLVector3d	getVector3d(const std::string& name) { return LLVector3d(); }
-	virtual LLRect		getRect(const std::string& name) { return LLRect(); }
-	virtual BOOL		getBOOL(const std::string& name) { return FALSE; }
-	virtual S32			getS32(const std::string& name) { return 0; }
-	virtual F32			getF32(const std::string& name) {return 0.0f; }
-	virtual U32			getU32(const std::string& name) {return 0; }
-	virtual LLSD        getLLSD(const std::string& name) { return LLSD(); }
-
-	virtual LLColor4	getColor(const std::string& name) { return LLColor4(); }
-	virtual LLColor4	getColor4(const std::string& name) { return LLColor4(); }
-	virtual LLColor3	getColor3(const std::string& name) { return LLColor3(); }
-	
-	virtual void		setBOOL(const std::string& name, BOOL val) {}
-	virtual void		setS32(const std::string& name, S32 val) {}
-	virtual void		setF32(const std::string& name, F32 val) {}
-	virtual void		setU32(const std::string& name, U32 val) {}
-	virtual void		setString(const std::string&  name, const std::string& val) {}
-	virtual void		setVector3(const std::string& name, const LLVector3 &val) {}
-	virtual void		setVector3d(const std::string& name, const LLVector3d &val) {}
-	virtual void		setRect(const std::string& name, const LLRect &val) {}
-	virtual void		setColor4(const std::string& name, const LLColor4 &val) {}
-	virtual void    	setLLSD(const std::string& name, const LLSD& val) {}
-};
-
-#endif /* LL_LLCONTROLGROUPREADER_H */
-
-
-
-
-
-
-
diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp
index eead92fd8e8f6e555d3e123fe5b97e300f2506b6..cff21b13c476d4ae6e625e18e1e3d5ce8bb920ce 100644
--- a/indra/media_plugins/cef/media_plugin_cef.cpp
+++ b/indra/media_plugins/cef/media_plugin_cef.cpp
@@ -241,6 +241,7 @@ void MediaPluginCEF::onRequestExitCallback()
 	LLPluginMessage message("base", "goodbye");
 	sendMessage(message);
 
+	// Will trigger delete on next staticReceiveMessage()
 	mDeleteMe = true;
 }
 
@@ -437,9 +438,13 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
 			}
 			else if (message_name == "cleanup")
 			{
-				mVolumeCatcher.setVolume(0);
+				mVolumeCatcher.setVolume(0); // Hack: masks CEF exit issues
 				mCEFLib->requestExit();
 			}
+			else if (message_name == "force_exit")
+			{
+				mDeleteMe = true;
+			}
 			else if (message_name == "shm_added")
 			{
 				SharedSegmentInfo info;
@@ -655,12 +660,18 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
 			}
 			else if (message_name == "scroll_event")
 			{
-				S32 x = message_in.getValueS32("x");
-				S32 y = message_in.getValueS32("y");
+				// Mouse coordinates for cef to be able to scroll 'containers'
+				//S32 x = message_in.getValueS32("x");
+				//S32 y = message_in.getValueS32("y");
+				// Wheel's clicks
+				S32 delta_x = message_in.getValueS32("clicks_x");
+				S32 delta_y = message_in.getValueS32("clicks_y");
 				const int scaling_factor = 40;
-				y *= -scaling_factor;
+				delta_x *= -scaling_factor;
+				delta_y *= -scaling_factor;
 
-				mCEFLib->mouseWheel(x, y);
+				// mCEFLib->mouseWheel(x, y, delta_x, delta_y);
+				mCEFLib->mouseWheel(delta_x, delta_y);
 			}
 			else if (message_name == "text_event")
 			{
diff --git a/indra/media_plugins/example/media_plugin_example.cpp b/indra/media_plugins/example/media_plugin_example.cpp
index c296a0413de5daaea3c4e3a4b0629a131a838270..650685fb945ac4cc7954d13dbeea56e82dcd08a9 100644
--- a/indra/media_plugins/example/media_plugin_example.cpp
+++ b/indra/media_plugins/example/media_plugin_example.cpp
@@ -128,6 +128,10 @@ void mediaPluginExample::receiveMessage(const char* message_string)
 
 				mDeleteMe = true;
 			}
+			else if (message_name == "force_exit")
+			{
+				mDeleteMe = true;
+			}
 			else if (message_name == "shm_added")
 			{
 				SharedSegmentInfo info;
diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
index 80702a10797229208690e1b2a557284d28aa2fb7..f7d35b33c281becebf0053bbb8a550b2ea1f4f07 100644
--- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
+++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
@@ -495,6 +495,10 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string)
 			{
 				resetVLC();
 			}
+			else if (message_name == "force_exit")
+			{
+				mDeleteMe = true;
+			}
 			else if (message_name == "shm_added")
 			{
 				SharedSegmentInfo info;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 694e89ab99bfcfaa67222e341e74ff3f1186c0ed..5a872f2aac9932edd085231250cbebcf359b22e9 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -246,6 +246,7 @@ set(viewer_SOURCE_FILES
     llfloaterexperiences.cpp
     llfloaterflickr.cpp
     llfloaterfonttest.cpp
+    llfloaterforgetuser.cpp
     llfloatergesture.cpp
     llfloatergodtools.cpp
     llfloatergotoline.cpp
@@ -375,6 +376,7 @@ set(viewer_SOURCE_FILES
     llinventoryobserver.cpp
     llinventorypanel.cpp
     lljoystickbutton.cpp
+    llkeyconflict.cpp
     lllandmarkactions.cpp
     lllandmarklist.cpp
     lllistbrowser.cpp
@@ -548,6 +550,7 @@ set(viewer_SOURCE_FILES
     llsecapi.cpp
     llsechandler_basic.cpp
     llselectmgr.cpp
+    llsetkeybinddialog.cpp
     llshareavatarhandler.cpp
     llsidepanelappearance.cpp
     llsidepanelinventory.cpp
@@ -651,7 +654,7 @@ set(viewer_SOURCE_FILES
     llviewerjointattachment.cpp
     llviewerjointmesh.cpp
     llviewerjoystick.cpp
-    llviewerkeyboard.cpp
+    llviewerinput.cpp
     llviewerlayer.cpp
     llviewermedia.cpp
     llviewermedia_streamingaudio.cpp
@@ -663,6 +666,7 @@ set(viewer_SOURCE_FILES
     llviewerobject.cpp
     llviewerobjectlist.cpp
     llvieweroctree.cpp
+    llviewerparcelaskplay.cpp
     llviewerparcelmedia.cpp
     llviewerparcelmediaautoplay.cpp
     llviewerparcelmgr.cpp
@@ -871,6 +875,7 @@ set(viewer_HEADER_FILES
     llfloaterexperiences.h
     llfloaterflickr.h
     llfloaterfonttest.h
+    llfloaterforgetuser.h
     llfloatergesture.h
     llfloatergodtools.h
     llfloatergotoline.h
@@ -1001,6 +1006,7 @@ set(viewer_HEADER_FILES
     llinventoryobserver.h
     llinventorypanel.h
     lljoystickbutton.h
+    llkeyconflict.h
     lllandmarkactions.h
     lllandmarklist.h
     lllightconstants.h
@@ -1165,6 +1171,7 @@ set(viewer_HEADER_FILES
     llsecapi.h
     llsechandler_basic.h
     llselectmgr.h
+    llsetkeybinddialog.h
     llsidepanelappearance.h
     llsidepanelinventory.h
     llsidepanelinventorysubpanel.h
@@ -1270,7 +1277,7 @@ set(viewer_HEADER_FILES
     llviewerjointattachment.h
     llviewerjointmesh.h
     llviewerjoystick.h
-    llviewerkeyboard.h
+    llviewerinput.h
     llviewerlayer.h
     llviewermedia.h
     llviewermediafocus.h
@@ -1282,6 +1289,7 @@ set(viewer_HEADER_FILES
     llviewerobject.h
     llviewerobjectlist.h
     llvieweroctree.h
+    llviewerparcelaskplay.h
     llviewerparcelmedia.h
     llviewerparcelmediaautoplay.h
     llviewerparcelmgr.h
@@ -1656,7 +1664,7 @@ set(viewer_APPSETTINGS_FILES
     app_settings/grass.xml
     app_settings/high_graphics.xml
     app_settings/ignorable_dialogs.xml
-    app_settings/keys.xml
+    app_settings/key_bindings.xml
     app_settings/keywords_lsl_default.xml
     app_settings/logcontrol.xml
     app_settings/low_graphics.xml
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index cab0c523b2300fd335e77843f59c1259bfea8e98..dae397a3b6c74ed90134f34afa4bcaf0bc75813b 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -150,16 +150,6 @@
            is_running_function="Floater.IsOpen"
            is_running_parameters="moveview"
            />
-  <command name="outbox"
-           available_in_toybox="false"
-           icon="Command_Outbox_Icon"
-           label_ref="Command_Outbox_Label"
-           tooltip_ref="Command_Outbox_Tooltip"
-           execute_function="Floater.ToggleOrBringToFront"
-           execute_parameters="outbox"
-           is_running_function="Floater.IsOpen"
-           is_running_parameters="outbox"
-           />
   <command name="people"
            available_in_toybox="true"
            icon="Command_People_Icon"
diff --git a/indra/newview/app_settings/keys.xml b/indra/newview/app_settings/key_bindings.xml
similarity index 64%
rename from indra/newview/app_settings/keys.xml
rename to indra/newview/app_settings/key_bindings.xml
index a8037fec05a663e610807aaafb8ea214754d7e3f..dd7429364472c4be3e7e27697844b91cae61010c 100644
--- a/indra/newview/app_settings/keys.xml
+++ b/indra/newview/app_settings/key_bindings.xml
@@ -28,34 +28,12 @@
     <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
     <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
 
-    <binding key="A" mask="SHIFT" command="slide_left"/>
-    <binding key="D" mask="SHIFT" command="slide_right"/>
-    <binding key="W" mask="SHIFT" command="push_forward"/>
-    <binding key="S" mask="SHIFT" command="push_backward"/>
-    <binding key="E" mask="SHIFT" command="jump"/>
-    <binding key="C" mask="SHIFT" command="push_down"/>
-    <binding key="F" mask="SHIFT" command="toggle_fly"/>
-
     <binding key="SPACE" mask="NONE" command="stop_moving"/>
     <binding key="ENTER" mask="NONE" command="start_chat"/>
     <binding key="DIVIDE" mask="NONE" command="start_gesture"/>
 
-    <binding key="LEFT" mask="SHIFT" command="slide_left"/>
-    <binding key="RIGHT" mask="SHIFT" command="slide_right"/>
-    <binding key="UP" mask="SHIFT" command="push_forward"/>
-    <binding key="DOWN" mask="SHIFT" command="push_backward"/>
-    <binding key="PGUP" mask="SHIFT" command="jump"/>
-    <binding key="PGDN" mask="SHIFT" command="push_down"/>
-
-    <binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
-    <binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
-    <binding key="PAD_UP" mask="SHIFT" command="push_forward"/>
-    <binding key="PAD_DOWN" mask="SHIFT" command="push_backward"/>
-    <binding key="PAD_PGUP" mask="SHIFT" command="jump"/>
-    <binding key="PAD_PGDN" mask="SHIFT" command="push_down"/>
-    <binding key="PAD_HOME" mask="SHIFT" command="toggle_fly"/>
-    <binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
-    <binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
+    <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+    <binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
   </first_person>
   <third_person>
     <binding key="A" mask="NONE" command="turn_left"/>
@@ -64,15 +42,10 @@
     <binding key="D" mask="SHIFT" command="slide_right"/>
     <binding key="W" mask="NONE" command="push_forward"/>
     <binding key="S" mask="NONE" command="push_backward"/>
-    <binding key="W" mask="SHIFT" command="push_forward"/>
-    <binding key="S" mask="SHIFT" command="push_backward"/>
     <binding key="E" mask="NONE" command="jump"/>
     <binding key="C" mask="NONE" command="push_down"/>
-    <binding key="E" mask="SHIFT" command="jump"/>
-    <binding key="C" mask="SHIFT" command="push_down"/>
 
     <binding key="F" mask="NONE" command="toggle_fly"/>
-    <binding key="F" mask="SHIFT" command="toggle_fly"/>
 
     <binding key="SPACE" mask="NONE" command="stop_moving"/>
     <binding key="ENTER" mask="NONE" command="start_chat"/>
@@ -84,13 +57,8 @@
     <binding key="RIGHT" mask="SHIFT" command="slide_right"/>
     <binding key="UP" mask="NONE" command="push_forward"/>
     <binding key="DOWN" mask="NONE" command="push_backward"/>
-    <binding key="UP" mask="SHIFT" command="push_forward"/>
-    <binding key="DOWN" mask="SHIFT" command="push_backward"/>
     <binding key="PGUP" mask="NONE" command="jump"/>
     <binding key="PGDN" mask="NONE" command="push_down"/>
-    <binding key="PGUP" mask="SHIFT" command="jump"/>
-    <binding key="PGDN" mask="SHIFT" command="push_down"/>
-    <binding key="HOME" mask="SHIFT" command="toggle_fly"/>
     <binding key="HOME" mask="NONE" command="toggle_fly"/>
 
     <binding key="PAD_LEFT" mask="NONE" command="turn_left"/>
@@ -99,20 +67,12 @@
     <binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
     <binding key="PAD_UP" mask="NONE" command="push_forward"/>
     <binding key="PAD_DOWN" mask="NONE" command="push_backward"/>
-    <binding key="PAD_UP" mask="SHIFT" command="push_forward"/>
-    <binding key="PAD_DOWN" mask="SHIFT" command="push_backward"/>
     <binding key="PAD_PGUP" mask="NONE" command="jump"/>
     <binding key="PAD_PGDN" mask="NONE" command="push_down"/>
-    <binding key="PAD_PGUP" mask="SHIFT" command="jump"/>
-    <binding key="PAD_PGDN" mask="SHIFT" command="push_down"/>
     <binding key="PAD_HOME" mask="NONE" command="toggle_fly"/>
-    <binding key="PAD_HOME" mask="SHIFT" command="toggle_fly"/>
     <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/>
-    <binding key="PAD_CENTER" mask="SHIFT" command="stop_moving"/>
     <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
-    <binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
     <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
-    <binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
 
     <!--Camera controls in third person on Alt-->
     <binding key="LEFT" mask="ALT" command="spin_around_cw"/>
@@ -139,28 +99,14 @@
     <binding key="PAD_DIVIDE" mask="ALT" command="start_gesture"/>
 
     <!--mimic alt zoom behavior with keyboard only-->
-    <binding key="A" mask="CTL_ALT" command="spin_around_cw"/>
-    <binding key="D" mask="CTL_ALT" command="spin_around_ccw"/>
     <binding key="W" mask="CTL_ALT" command="spin_over"/>
     <binding key="S" mask="CTL_ALT" command="spin_under"/>
-    <binding key="E" mask="CTL_ALT" command="spin_over"/>
-    <binding key="C" mask="CTL_ALT" command="spin_under"/>
 
-    <binding key="LEFT" mask="CTL_ALT" command="spin_around_cw"/>
-    <binding key="RIGHT" mask="CTL_ALT" command="spin_around_ccw"/>
     <binding key="UP" mask="CTL_ALT" command="spin_over"/>
     <binding key="DOWN" mask="CTL_ALT" command="spin_under"/>
-    <binding key="PGUP" mask="CTL_ALT" command="spin_over"/>
-    <binding key="PGDN" mask="CTL_ALT" command="spin_under"/>
 
-    <binding key="PAD_LEFT" mask="CTL_ALT" command="spin_around_cw"/>
-    <binding key="PAD_RIGHT" mask="CTL_ALT" command="spin_around_ccw"/>
     <binding key="PAD_UP" mask="CTL_ALT" command="spin_over"/>
     <binding key="PAD_DOWN" mask="CTL_ALT" command="spin_under"/>
-    <binding key="PAD_PGUP" mask="CTL_ALT" command="spin_over"/>
-    <binding key="PAD_PGDN" mask="CTL_ALT" command="spin_under"/>
-    <binding key="PAD_ENTER" mask="CTL_ALT" command="start_chat"/>
-    <binding key="PAD_DIVIDE" mask="CTL_ALT" command="start_gesture"/>
 
     <!--Therefore pan on Alt-Shift-->
     <binding key="A" mask="CTL_ALT_SHIFT" command="pan_left"/>
@@ -179,63 +125,10 @@
     <binding key="PAD_DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
     <binding key="PAD_ENTER" mask="CTL_ALT_SHIFT" command="start_chat"/>
     <binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
-  </third_person>
 
-  <!-- Basic editing camera control -->
-  <edit>
-    <binding key="A" mask="NONE" command="spin_around_cw"/>
-    <binding key="D" mask="NONE" command="spin_around_ccw"/>
-    <binding key="W" mask="NONE" command="move_forward"/>
-    <binding key="S" mask="NONE" command="move_backward"/>
-    <binding key="E" mask="NONE" command="spin_over"/>
-    <binding key="C" mask="NONE" command="spin_under"/>
-    <binding key="ENTER" mask="NONE" command="start_chat"/>
-    <binding key="DIVIDE" mask="NONE" command="start_gesture"/>
-    <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
-    <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
-
-    <binding key="LEFT" mask="NONE" command="spin_around_cw"/>
-    <binding key="RIGHT" mask="NONE" command="spin_around_ccw"/>
-    <binding key="UP" mask="NONE" command="move_forward"/>
-    <binding key="DOWN" mask="NONE" command="move_backward"/>
-    <binding key="PGUP" mask="NONE" command="spin_over"/>
-    <binding key="PGDN" mask="NONE" command="spin_under"/>
-
-    <binding key="A" mask="SHIFT" command="pan_left"/>
-    <binding key="D" mask="SHIFT" command="pan_right"/>
-    <binding key="W" mask="SHIFT" command="pan_up"/>
-    <binding key="S" mask="SHIFT" command="pan_down"/>
-
-    <binding key="LEFT" mask="SHIFT" command="pan_left"/>
-    <binding key="RIGHT" mask="SHIFT" command="pan_right"/>
-    <binding key="UP" mask="SHIFT" command="pan_up"/>
-    <binding key="DOWN" mask="SHIFT" command="pan_down"/>
-
-    <!--Walking works with ALT held down.-->
-    <binding key="A" mask="ALT" command="slide_left"/>
-    <binding key="D" mask="ALT" command="slide_right"/>
-    <binding key="W" mask="ALT" command="push_forward"/>
-    <binding key="S" mask="ALT" command="push_backward"/>
-    <binding key="E" mask="ALT" command="jump"/>
-    <binding key="C" mask="ALT" command="push_down"/>
-
-    <binding key="LEFT" mask="ALT" command="slide_left"/>
-    <binding key="RIGHT" mask="ALT" command="slide_right"/>
-    <binding key="UP" mask="ALT" command="push_forward"/>
-    <binding key="DOWN" mask="ALT" command="push_backward"/>
-    <binding key="PGUP" mask="ALT" command="jump"/>
-    <binding key="PGDN" mask="ALT" command="push_down"/>
-    <binding key="HOME" mask="ALT" command="toggle_fly"/>
-
-    <binding key="PAD_LEFT" mask="ALT" command="slide_left"/>
-    <binding key="PAD_RIGHT" mask="ALT" command="slide_right"/>
-    <binding key="PAD_UP" mask="ALT" command="push_forward"/>
-    <binding key="PAD_DOWN" mask="ALT" command="push_backward"/>
-    <binding key="PAD_PGUP" mask="ALT" command="jump"/>
-    <binding key="PAD_PGDN" mask="ALT" command="push_down"/>
-    <binding key="PAD_ENTER" mask="ALT" command="start_chat"/>
-    <binding key="PAD_DIVIDE" mask="ALT" command="start_gesture"/>
-  </edit>
+    <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+    <binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
+  </third_person>
   <sitting>
     <binding key="A" mask="ALT" command="spin_around_cw"/>
     <binding key="D" mask="ALT" command="spin_around_ccw"/>
@@ -251,15 +144,11 @@
     <binding key="PGUP" mask="ALT" command="spin_over"/>
     <binding key="PGDN" mask="ALT" command="spin_under"/>
 
-    <binding key="A" mask="CTL_ALT" command="spin_around_cw"/>
-    <binding key="D" mask="CTL_ALT" command="spin_around_ccw"/>
     <binding key="W" mask="CTL_ALT" command="spin_over"/>
     <binding key="S" mask="CTL_ALT" command="spin_under"/>
     <binding key="E" mask="CTL_ALT" command="spin_over"/>
     <binding key="C" mask="CTL_ALT" command="spin_under"/>
 
-    <binding key="LEFT" mask="CTL_ALT" command="spin_around_cw"/>
-    <binding key="RIGHT" mask="CTL_ALT" command="spin_around_ccw"/>
     <binding key="UP" mask="CTL_ALT" command="spin_over"/>
     <binding key="DOWN" mask="CTL_ALT" command="spin_under"/>
     <binding key="PGUP" mask="CTL_ALT" command="spin_over"/>
@@ -294,23 +183,23 @@
     <binding key="A" mask="SHIFT" command="slide_left"/>
     <binding key="D" mask="SHIFT" command="slide_right"/>
     <binding key="W" mask="SHIFT" command="move_forward_sitting"/>
-	<binding key="S" mask="SHIFT" command="move_backward_sitting"/>
-	<binding key="E" mask="SHIFT" command="spin_over_sitting"/>
-	<binding key="C" mask="SHIFT" command="spin_under_sitting"/>
+    <binding key="S" mask="SHIFT" command="move_backward_sitting"/>
+    <binding key="E" mask="SHIFT" command="spin_over_sitting"/>
+    <binding key="C" mask="SHIFT" command="spin_under_sitting"/>
 
     <binding key="LEFT" mask="SHIFT" command="slide_left"/>
     <binding key="RIGHT" mask="SHIFT" command="slide_right"/>
     <binding key="UP" mask="SHIFT" command="move_forward_sitting"/>
-	<binding key="DOWN" mask="SHIFT" command="move_backward_sitting"/>
-	<binding key="PGUP" mask="SHIFT" command="spin_over_sitting"/>
-	<binding key="PGDN" mask="SHIFT" command="spin_under_sitting"/>
+    <binding key="DOWN" mask="SHIFT" command="move_backward_sitting"/>
+    <binding key="PGUP" mask="SHIFT" command="spin_over_sitting"/>
+    <binding key="PGDN" mask="SHIFT" command="spin_under_sitting"/>
 
     <binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
     <binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
     <binding key="PAD_UP" mask="SHIFT" command="move_forward_sitting"/>
-	<binding key="PAD_DOWN" mask="SHIFT" command="move_backward_sitting"/>
-	<binding key="PAD_PGUP" mask="SHIFT" command="spin_over_sitting"/>
-	<binding key="PAD_PGDN" mask="SHIFT" command="spin_under_sitting"/> 
+    <binding key="PAD_DOWN" mask="SHIFT" command="move_backward_sitting"/>
+    <binding key="PAD_PGUP" mask="SHIFT" command="spin_over_sitting"/>
+    <binding key="PAD_PGDN" mask="SHIFT" command="spin_under_sitting"/> 
     <binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
     <binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
 
@@ -334,6 +223,9 @@
 
     <binding key="ENTER" mask="NONE" command="start_chat"/>
     <binding key="DIVIDE" mask="NONE" command="start_gesture"/>
+
+    <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+    <binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
   </sitting>
   <edit_avatar>
     <!--Avatar editing camera controls-->
@@ -359,5 +251,7 @@
     <binding key="PAD_PGDN" mask="NONE" command="edit_avatar_spin_under"/>
     <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
     <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
+
+    <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
   </edit_avatar>
-</keys>
\ No newline at end of file
+</keys>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 49601ae98f6fc992923710d30b31a0ad6934fa17..bbac65ef61bbde7ee153106ae7f1858339574524 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -3494,7 +3494,7 @@
     <key>DoubleClickAutoPilot</key>
     <map>
       <key>Comment</key>
-      <string>Enable double-click auto pilot</string>
+      <string>(Obsolete)Enable double-click auto pilot</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
@@ -3505,13 +3505,13 @@
     <key>DoubleClickTeleport</key>
     <map>
       <key>Comment</key>
-      <string>Enable double-click to teleport where allowed</string>
+      <string>Enable double-click to teleport where allowed (afects minimap and people panel)</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
-      <integer>0</integer>
+      <integer>1</integer>
     </map>
     <key>DoubleClickShowWorldMap</key>
     <map>
@@ -4913,7 +4913,7 @@
     <key>InventoryOutboxDisplayBoth</key>
     <map>
         <key>Comment</key>
-        <string>Show the legacy Merchant Outbox UI as well as the Marketplace Listings UI</string>
+        <string>(Deprecated) Show the legacy Merchant Outbox UI as well as the Marketplace Listings UI</string>
         <key>Persist</key>
         <integer>1</integer>
         <key>Type</key>
@@ -5304,7 +5304,7 @@
       <key>Type</key>
       <string>String</string>
       <key>Value</key>
-      <string>https://secondlife-status.statuspage.io/history.atom</string>
+      <string>https://status.secondlifegrid.net/history.atom</string>
     </map>
     <key>GridStatusUpdateDelay</key>
     <map>
@@ -7494,11 +7494,11 @@
     <key>ParcelMediaAutoPlayEnable</key>
     <map>
       <key>Comment</key>
-      <string>Auto play parcel media when available</string>
+      <string>Auto play parcel media when available. 0 - Do not autoplay; 1- Autoplay; 2 - Ask</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
-      <string>Boolean</string>
+      <string>S32</string>
       <key>Value</key>
       <integer>1</integer>
     </map>
@@ -8184,7 +8184,7 @@
     <key>PushToTalkButton</key>
     <map>
       <key>Comment</key>
-      <string>Which button or keyboard key is used for push-to-talk</string>
+      <string>(Obsolete)Which button or keyboard key is used for push-to-talk</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
@@ -8434,6 +8434,17 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>RememberUser</key>
+    <map>
+      <key>Comment</key>
+      <string>Keep user name for next login</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>RememberPassword</key>
     <map>
       <key>Comment</key>
@@ -9276,7 +9287,7 @@
   <key>RenderShadowResolutionScale</key>
   <map>
     <key>Comment</key>
-    <string>Scale of shadow map resolution vs. screen resolution</string>
+    <string>Scale of shadow map resolution vs. screen resolution (only positivie values are allowed)</string>
     <key>Persist</key>
     <integer>1</integer>
     <key>Type</key>
@@ -11219,6 +11230,17 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>BasicUITooltips</key>
+    <map>
+      <key>Comment</key>
+      <string>Show tooltips for various 2D UI elements like buttons or checkboxes, won't supress tooltips like drag'n'drop, inworld, links or media</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>ShowHoverTips</key>
     <map>
       <key>Comment</key>
@@ -13133,6 +13155,17 @@
       <key>Value</key>
       <real>3</real>
     </map>
+    <key>HUDScaleFactor</key>
+    <map>
+    <key>Comment</key>
+      <string>Scale of HUD attachments</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <real>1.0</real>
+    </map>
     <key>UIScaleFactor</key>
     <map>
       <key>Comment</key>
@@ -15331,7 +15364,7 @@
     <key>ClickToWalk</key>
     <map>
       <key>Comment</key>
-      <string>Click in world to walk to location</string>
+      <string>(obsolete)Click in world to walk to location</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 31b8b9051887cc0c1984709a23ae772d1fbeefae..0e43af91df11d17aba42279f16186f63974e7bfc 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -829,6 +829,17 @@ bool LLAgent::enableFlying()
 	return !sitting;
 }
 
+// static
+bool LLAgent::isSitting()
+{
+    BOOL sitting = FALSE;
+    if (isAgentAvatarValid())
+    {
+        sitting = gAgentAvatarp->isSitting();
+    }
+    return sitting;
+}
+
 void LLAgent::standUp()
 {
 	setControlFlags(AGENT_CONTROL_STAND_UP);
@@ -2022,6 +2033,14 @@ U8 LLAgent::getRenderState()
 //-----------------------------------------------------------------------------
 void LLAgent::endAnimationUpdateUI()
 {
+	if (LLApp::isExiting()
+		|| !gViewerWindow
+		|| !gMenuBarView
+		|| !gToolBarView
+		|| !gStatusBar)
+	{
+		return;
+	}
 	if (gAgentCamera.getCameraMode() == gAgentCamera.getLastCameraMode())
 	{
 		// We're already done endAnimationUpdateUI for this transition.
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 5ba1083d8efc345b2b7f48b138972da50758a7df..a5d37ef4969f502fa2ce087b269a8e9934a78bf7 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -343,6 +343,7 @@ class LLAgent : public LLOldEvents::LLObservable
 	static void		toggleFlying();
 	static bool		enableFlying();
 	BOOL			canFly(); 			// Does this parcel allow you to fly?
+	static bool		isSitting();
 
 	//--------------------------------------------------------------------
 	// Voice
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 0b4b848014e400fe14b882f4caa619f64c3e280f..c55c12e67058f916ce8fbc7ba4501e686390f227 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -282,6 +282,11 @@ LLAgentCamera::~LLAgentCamera()
 //-----------------------------------------------------------------------------
 void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera)
 {
+	if (gDisconnected)
+	{
+		return;
+	}
+
 	if (gAgent.getAutoPilot())
 	{
 		gAgent.stopAutoPilot(TRUE);
@@ -807,6 +812,12 @@ void LLAgentCamera::setCameraZoomFraction(F32 fraction)
 	startCameraAnimation();
 }
 
+F32 LLAgentCamera::getAgentHUDTargetZoom()
+{
+	static LLCachedControl<F32> hud_scale_factor(gSavedSettings, "HUDScaleFactor");
+	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+	return (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) ? hud_scale_factor*gAgentCamera.mHUDTargetZoom : hud_scale_factor;
+}
 
 //-----------------------------------------------------------------------------
 // cameraOrbitAround()
diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h
index d087de1e2ff5d55227ea3bb700faf579b818f139..a4bc8434b0c982892ff99b8710e6a4d721ed9d4f 100644
--- a/indra/newview/llagentcamera.h
+++ b/indra/newview/llagentcamera.h
@@ -266,6 +266,7 @@ class LLAgentCamera
 	F32				getCameraZoomFraction();				// Get camera zoom as fraction of minimum and maximum zoom
 	void			setCameraZoomFraction(F32 fraction);	// Set camera zoom as fraction of minimum and maximum zoom
 	F32				calcCameraFOVZoomFactor();
+	F32				getAgentHUDTargetZoom();
 
 	//--------------------------------------------------------------------
 	// Pan
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 7325ec598a17ed1977a8b49b8694c7056569da69..fb864f18c1568731d4846baaa92fbf03bd1d8b78 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1713,6 +1713,24 @@ void LLAppearanceMgr::slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_
 	LLInventoryModel::item_array_t* items;
 	LLSD contents = LLSD::emptyArray();
 	gInventory.getDirectDescendentsOf(src_id, cats, items);
+	if (!cats || !items)
+	{
+		// NULL means the call failed -- cats/items map doesn't exist (note: this does NOT mean
+		// that the cat just doesn't have any items or subfolders).
+		LLViewerInventoryCategory* category = gInventory.getCategory(src_id);
+		if (category)
+		{
+			LL_WARNS() << "Category '" << category->getName() << "' descendents corrupted, linking content failed." << LL_ENDL;
+		}
+		else
+		{
+			LL_WARNS() << "Category could not be retrieved, linking content failed." << LL_ENDL;
+		}
+		llassert(cats != NULL && items != NULL);
+
+		return;
+	}
+
 	LL_INFOS() << "copying " << items->size() << " items" << LL_ENDL;
 	for (LLInventoryModel::item_array_t::const_iterator iter = items->begin();
 		 iter != items->end();
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index ff897ef9624739691e3550988c885aff3368d4ec..3e33815b206b3d891835b66400ae3255aa99d1a5 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -61,13 +61,16 @@
 #include "llallocator.h"
 #include "llcalc.h"
 #include "llconversationlog.h"
+#if LL_WINDOWS
 #include "lldxhardware.h"
+#endif
 #include "lltexturestats.h"
 #include "lltrace.h"
 #include "lltracethreadrecorder.h"
 #include "llviewerwindow.h"
 #include "llviewerdisplay.h"
 #include "llviewermedia.h"
+#include "llviewerparcelaskplay.h"
 #include "llviewerparcelmedia.h"
 #include "llviewermediafocus.h"
 #include "llviewermessage.h"
@@ -145,7 +148,7 @@
 #include "llapr.h"
 #include <boost/lexical_cast.hpp>
 
-#include "llviewerkeyboard.h"
+#include "llviewerinput.h"
 #include "lllfsthread.h"
 #include "llworkerthread.h"
 #include "lltexturecache.h"
@@ -994,20 +997,15 @@ bool LLAppViewer::init()
 	gGLManager.getGLInfo(gDebugInfo);
 	gGLManager.printGLInfoString();
 
-	// Load Default bindings
-	std::string key_bindings_file = gDirUtilp->findFile("keys.xml",
-														gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
-														gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
-
-
-	if (!gViewerKeyboard.loadBindingsXML(key_bindings_file))
+	// Load User's bindings
+	std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml");
+	if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file))
 	{
-		std::string key_bindings_file = gDirUtilp->findFile("keys.ini",
-															gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
-															gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
-		if (!gViewerKeyboard.loadBindings(key_bindings_file))
+		// Failed to load custom bindings, try default ones
+		key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml");
+		if (!gViewerInput.loadBindingsXML(key_bindings_file))
 		{
-			LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
+			LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL;
 		}
 	}
 
@@ -1128,7 +1126,7 @@ bool LLAppViewer::init()
 	try {
 		initializeSecHandler();
 	}
-	catch (LLProtectedDataException ex)
+	catch (LLProtectedDataException&)
 	{
 	  LLNotificationsUtil::add("CorruptedProtectedDataStore");
 	}
@@ -1341,7 +1339,7 @@ bool LLAppViewer::frame()
 		{
 			LOG_UNHANDLED_EXCEPTION("");
 		}
-		catch (std::bad_alloc)
+		catch (std::bad_alloc&)
 		{
 			LLMemory::logMemoryInfo(TRUE);
 			LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
@@ -1438,6 +1436,7 @@ bool LLAppViewer::doFrame()
 			{
 				joystick->scanJoystick();
 				gKeyboard->scanKeyboard();
+                gViewerInput.scanMouse();
 			}
 
 			// Update state based on messages, user input, object idle.
@@ -1708,6 +1707,11 @@ bool LLAppViewer::cleanup()
 	disconnectViewer();
 
 	LL_INFOS() << "Viewer disconnected" << LL_ENDL;
+	
+	if (gKeyboard)
+	{
+		gKeyboard->resetKeys();
+	}
 
 	display_cleanup();
 
@@ -1923,6 +1927,11 @@ bool LLAppViewer::cleanup()
 	{
 		gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
 		LL_INFOS() << "Saved settings" << LL_ENDL;
+
+		if (LLViewerParcelAskPlay::instanceExists())
+		{
+			LLViewerParcelAskPlay::getInstance()->saveSettings();
+		}
 	}
 
 	std::string warnings_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Warnings"));
@@ -2125,6 +2134,9 @@ void watchdog_llerrs_callback(const std::string &error_string)
 {
 	gLLErrorActivated = true;
 
+	gDebugInfo["FatalMessage"] = error_string;
+	LLAppViewer::instance()->writeDebugInfo();
+
 #ifdef LL_WINDOWS
 	RaiseException(0,0,0,0);
 #else
@@ -3962,7 +3974,10 @@ static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_q
 
 void LLAppViewer::userQuit()
 {
-	if (gDisconnected || gViewerWindow->getProgressView()->getVisible())
+	if (gDisconnected
+		|| !gViewerWindow
+		|| !gViewerWindow->getProgressView()
+		|| gViewerWindow->getProgressView()->getVisible())
 	{
 		requestQuit();
 	}
@@ -4492,6 +4507,7 @@ void LLAppViewer::saveFinalSnapshot()
 									gViewerWindow->getWindowWidthRaw(),
 									gViewerWindow->getWindowHeightRaw(),
 									FALSE,
+									gSavedSettings.getBOOL("RenderHUDInSnapshot"),
 									TRUE,
 									LLSnapshotModel::SNAPSHOT_TYPE_COLOR,
 									LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
diff --git a/indra/newview/llaudiosourcevo.cpp b/indra/newview/llaudiosourcevo.cpp
index b37aba6c1520b10d6493967d7cf6a93ddd0be5d6..4b6c855bde3427eb74aabd2e4432fb23629bd385 100644
--- a/indra/newview/llaudiosourcevo.cpp
+++ b/indra/newview/llaudiosourcevo.cpp
@@ -29,8 +29,10 @@
 
 #include "llaudiosourcevo.h"
 
+#include "llagent.h"
 #include "llagentcamera.h"
 #include "llmutelist.h"
+#include "llviewercontrol.h"
 #include "llviewerparcelmgr.h"
 
 LLAudioSourceVO::LLAudioSourceVO(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, LLViewerObject *objectp)
@@ -54,6 +56,79 @@ void LLAudioSourceVO::setGain(const F32 gain)
 	mGain = llclamp(gain, 0.f, 1.f);
 }
 
+void LLAudioSourceVO::checkCutOffRadius()
+{
+    if (mSourceMuted // already muted by something, will be recalculated on update()
+        || !mObjectp)
+    {
+        return;
+    }
+
+    F32 cutoff = mObjectp->getSoundCutOffRadius();
+    if (cutoff < 0.1f)
+    {
+        // consider cutoff below 0.1m as off (to avoid near zero comparison)
+        return;
+    }
+
+    LLVector3d pos_global = getPosGlobal();
+    if (!isInCutOffRadius(pos_global, cutoff))
+    {
+        mSourceMuted = true;
+    }
+}
+
+LLVector3d LLAudioSourceVO::getPosGlobal() const
+{
+    if (mObjectp->isAttachment())
+    {
+        LLViewerObject* parent = mObjectp;
+        while (parent && !parent->isAvatar())
+        {
+            parent = (LLViewerObject*)parent->getParent();
+        }
+        if (parent)
+        {
+            return parent->getPositionGlobal();
+        }
+    }
+    else
+    {
+        return mObjectp->getPositionGlobal();
+    }
+    return LLVector3d();
+}
+
+bool LLAudioSourceVO::isInCutOffRadius(const LLVector3d pos_global, const F32 cutoff) const
+{
+    static LLCachedControl<S32> ear_mode(gSavedSettings, "VoiceEarLocation", 0);
+
+    LLVector3d pos_ear;
+
+    switch (ear_mode())
+    {
+        case 0: // camera
+            pos_ear = gAgentCamera.getCameraPositionGlobal();
+            break;
+
+        case 1: // avatar
+        case 2:
+            // voice support 'mixed' in '2' case with agent's position and camera's rotations
+            // but it is not defined in settings and uses camera as default
+            pos_ear = gAgent.getPositionGlobal();
+            break;
+
+        default:
+            pos_ear = gAgentCamera.getCameraPositionGlobal();
+            break;
+    }
+    LLVector3d to_vec = pos_global - pos_ear;
+
+    F32 dist = (F32)to_vec.magVec();
+
+    return dist < cutoff;
+}
+
 void LLAudioSourceVO::updateMute()
 {
 	if (!mObjectp || mObjectp->isDead())
@@ -63,26 +138,11 @@ void LLAudioSourceVO::updateMute()
 	}
 
 	bool mute = false;
-	LLVector3d pos_global;
-
-	if (mObjectp->isAttachment())
-	{
-		LLViewerObject* parent = mObjectp;
-		while (parent && !parent->isAvatar())
-		{
-			parent = (LLViewerObject*)parent->getParent();
-		}
-		if (parent)
-		{
-			pos_global = parent->getPositionGlobal();
-		}
-	}
-	else
-	{
-		pos_global = mObjectp->getPositionGlobal();
-	}
+	LLVector3d pos_global = getPosGlobal();
 
-	if (!LLViewerParcelMgr::getInstance()->canHearSound(pos_global))
+	F32 cutoff = mObjectp->getSoundCutOffRadius();
+	if ((cutoff > 0.1f && !isInCutOffRadius(pos_global, cutoff)) // consider cutoff below 0.1m as off
+		|| !LLViewerParcelMgr::getInstance()->canHearSound(pos_global))
 	{
 		mute = true;
 	}
diff --git a/indra/newview/llaudiosourcevo.h b/indra/newview/llaudiosourcevo.h
index f1d8ef4528507b6be516b70cc54ac5edbc551b96..672a07f7d350f0b852236d08554b59119dd250e6 100644
--- a/indra/newview/llaudiosourcevo.h
+++ b/indra/newview/llaudiosourcevo.h
@@ -41,7 +41,11 @@ class LLAudioSourceVO : public LLAudioSource
 	/*virtual*/	void update();
 	/*virtual*/ void setGain(const F32 gain);
 
+	void checkCutOffRadius();
+
 private:
+	LLVector3d getPosGlobal() const;
+	bool isInCutOffRadius(LLVector3d pos_global, const F32 cutoff) const;
 	void updateMute();
 
 private:
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 1099d4bc09e1481233d1c41b3a64656ff5a5979f..722523830baa8f1d096e16d6804315fe73c24b89 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -1085,7 +1085,8 @@ LLView* LLChatHistory::getSeparator()
 LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style_params, const LLSD& args)
 {
 	LLChatHistoryHeader* header = LLChatHistoryHeader::createInstance(mMessageHeaderFilename);
-	header->setup(chat, style_params, args);
+    if (header)
+        header->setup(chat, style_params, args);
 	return header;
 }
 
@@ -1298,6 +1299,12 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 			view = getSeparator();
 			p.top_pad = mTopSeparatorPad;
 			p.bottom_pad = mBottomSeparatorPad;
+            if (!view)
+            {
+                // Might be wiser to make this LL_ERRS, getSeparator() should work in case of correct instalation.
+                LL_WARNS() << "Failed to create separator from " << mMessageSeparatorFilename << ": can't append to history" << LL_ENDL;
+                return;
+            }
 		}
 		else
 		{
@@ -1306,7 +1313,12 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
 				p.top_pad = 0;
 			else
 				p.top_pad = mTopHeaderPad;
-			p.bottom_pad = mBottomHeaderPad;
+            p.bottom_pad = mBottomHeaderPad;
+            if (!view)
+            {
+                LL_WARNS() << "Failed to create header from " << mMessageHeaderFilename << ": can't append to history" << LL_ENDL;
+                return;
+            }
 			
 		}
 		p.view = view;
diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index 92eeebd705446ad4a8f4bebbbf59fb5197d05aad..f0682dc1ba77a72fd346e60f68bb01d8bf559de3 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -171,7 +171,10 @@ void LLControlAvatar::matchVolumeTransform()
             if (attached_av)
             {
                 LLViewerJointAttachment *attach = attached_av->getTargetAttachmentPoint(mRootVolp);
-                setPositionAgent(mRootVolp->getRenderPosition());
+                if (getRegion() && !isDead())
+                {
+                    setPositionAgent(mRootVolp->getRenderPosition());
+                }
 				attach->updateWorldPRSParent();
                 LLVector3 joint_pos = attach->getWorldPosition();
                 LLQuaternion joint_rot = attach->getWorldRotation();
@@ -227,7 +230,10 @@ void LLControlAvatar::matchVolumeTransform()
 #endif
 			setRotation(bind_rot*obj_rot);
             mRoot->setWorldRotation(bind_rot*obj_rot);
-			setPositionAgent(vol_pos);
+            if (getRegion() && !isDead())
+            {
+                setPositionAgent(vol_pos);
+            }
 			mRoot->setPosition(vol_pos + mPositionConstraintFixup);
 
             F32 global_scale = gSavedSettings.getF32("AnimatedObjectsGlobalScale");
diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp
index f7c61efce07dc93bf1c1fe76ccb62d5190467a10..5539fa75dd4afb23b125514d78b2a310279b1db2 100644
--- a/indra/newview/llconversationlog.cpp
+++ b/indra/newview/llconversationlog.cpp
@@ -490,7 +490,7 @@ bool LLConversationLog::saveToFile(const std::string& filename)
 				(S32)conv_it->getConversationType(),
 				(S32)0,
 				(S32)conv_it->hasOfflineMessages(),
-				conv_it->getConversationName().c_str(),
+				LLURI::escape(conv_it->getConversationName()).c_str(),
 				participant_id.c_str(),
 				conversation_id.c_str(),
 				LLURI::escape(conv_it->getHistoryFileName()).c_str());
@@ -545,7 +545,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
 		params.time(LLUnits::Seconds::fromValue(time))
 			.conversation_type((SessionType)stype)
 			.has_offline_ims(has_offline_ims)
-			.conversation_name(conv_name_buffer)
+			.conversation_name(LLURI::unescape(conv_name_buffer))
 			.participant_id(LLUUID(part_id_buffer))
 			.session_id(LLUUID(conv_id_buffer))
 			.history_filename(LLURI::unescape(history_file_name));
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index 0075b621008ac03909d77dd3b30315b8090ecafd..60a5204547d158b630a7723042de398a92b1a773 100644
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -175,7 +175,7 @@ BOOL LLConversationViewSession::postBuild()
 				LLAvatarIconCtrl* icon = mItemPanel->getChild<LLAvatarIconCtrl>("avatar_icon");
 				icon->setVisible(true);
 				icon->setValue(session->mOtherParticipantID);
-				mSpeakingIndicator->setSpeakerId(gAgentID, session->mSessionID, true);
+				mSpeakingIndicator->setSpeakerId(session->mOtherParticipantID, session->mSessionID, true);
                 mHasArrow = false;
 			}
 			break;
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 1587903a1517e6b9fd9fb60f167bda344fb0574e..85ee33edb19234b99736aba2c106c52b4cd3a71e 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -456,7 +456,7 @@ void LLFace::setTextureIndex(U8 index)
 		}
 		else
 		{
-			if (mDrawInfo && !mDrawInfo->mTextureList.empty())
+			if (mDrawInfo && mDrawInfo->mTextureList.size() <= 1)
 			{
 				LL_ERRS() << "Face with no texture index references indexed texture draw info." << LL_ENDL;
 			}
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 5b4b7789b482f4c803266917d053e27bdc4b2ef1..347997a69a6ad9cef52cf76e2de55a567fe6b81f 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -1493,18 +1493,24 @@ void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id)
 }
 
 // static
-std::string LLFavoritesOrderStorage::getStoredFavoritesFilename()
+std::string LLFavoritesOrderStorage::getStoredFavoritesFilename(const std::string &grid)
 {
-	std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
+    std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
 
     return (user_dir.empty() ? ""
             : gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
                                              "stored_favorites_"
-                                          + LLGridManager::getInstance()->getGrid()
+                                          + grid
                                           + ".xml")
             );
 }
 
+// static
+std::string LLFavoritesOrderStorage::getStoredFavoritesFilename()
+{
+    return getStoredFavoritesFilename(LLGridManager::getInstance()->getGrid());
+}
+
 // static
 void LLFavoritesOrderStorage::destroyClass()
 {
@@ -1584,14 +1590,29 @@ void LLFavoritesOrderStorage::load()
 												<< (fav_llsd.isMap() ? "" : "un") << "successfully"
 												<< LL_ENDL;
 				in_file.close();
-				user_llsd = fav_llsd[gAgentUsername];
+				if (fav_llsd.isMap() && fav_llsd.has(gAgentUsername))
+				{
+					user_llsd = fav_llsd[gAgentUsername];
 
-				S32 index = 0;
-				for (LLSD::array_iterator iter = user_llsd.beginArray();
+					S32 index = 0;
+					bool needs_validation = gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin");
+					for (LLSD::array_iterator iter = user_llsd.beginArray();
 						iter != user_llsd.endArray(); ++iter)
-				{
-					mSortIndexes.insert(std::make_pair(iter->get("id").asUUID(), index));
-					index++;
+					{
+						// Validation
+						LLUUID fv_id = iter->get("id").asUUID();
+						if (needs_validation
+							&& (fv_id.isNull()
+								|| iter->get("asset_id").asUUID().isNull()
+								|| iter->get("name").asString().empty()
+								|| iter->get("slurl").asString().empty()))
+						{
+							mRecreateFavoriteStorage = true;
+						}
+
+						mSortIndexes.insert(std::make_pair(fv_id, index));
+						index++;
+					}
 				}
 			}
 			else
@@ -1602,6 +1623,64 @@ void LLFavoritesOrderStorage::load()
 	}
 }
 
+// static
+void LLFavoritesOrderStorage::removeFavoritesRecordOfUser(const std::string &user, const std::string &grid)
+{
+    std::string filename = getStoredFavoritesFilename(grid);
+    if (!filename.empty())
+    {
+        LLSD fav_llsd;
+        llifstream file;
+        file.open(filename.c_str());
+        if (file.is_open())
+        {
+            LLSDSerialize::fromXML(fav_llsd, file);
+            file.close();
+
+            // Note : use the "John Doe" and not the "john.doe" version of the name.
+            // See saveFavoritesSLURLs() here above for the reason why.
+            if (fav_llsd.has(user))
+            {
+                LLSD user_llsd = fav_llsd[user];
+
+                if ((user_llsd.beginArray() != user_llsd.endArray()) && user_llsd.beginArray()->has("id"))
+                {
+                    for (LLSD::array_iterator iter = user_llsd.beginArray(); iter != user_llsd.endArray(); ++iter)
+                    {
+                        LLSD value;
+                        value["id"] = iter->get("id").asUUID();
+                        iter->assign(value);
+                    }
+                    fav_llsd[user] = user_llsd;
+                    llofstream file;
+                    file.open(filename.c_str());
+                    if (file.is_open())
+                    {
+                        LLSDSerialize::toPrettyXML(fav_llsd, file);
+                        file.close();
+                    }
+                }
+                else
+                {
+                    LL_INFOS("FavoritesBar") << "Removed favorites for " << user << LL_ENDL;
+                    fav_llsd.erase(user);
+                }
+            }
+
+            llofstream out_file;
+            out_file.open(filename.c_str());
+            if (out_file.is_open())
+            {
+                LLSDSerialize::toPrettyXML(fav_llsd, out_file);
+                LL_INFOS("FavoritesBar") << "saved favorites to '" << filename << "' "
+                    << LL_ENDL;
+                out_file.close();
+            }
+        }
+    }
+}
+
+// static
 void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
 {
 	std::string filename = getStoredFavoritesFilename();
@@ -1777,6 +1856,8 @@ void LLFavoritesOrderStorage::rearrangeFavoriteLandmarks(const LLUUID& source_it
 
 BOOL LLFavoritesOrderStorage::saveFavoritesRecord(bool pref_changed)
 {
+	pref_changed |= mRecreateFavoriteStorage;
+	mRecreateFavoriteStorage = false;
 
 	LLUUID favorite_folder= gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
 	if (favorite_folder.isNull())
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index cac32c7f2a6dfce51212e59a0e7e6cf08b28d753..571208aa31b201f1c42e73c8cbf63668daa7eec7 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -208,9 +208,15 @@ class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage>
 	 * @see cleanup()
 	 */
 	static void destroyClass();
+	static std::string getStoredFavoritesFilename(const std::string &grid);
 	static std::string getStoredFavoritesFilename();
 	static std::string getSavedOrderFileName();
 
+	// Remove record of specified user's favorites from file on disk.
+	static void removeFavoritesRecordOfUser(const std::string &user, const std::string &grid);
+	// Remove record of current user's favorites from file on disk.
+	static void removeFavoritesRecordOfUser();
+
 	BOOL saveFavoritesRecord(bool pref_changed = false);
 	void showFavoritesOnLoginChanged(BOOL show);
 
@@ -232,9 +238,6 @@ class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage>
 
 	void load();
 
-	// Remove record of current user's favorites from file on disk.
-	void removeFavoritesRecordOfUser();
-
 	void onLandmarkLoaded(const LLUUID& asset_id, class LLLandmark* landmark);
 	void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl);
 
@@ -245,6 +248,7 @@ class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage>
 	slurls_map_t mSLURLs;
 	std::set<LLUUID> mMissingSLURLs;
 	bool mIsDirty;
+	bool mRecreateFavoriteStorage;
 
 	struct IsNotInFavorites
 	{
@@ -275,7 +279,9 @@ class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage>
 
 inline
 LLFavoritesOrderStorage::LLFavoritesOrderStorage() :
-	mIsDirty(false), mUpdateRequired(false)
+	mIsDirty(false),
+	mUpdateRequired(false),
+	mRecreateFavoriteStorage(false)
 { load(); }
 
 #endif // LL_LLFAVORITESBARCTRL_H
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index 56619e818af2526f399da48e11796809130da5c5..957b2e1e8ef008d21980b77b1b09bebc653b5865 100644
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -182,8 +182,11 @@ void LLFloaterAuction::onClickSnapshot(void* data)
 	BOOL success = gViewerWindow->rawSnapshot(raw,
 											  gViewerWindow->getWindowWidthScaled(),
 											  gViewerWindow->getWindowHeightScaled(),
-											  TRUE, FALSE,
-											  FALSE, FALSE);
+											  TRUE,
+											  FALSE,
+											  FALSE, //UI
+											  FALSE, //HUD
+											  FALSE);
 	gForceRenderLandFence = FALSE;
 
 	if (success)
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 33099db1b946c0b10f8ace73c6b1cd4e26eb95a3..ab95bc06b889f1fcbdf7da58130dc6690561e77f 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -361,59 +361,8 @@ void LLFloaterAvatarPicker::populateFriend()
 
 void LLFloaterAvatarPicker::drawFrustum()
 {
-    if(mFrustumOrigin.get())
-    {
-        LLView * frustumOrigin = mFrustumOrigin.get();
-        LLRect origin_rect;
-        frustumOrigin->localRectToOtherView(frustumOrigin->getLocalRect(), &origin_rect, this);
-        // draw context cone connecting color picker with color swatch in parent floater
-        LLRect local_rect = getLocalRect();
-        if (hasFocus() && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f)
-        {
-            gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-            LLGLEnable(GL_CULL_FACE);
-            gGL.begin(LLRender::QUADS);
-            {
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-                gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
-                gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-                gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-                gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-                gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-                gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-                gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
-                gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
-
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-                gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-                gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-                gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
-                gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
-
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-                gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-                gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-                gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
-                gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
-            }
-            gGL.end();
-        }
-
-        if (gFocusMgr.childHasMouseCapture(getDragHandle()))
-        {
-            mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLSmoothInterpolation::getInterpolant(mContextConeFadeTime));
-        }
-        else
-        {
-            mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(mContextConeFadeTime));
-        }
-    }
+    static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
+    drawConeToOwner(mContextConeOpacity, max_opacity, mFrustumOrigin.get(), mContextConeFadeTime, mContextConeInAlpha, mContextConeOutAlpha);
 }
 
 void LLFloaterAvatarPicker::draw()
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index ec2c9740afe9846836ce5632a7b0e5f2b8f01689..1a784223c2eb0084645ccef108fb203e3f09fcff 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -485,56 +485,8 @@ BOOL LLFloaterColorPicker::isColorChanged()
 //
 void LLFloaterColorPicker::draw()
 {
-	LLRect swatch_rect;
-	mSwatch->localRectToOtherView(mSwatch->getLocalRect(), &swatch_rect, this);
-	// draw context cone connecting color picker with color swatch in parent floater
-	LLRect local_rect = getLocalRect();
-	if (hasFocus() && mSwatch->isInVisibleChain() && mContextConeOpacity > 0.001f)
-	{
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		LLGLEnable(GL_CULL_FACE);
-		gGL.begin(LLRender::QUADS);
-		{
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-			gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop);
-			gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop);
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-			gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-			gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-			gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-			gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-			gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom);
-			gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop);
-
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-			gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-			gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-			gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop);
-			gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom);
-
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-			gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-			gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-			gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom);
-			gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom);
-		}
-		gGL.end();
-	}
-
-	if (gFocusMgr.childHasMouseCapture(getDragHandle()))
-	{
-		mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), 
-                                        LLSmoothInterpolation::getInterpolant(mContextConeFadeTime));
-	}
-	else
-	{
-		mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(mContextConeFadeTime));
-	}
+	static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
+	drawConeToOwner(mContextConeOpacity, max_opacity, mSwatch, mContextConeFadeTime, mContextConeInAlpha, mContextConeOutAlpha);
 
 	mPipetteBtn->setToggleState(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance());
 	mApplyImmediateCheck->setEnabled(mActive && mCanApplyImmediately);
diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp
index 55561fa1281c35bb39b9c2d93bfb874a979c1eb9..44725cab7023cfbe4eb027fb598b70d4b226cc55 100644
--- a/indra/newview/llfloaterconversationpreview.cpp
+++ b/indra/newview/llfloaterconversationpreview.cpp
@@ -50,6 +50,7 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_i
 	mShowHistory(false),
 	mMessages(NULL),
 	mHistoryThreadsBusy(false),
+	mIsGroup(false),
 	mOpened(false)
 {
 }
@@ -75,6 +76,7 @@ BOOL LLFloaterConversationPreview::postBuild()
 	{
 		name = conv->getConversationName();
 		file = conv->getHistoryFileName();
+		mIsGroup = (LLIMModel::LLIMSession::GROUP_SESSION == conv->getConversationType());
 	}
 	else
 	{
@@ -82,6 +84,10 @@ BOOL LLFloaterConversationPreview::postBuild()
 		file = "chat";
 	}
 	mChatHistoryFileName = file;
+	if (mIsGroup)
+	{
+		mChatHistoryFileName += GROUP_CHAT_SUFFIX;
+	}
 	LLStringUtil::format_map_t args;
 	args["[NAME]"] = name;
 	std::string title = getString("Title", args);
@@ -145,6 +151,7 @@ void LLFloaterConversationPreview::onOpen(const LLSD& key)
 	LLSD load_params;
 	load_params["load_all_history"] = true;
 	load_params["cut_off_todays_date"] = false;
+	load_params["is_group"] = mIsGroup;
 
 	// The temporary message list with "Loading..." text
 	// Will be deleted upon loading completion in setPages() method
diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h
index a8dbbc9ffe0c112721f984dfcd1dd821afbe82e4..7ca4ee6945cceb3e6230cb7a0231f9f171146574 100644
--- a/indra/newview/llfloaterconversationpreview.h
+++ b/indra/newview/llfloaterconversationpreview.h
@@ -66,6 +66,7 @@ class LLFloaterConversationPreview : public LLFloater
 	bool			mShowHistory;
 	bool			mHistoryThreadsBusy;
 	bool			mOpened;
+	bool			mIsGroup;
 };
 
 #endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */
diff --git a/indra/newview/llfloaterexperiencepicker.cpp b/indra/newview/llfloaterexperiencepicker.cpp
index bb54c57baf1a23ed33ee0fc4591ea2d9f9bbf50d..c642da7b83b104554023dd2aa4e0eff54f393f12 100644
--- a/indra/newview/llfloaterexperiencepicker.cpp
+++ b/indra/newview/llfloaterexperiencepicker.cpp
@@ -74,59 +74,8 @@ LLFloaterExperiencePicker* LLFloaterExperiencePicker::show( select_callback_t ca
 
 void LLFloaterExperiencePicker::drawFrustum()
 {
-	if(mFrustumOrigin.get())
-	{
-		LLView * frustumOrigin = mFrustumOrigin.get();
-		LLRect origin_rect;
-		frustumOrigin->localRectToOtherView(frustumOrigin->getLocalRect(), &origin_rect, this);
-		// draw context cone connecting color picker with color swatch in parent floater
-		LLRect local_rect = getLocalRect();
-		if (hasFocus() && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f)
-		{
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			LLGLEnable(GL_CULL_FACE);
-			gGL.begin(LLRender::QUADS);
-			{
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-				gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
-				gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-				gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
-				gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
-
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-				gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-				gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
-				gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
-
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-				gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-				gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
-				gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
-			}
-			gGL.end();
-		}
-
-		if (gFocusMgr.childHasMouseCapture(getDragHandle()))
-		{
-			mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime));
-		}
-		else
-		{
-			mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime));
-		}
-	}
+    static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
+    drawConeToOwner(mContextConeOpacity, max_opacity, mFrustumOrigin.get(), mContextConeFadeTime, mContextConeInAlpha, mContextConeOutAlpha);
 }
 
 void LLFloaterExperiencePicker::draw()
diff --git a/indra/newview/llfloaterexperiences.cpp b/indra/newview/llfloaterexperiences.cpp
index fdc1b473341f0be8e4bfb96996d7e768e9a18211..184e39402a47d229b4db97d300cddd3f8599fd4f 100644
--- a/indra/newview/llfloaterexperiences.cpp
+++ b/indra/newview/llfloaterexperiences.cpp
@@ -74,10 +74,6 @@ BOOL LLFloaterExperiences::postBuild()
 	getChild<LLTabContainer>("xp_tabs")->addTabPanel(new LLPanelExperienceLog());
     resizeToTabs();
 
-   
-    LLEventPumps::instance().obtain("experience_permission").listen("LLFloaterExperiences", 
-        boost::bind(&LLFloaterExperiences::updatePermissions, this, _1));
-     
    	return TRUE;
 }
 
@@ -163,6 +159,10 @@ void LLFloaterExperiences::refreshContents()
 
 void LLFloaterExperiences::onOpen( const LLSD& key )
 {
+    LLEventPumps::instance().obtain("experience_permission").stopListening("LLFloaterExperiences");
+    LLEventPumps::instance().obtain("experience_permission").listen("LLFloaterExperiences",
+        boost::bind(&LLFloaterExperiences::updatePermissions, this, _1));
+
     LLViewerRegion* region = gAgent.getRegion();
     if(region)
     {
diff --git a/indra/newview/llfloaterforgetuser.cpp b/indra/newview/llfloaterforgetuser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5659cb2f793fb780cdb0290dc3a3c6676b302585
--- /dev/null
+++ b/indra/newview/llfloaterforgetuser.cpp
@@ -0,0 +1,154 @@
+/** 
+ * @file llfloaterforgetuser.cpp
+ * @brief LLFloaterForgetUser class definition.
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, 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 "llviewerprecompiledheaders.h"
+
+#include "llfloaterforgetuser.h"
+
+#include "llcheckboxctrl.h"
+#include "llfavoritesbar.h"
+#include "llpanellogin.h"        // for helper function getUserName() and to repopulate list if nessesary
+#include "llscrolllistctrl.h"
+#include "llsecapi.h"
+#include "llviewernetwork.h"
+
+
+LLFloaterForgetUser::LLFloaterForgetUser(const LLSD &key)
+    : LLFloater("floater_forget_user"),
+    mLoginPanelDirty(false)
+{
+
+}
+
+LLFloaterForgetUser::~LLFloaterForgetUser()
+{
+    if (mLoginPanelDirty)
+    {
+        LLPanelLogin::resetFields();
+    }
+}
+
+BOOL LLFloaterForgetUser::postBuild()
+{
+    // Note, storage works per grid, watever is selected currently in login screen or logged in.
+    // Since login screen can change grid, store the value.
+    mGrid = LLGridManager::getInstance()->getGrid();
+
+    LLScrollListCtrl *scroll_list = getChild<LLScrollListCtrl>("user_list");
+    if (gSecAPIHandler->hasCredentialMap("login_list", mGrid))
+    {
+        LLSecAPIHandler::credential_map_t credencials;
+        gSecAPIHandler->loadCredentialMap("login_list", mGrid, credencials);
+
+        LLSecAPIHandler::credential_map_t::iterator cr_iter = credencials.begin();
+        LLSecAPIHandler::credential_map_t::iterator cr_end = credencials.end();
+        while (cr_iter != cr_end)
+        {
+            if (cr_iter->second.notNull()) // basic safety
+            {
+                LLScrollListItem::Params item_params;
+                item_params.value(cr_iter->first);
+                item_params.columns.add()
+                    .value(LLPanelLogin::getUserName(cr_iter->second))
+                    .column("user")
+                    .font(LLFontGL::getFontSansSerifSmall());
+                scroll_list->addRow(item_params, ADD_BOTTOM);
+            }
+            cr_iter++;
+        }
+        scroll_list->selectFirstItem();
+    }
+    else
+    {
+        LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(mGrid);
+        if (cred.notNull())
+        {
+            LLScrollListItem::Params item_params;
+            item_params.value(cred->userID());
+            item_params.columns.add()
+                .value(LLPanelLogin::getUserName(cred))
+                .column("user")
+                .font(LLFontGL::getFontSansSerifSmall());
+            scroll_list->addRow(item_params, ADD_BOTTOM);
+            scroll_list->selectFirstItem();
+        }
+    }
+
+    bool enable_button = scroll_list->getFirstSelectedIndex() != -1;
+    getChild<LLView>("delete_data")->setEnabled(enable_button);
+    LLButton *button = getChild<LLButton>("forget");
+    button->setEnabled(enable_button);
+    button->setCommitCallback(boost::bind(&LLFloaterForgetUser::onForgetClicked, this));
+
+    return TRUE;
+}
+
+void LLFloaterForgetUser::onForgetClicked()
+{
+    mLoginPanelDirty = true;
+    LLScrollListCtrl *scroll_list = getChild<LLScrollListCtrl>("user_list");
+    std::string user_key = scroll_list->getSelectedValue();
+
+    // remove creds
+    gSecAPIHandler->removeFromCredentialMap("login_list", mGrid, user_key);
+
+    LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(mGrid);
+    if (cred.notNull() && cred->userID() == user_key)
+    {
+        gSecAPIHandler->deleteCredential(cred);
+    }
+
+    // Clean data
+    LLCheckBoxCtrl *chk_box = getChild<LLCheckBoxCtrl>("delete_data");
+    BOOL delete_data = chk_box->getValue();
+    if (delete_data)
+    {
+        // key is edentical to one we use for name of user's folder
+        std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + user_key;
+        gDirUtilp->deleteDirAndContents(user_path);
+
+        // Clean favorites, label is edentical to username
+        LLFavoritesOrderStorage::removeFavoritesRecordOfUser(scroll_list->getSelectedItemLabel(), mGrid);
+
+        // Note: we do not clean user-related files from cache because there are id dependent (inventory)
+        // files and cache has separate cleaning mechanism either way.
+        // Also this only cleans user from current grid, not all of them.
+    }
+
+
+    // Update UI
+    scroll_list->deleteSelectedItems();
+    scroll_list->selectFirstItem();
+    if (scroll_list->getFirstSelectedIndex() == -1)
+    {
+        LLButton *button = getChild<LLButton>("forget");
+        button->setEnabled(false);
+        chk_box->setEnabled(false);
+    }
+}
+
+
diff --git a/indra/newview/llfloaterforgetuser.h b/indra/newview/llfloaterforgetuser.h
new file mode 100644
index 0000000000000000000000000000000000000000..119aece2d10f522ab68fa7a3ffe80736f40ff6b0
--- /dev/null
+++ b/indra/newview/llfloaterforgetuser.h
@@ -0,0 +1,46 @@
+/** 
+ * @file llfloaterforgetuser.h
+ * @brief LLFloaterForgetUser class declaration.
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, 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$
+ */
+
+#ifndef LL_LLFLOATERFORGETUSER_H
+#define LL_LLFLOATERFORGETUSER_H
+
+#include "llfloater.h"
+
+class LLFloaterForgetUser : public LLFloater
+{
+public:
+    LLFloaterForgetUser(const LLSD &key);
+    ~LLFloaterForgetUser();
+
+    BOOL postBuild();
+    void onForgetClicked();
+
+private:
+    bool mLoginPanelDirty;
+    std::string mGrid;
+};
+
+#endif
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index b840d37c4d99fe0af8612c5452365468e760d6bf..e778e8eb9e14b7e831149165c3b2a526ae25d9ac 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -41,6 +41,7 @@
 #include "llkeyboard.h"
 #include "llmenugl.h"
 #include "llmultigesture.h"
+#include "llnotificationsutil.h"
 #include "llpreviewgesture.h"
 #include "llscrolllistctrl.h"
 #include "lltrans.h"
@@ -125,6 +126,7 @@ LLFloaterGesture::LLFloaterGesture(const LLSD& key)
 	mCommitCallbackRegistrar.add("Gesture.Action.ShowPreview", boost::bind(&LLFloaterGesture::onClickEdit, this));
 	mCommitCallbackRegistrar.add("Gesture.Action.CopyPaste", boost::bind(&LLFloaterGesture::onCopyPasteAction, this, _2));
 	mCommitCallbackRegistrar.add("Gesture.Action.SaveToCOF", boost::bind(&LLFloaterGesture::addToCurrentOutFit, this));
+	mCommitCallbackRegistrar.add("Gesture.Action.Rename", boost::bind(&LLFloaterGesture::onRenameSelected, this));
 
 	mEnableCallbackRegistrar.add("Gesture.EnableAction", boost::bind(&LLFloaterGesture::isActionEnabled, this, _2));
 }
@@ -430,6 +432,19 @@ bool LLFloaterGesture::isActionEnabled(const LLSD& command)
 	{
 		return	mGestureList->getAllSelected().size() == 1;
 	}
+	else if ("rename_gesture" == command_name)
+	{
+		if (mGestureList->getAllSelected().size() == 1)
+		{
+			LLViewerInventoryItem* item = gInventory.getItem(mGestureList->getCurrentID());
+
+			if (item && item->getPermissions().allowModifyBy(gAgentID))
+			{
+				return true;
+			}
+		}
+		return false;
+	}
 	return true;
 }
 
@@ -514,6 +529,44 @@ void LLFloaterGesture::onActivateBtnClick()
 	}
 }
 
+void LLFloaterGesture::onRenameSelected()
+{
+	LLViewerInventoryItem* gesture = gInventory.getItem(mGestureList->getCurrentID());
+	if (!gesture)
+	{
+		return;
+	}
+
+	LLSD args;
+	args["NAME"] = gesture->getName();
+
+	LLSD payload;
+	payload["gesture_id"] = mGestureList->getCurrentID();
+
+	LLNotificationsUtil::add("RenameGesture", args, payload, boost::bind(onGestureRename, _1, _2));
+
+}
+
+void LLFloaterGesture::onGestureRename(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (option != 0) return; // canceled
+
+	std::string new_name = response["new_name"].asString();
+	LLInventoryObject::correctInventoryName(new_name);
+	if (!new_name.empty())
+	{
+		LLUUID item_id = notification["payload"]["gesture_id"].asUUID();
+		LLViewerInventoryItem* gesture = gInventory.getItem(item_id);
+		if (gesture && (gesture->getName() != new_name))
+		{
+			LLSD updates;
+			updates["name"] = new_name;
+			update_inventory_item(item_id, updates, NULL);
+		}
+	}
+}
+
 void LLFloaterGesture::onCopyPasteAction(const LLSD& command)
 {
 	std::string command_name  = command.asString();
diff --git a/indra/newview/llfloatergesture.h b/indra/newview/llfloatergesture.h
index 8efb3e6461a901d1f865543d7a72b8681837d4c5..1d702c6704e17dfed42e634b7e3008c7d0da6e35 100644
--- a/indra/newview/llfloatergesture.h
+++ b/indra/newview/llfloatergesture.h
@@ -95,6 +95,9 @@ class LLFloaterGesture
 	void onCommitList();
 	void onCopyPasteAction(const LLSD& command);
 	void onDeleteSelected();
+	void onRenameSelected();
+
+	static void onGestureRename(const LLSD& notification, const LLSD& response);
 
 	LLUUID mSelectedID;
 	LLUUID mGestureFolderID;
diff --git a/indra/newview/llfloatergridstatus.cpp b/indra/newview/llfloatergridstatus.cpp
index c47ff1c1d926197b4b16b4f9f9b08715da5630e8..faa7e9f3db25886e3eb703c040c60c8db301ada7 100644
--- a/indra/newview/llfloatergridstatus.cpp
+++ b/indra/newview/llfloatergridstatus.cpp
@@ -39,7 +39,7 @@
 #include "llxmltree.h"
 
 std::map<std::string, std::string> LLFloaterGridStatus::sItemsMap;
-const std::string DEFAULT_GRID_STATUS_URL = "http://secondlife-status.statuspage.io/";
+const std::string DEFAULT_GRID_STATUS_URL = "http://status.secondlifegrid.net/";
 
 LLFloaterGridStatus::LLFloaterGridStatus(const Params& key) :
     LLFloaterWebContent(key),
diff --git a/indra/newview/llfloatergroupinvite.cpp b/indra/newview/llfloatergroupinvite.cpp
index 7fdba8734a6cac29dcd180aa99a21b73003bccdc..30c90ac184f3ef36f8149115ac1cdfa8d40ea06c 100644
--- a/indra/newview/llfloatergroupinvite.cpp
+++ b/indra/newview/llfloatergroupinvite.cpp
@@ -108,7 +108,7 @@ LLFloaterGroupInvite::~LLFloaterGroupInvite()
 }
 
 // static
-void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, uuid_vec_t *agent_ids)
+void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, uuid_vec_t *agent_ids, bool request_update)
 {
 	const LLFloater::Params& floater_params = LLFloater::getDefaultParams();
 	S32 floater_header_size = floater_params.header_height;
@@ -126,9 +126,12 @@ void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, uuid_vec_t *agen
 											 group_id,
 											 (LLFloaterGroupInvite*)NULL);
 
-	// refresh group information
-	gAgent.sendAgentDataUpdateRequest();
-	LLGroupMgr::getInstance()->clearGroupData(group_id);
+	if (request_update)
+	{
+		// refresh group information
+		gAgent.sendAgentDataUpdateRequest();
+		LLGroupMgr::getInstance()->clearGroupData(group_id);
+	}
 
 
 	if (!fgi)
diff --git a/indra/newview/llfloatergroupinvite.h b/indra/newview/llfloatergroupinvite.h
index f6a3ca55509b6c2a7e6c2b3b50a9e7fb50c4f58d..657e5711f0fdebf9ac043fdf27fd9b110d0a9447 100644
--- a/indra/newview/llfloatergroupinvite.h
+++ b/indra/newview/llfloatergroupinvite.h
@@ -37,7 +37,7 @@ class LLFloaterGroupInvite
 public:
 	virtual ~LLFloaterGroupInvite();
 
-	static void showForGroup(const LLUUID &group_id, uuid_vec_t *agent_ids = NULL);
+	static void showForGroup(const LLUUID &group_id, uuid_vec_t *agent_ids = NULL, bool request_update = true);
 
 protected:
 	LLFloaterGroupInvite(const LLUUID& group_id = LLUUID::null);
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 3098c6d11831c941fd2d769dadd3cb55df5b462a..d8f4360142e5ac4ba8c8f96cf01376f90f76a9ac 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -2209,7 +2209,7 @@ void LLPanelLandOptions::refreshSearch()
 	// effort to reduce search spam from small parcels.  See also
 	// the search crawler "grid-crawl.py" in secondlife.com/doc/app/search/ JC
 	const S32 MIN_PARCEL_AREA_FOR_SEARCH = 128;
-	bool large_enough = parcel->getArea() > MIN_PARCEL_AREA_FOR_SEARCH;
+	bool large_enough = parcel->getArea() >= MIN_PARCEL_AREA_FOR_SEARCH;
 	if (large_enough)
 	{
 		if (can_change)
diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp
index 10cce3bd22dcd5ff255bfe46405e7597916fc008..595d584799d2171765778d1505c99da818a7b174 100644
--- a/indra/newview/llfloaterlinkreplace.cpp
+++ b/indra/newview/llfloaterlinkreplace.cpp
@@ -32,6 +32,8 @@
 #include "llagent.h"
 #include "llappearancemgr.h"
 #include "lllineeditor.h"
+#include "llnotificationsutil.h"
+#include "llnotifications.h"
 #include "lltextbox.h"
 #include "llviewercontrol.h"
 
@@ -142,37 +144,72 @@ void LLFloaterLinkReplace::onStartClicked()
 		LL_WARNS() << "Cannot replace. Source and target are identical." << LL_ENDL;
 		return;
 	}
+	
+	const LLUUID& source_item_id = gInventory.getLinkedItemID(mSourceUUID);
+	LLViewerInventoryItem *source_item = gInventory.getItem(source_item_id);
+	const LLUUID& target_item_id = gInventory.getLinkedItemID(mTargetUUID);
+	LLViewerInventoryItem *target_item = gInventory.getItem(target_item_id);
 
-	LLInventoryModel::cat_array_t cat_array;
-	LLLinkedItemIDMatches is_linked_item_match(mSourceUUID);
-	gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
-									cat_array,
-									mRemainingInventoryItems,
-									LLInventoryModel::INCLUDE_TRASH,
-									is_linked_item_match);
-	LL_INFOS() << "Found " << mRemainingInventoryItems.size() << " inventory links that need to be replaced." << LL_ENDL;
 
-	if (mRemainingInventoryItems.size() > 0)
+	LLNotification::Params params("ConfirmReplaceLink");
+	params.functor.function(boost::bind(&LLFloaterLinkReplace::onStartClickedResponse, this, _1, _2));
+	if (source_item && source_item->isWearableType() && source_item->getWearableType() <= LLWearableType::WT_EYES)
 	{
-		LLViewerInventoryItem* target_item = gInventory.getItem(mTargetUUID);
-		if (target_item)
+		if(target_item && target_item->isWearableType() && source_item->getWearableType() == target_item->getWearableType())
 		{
-			mRemainingItems = (U32)mRemainingInventoryItems.size();
-
-			LLStringUtil::format_map_t args;
-			args["NUM"] = llformat("%d", mRemainingItems);
-			mStatusText->setText(getString("ItemsRemaining", args));
-
-			mStartBtn->setEnabled(FALSE);
-			mRefreshBtn->setEnabled(FALSE);
-
-			mEventTimer.start();
-			tick();
+			LLNotifications::instance().forceResponse(params, 0);
 		}
 		else
 		{
-			mStatusText->setText(getString("TargetNotFound"));
-			LL_WARNS() << "Link replace target not found." << LL_ENDL;
+			LLSD args;
+			args["TYPE"] = LLWearableType::getTypeName(source_item->getWearableType());
+			params.substitutions(args);
+			LLNotifications::instance().add(params);
+		}
+	}
+	else
+	{		
+		LLNotifications::instance().forceResponse(params, 0);
+	}
+}
+
+void LLFloaterLinkReplace::onStartClickedResponse(const LLSD& notification, const LLSD& response)
+{
+
+	if (LLNotificationsUtil::getSelectedOption(notification, response) == 0)
+	{
+	
+		LLInventoryModel::cat_array_t cat_array;
+		LLLinkedItemIDMatches is_linked_item_match(mSourceUUID);
+		gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
+			cat_array,
+			mRemainingInventoryItems,
+			LLInventoryModel::INCLUDE_TRASH,
+			is_linked_item_match);
+		LL_INFOS() << "Found " << mRemainingInventoryItems.size() << " inventory links that need to be replaced." << LL_ENDL;
+
+		if (mRemainingInventoryItems.size() > 0)
+		{
+			LLViewerInventoryItem* target_item = gInventory.getItem(mTargetUUID);
+			if (target_item)
+			{
+				mRemainingItems = (U32)mRemainingInventoryItems.size();
+
+				LLStringUtil::format_map_t args;
+				args["NUM"] = llformat("%d", mRemainingItems);
+				mStatusText->setText(getString("ItemsRemaining", args));
+
+				mStartBtn->setEnabled(FALSE);
+				mRefreshBtn->setEnabled(FALSE);
+
+				mEventTimer.start();
+				tick();
+			}
+			else
+			{
+				mStatusText->setText(getString("TargetNotFound"));
+				LL_WARNS() << "Link replace target not found." << LL_ENDL;
+			}
 		}
 	}
 }
diff --git a/indra/newview/llfloaterlinkreplace.h b/indra/newview/llfloaterlinkreplace.h
index dd5c3012061fd89313b8b42afdf23182ff1b692e..060773f93e769d3e001bd3ba5a7923299a0fcd90 100644
--- a/indra/newview/llfloaterlinkreplace.h
+++ b/indra/newview/llfloaterlinkreplace.h
@@ -94,6 +94,7 @@ class LLFloaterLinkReplace : public LLFloater, LLEventTimer
 private:
 	void checkEnableStart();
 	void onStartClicked();
+	void onStartClickedResponse(const LLSD& notification, const LLSD& response);
 	void decreaseOpenItemCount();
 	void updateFoundLinks();
 	void processBatch(LLInventoryModel::item_array_t items);
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index b6efc1590ea3ec51d40fa3908510850b65df024c..e12ad262f820e7e9e985e46bb8f76e637425d63d 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -433,7 +433,7 @@ void LLFloaterModelPreview::initModelPreview()
 	mModelPreview = new LLModelPreview(512, 512, this );
 	mModelPreview->setPreviewTarget(16.f);
 	mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5));
-	mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this, _1));
+	mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelPreview::modelUpdated, this, _1));
 }
 
 void LLFloaterModelPreview::onViewOptionChecked(LLUICtrl* ctrl)
@@ -510,7 +510,8 @@ void LLFloaterModelPreview::onClickCalculateBtn()
 		mModelPreview->getPreviewAvatar()->showAttachmentOverrides();
     }
 
-	mUploadModelUrl.clear();
+    mUploadModelUrl.clear();
+    mModelPhysicsFee.clear();
 
 	gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale,
                           childGetValue("upload_textures").asBoolean(), 
@@ -3014,6 +3015,15 @@ void LLModelPreview::updateStatusMessages()
 	{
 		mFMP->childDisable("ok_btn");
 	}
+
+    if (mModelNoErrors && mLodsWithParsingError.empty())
+    {
+        mFMP->childEnable("calculate_btn");
+    }
+    else
+    {
+        mFMP->childDisable("calculate_btn");
+    }
 	
 	//add up physics triangles etc
 	S32 phys_tris = 0;
@@ -4430,6 +4440,12 @@ void LLFloaterModelPreview::toggleCalculateButton()
 	toggleCalculateButton(true);
 }
 
+void LLFloaterModelPreview::modelUpdated(bool calculate_visible)
+{
+    mModelPhysicsFee.clear();
+    toggleCalculateButton(calculate_visible);
+}
+
 void LLFloaterModelPreview::toggleCalculateButton(bool visible)
 {
 	mCalculateBtn->setVisible(visible);
@@ -4455,7 +4471,10 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
 		childSetTextArg("download_weight", "[ST]", tbd);
 		childSetTextArg("server_weight", "[SIM]", tbd);
 		childSetTextArg("physics_weight", "[PH]", tbd);
-		childSetTextArg("upload_fee", "[FEE]", tbd);
+		if (!mModelPhysicsFee.isMap() || mModelPhysicsFee.emptyMap())
+		{
+			childSetTextArg("upload_fee", "[FEE]", tbd);
+		}
 		childSetTextArg("price_breakdown", "[STREAMING]", tbd);
 		childSetTextArg("price_breakdown", "[PHYSICS]", tbd);
 		childSetTextArg("price_breakdown", "[INSTANCES]", tbd);
@@ -4515,10 +4534,21 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived()
 	mUploadBtn->setEnabled(isModelUploadAllowed());
 }
 
-void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason)
+void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason, const LLSD& result)
 {
 	LL_WARNS() << "LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << LL_ENDL;
 	doOnIdleOneTime(boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this, true));
+
+    if (result.has("upload_price"))
+    {
+        mModelPhysicsFee = result;
+        childSetTextArg("upload_fee", "[FEE]", llformat("%d", result["upload_price"].asInteger()));
+        childSetVisible("upload_fee", true);
+    }
+    else
+    {
+        mModelPhysicsFee.clear();
+    }
 }
 
 /*virtual*/ 
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index edc90d1695176aa3859ff656e84daef8b9d97c5b..1c66570650b64a977be0533f60dcf0f8f9d09d8f 100644
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -125,7 +125,7 @@ class LLFloaterModelPreview : public LLFloaterModelUploadBase
 
 	/*virtual*/ void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url);
 				void handleModelPhysicsFeeReceived();
-	/*virtual*/ void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason);
+	/*virtual*/ void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason, const LLSD& result);
 
 	/*virtual*/ void onModelUploadSuccess();
 
@@ -208,6 +208,8 @@ class LLFloaterModelPreview : public LLFloaterModelUploadBase
 
 	void onLoDSourceCommit(S32 lod);
 
+	void modelUpdated(bool calculate_visible);
+
 	// Toggles between "Calculate weights & fee" and "Upload" buttons.
 	void toggleCalculateButton(bool visible);
 
diff --git a/indra/newview/llfloatermodeluploadbase.h b/indra/newview/llfloatermodeluploadbase.h
index 0d4c834122325d56ab1bc62457ca1fbfc0465ac5..721fce059e008288a06fa8c40c6c0af6298326f7 100644
--- a/indra/newview/llfloatermodeluploadbase.h
+++ b/indra/newview/llfloatermodeluploadbase.h
@@ -45,7 +45,7 @@ class LLFloaterModelUploadBase : public LLFloater, public LLUploadPermissionsObs
 
 	virtual void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) = 0;
 
-	virtual void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason) = 0;
+	virtual void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason, const LLSD& result) = 0;
 
 	virtual void onModelUploadSuccess() {};
 
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index fe347a91a301e2f328c4f7cd22ef977840de035b..c9c563a054a5f024d392c6efd2fe5321aee2908b 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -71,8 +71,9 @@
 #include "lltrans.h"
 #include "llviewercontrol.h"
 #include "llviewercamera.h"
-#include "llviewerwindow.h"
+#include "llviewereventrecorder.h"
 #include "llviewermessage.h"
+#include "llviewerwindow.h"
 #include "llviewershadermgr.h"
 #include "llviewerthrottle.h"
 #include "llvoavatarself.h"
@@ -124,7 +125,9 @@ char const* const VISIBILITY_DEFAULT = "default";
 char const* const VISIBILITY_HIDDEN = "hidden";
 
 //control value for middle mouse as talk2push button
-const static std::string MIDDLE_MOUSE_CV = "MiddleMouse";
+const static std::string MIDDLE_MOUSE_CV = "MiddleMouse"; // for voice client and redability
+const static std::string MOUSE_BUTTON_4_CV = "MouseButton4";
+const static std::string MOUSE_BUTTON_5_CV = "MouseButton5";
 
 /// This must equal the maximum value set for the IndirectMaxComplexity slider in panel_preferences_graphics1.xml
 static const U32 INDIRECT_MAX_ARC_OFF = 101; // all the way to the right == disabled
@@ -157,67 +160,6 @@ struct LabelTable : public LLInitParam::Block<LabelTable>
     {}
 };
 
-class LLVoiceSetKeyDialog : public LLModalDialog
-{
-public:
-	LLVoiceSetKeyDialog(const LLSD& key);
-	~LLVoiceSetKeyDialog();
-	
-	/*virtual*/ BOOL postBuild();
-	
-	void setParent(LLFloaterPreference* parent) { mParent = parent; }
-	
-	BOOL handleKeyHere(KEY key, MASK mask);
-	static void onCancel(void* user_data);
-		
-private:
-	LLFloaterPreference* mParent;
-};
-
-LLVoiceSetKeyDialog::LLVoiceSetKeyDialog(const LLSD& key)
-  : LLModalDialog(key),
-	mParent(NULL)
-{
-}
-
-//virtual
-BOOL LLVoiceSetKeyDialog::postBuild()
-{
-	childSetAction("Cancel", onCancel, this);
-	getChild<LLUICtrl>("Cancel")->setFocus(TRUE);
-	
-	gFocusMgr.setKeystrokesOnly(TRUE);
-	
-	return TRUE;
-}
-
-LLVoiceSetKeyDialog::~LLVoiceSetKeyDialog()
-{
-}
-
-BOOL LLVoiceSetKeyDialog::handleKeyHere(KEY key, MASK mask)
-{
-	BOOL result = TRUE;
-	
-	if (key == 'Q' && mask == MASK_CONTROL)
-	{
-		result = FALSE;
-	}
-	else if (mParent)
-	{
-		mParent->setKey(key);
-	}
-	closeFloater();
-	return result;
-}
-
-//static
-void LLVoiceSetKeyDialog::onCancel(void* user_data)
-{
-	LLVoiceSetKeyDialog* self = (LLVoiceSetKeyDialog*)user_data;
-	self->closeFloater();
-}
-
 
 // global functions 
 
@@ -297,37 +239,6 @@ void handleAppearanceCameraMovementChanged(const LLSD& newvalue)
 	}
 }
 
-/*bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (0 == option && floater )
-	{
-		if ( floater )
-		{
-			floater->setAllIgnored();
-		//	LLFirstUse::disableFirstUse();
-			floater->buildPopupLists();
-		}
-	}
-	return false;
-}
-
-bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if ( 0 == option && floater )
-	{
-		if ( floater )
-		{
-			floater->resetAllIgnored();
-			//LLFirstUse::resetFirstUse();
-			floater->buildPopupLists();
-		}
-	}
-	return false;
-}
-*/
-
 void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator)
 {
 	numerator = 0;
@@ -352,8 +263,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	mGotPersonalInfo(false),
 	mOriginalIMViaEmail(false),
 	mLanguageChanged(false),
-	mAvatarDataInitialized(false),
-	mClickActionDirty(false)
+	mAvatarDataInitialized(false)
 {
 	LLConversationLog::instance().addObserver(this);
 
@@ -362,7 +272,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	static bool registered_dialog = false;
 	if (!registered_dialog)
 	{
-		LLFloaterReg::add("voice_set_key", "floater_select_key.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLVoiceSetKeyDialog>);
+		LLFloaterReg::add("keybind_dialog", "floater_select_key.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLSetKeyBindDialog>);
 		registered_dialog = true;
 	}
 	
@@ -375,8 +285,6 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	mCommitCallbackRegistrar.add("Pref.ResetCache",				boost::bind(&LLFloaterPreference::onClickResetCache, this));
 	mCommitCallbackRegistrar.add("Pref.ClickSkin",				boost::bind(&LLFloaterPreference::onClickSkin, this,_1, _2));
 	mCommitCallbackRegistrar.add("Pref.SelectSkin",				boost::bind(&LLFloaterPreference::onSelectSkin, this));
-	mCommitCallbackRegistrar.add("Pref.VoiceSetKey",			boost::bind(&LLFloaterPreference::onClickSetKey, this));
-	mCommitCallbackRegistrar.add("Pref.VoiceSetMiddleMouse",	boost::bind(&LLFloaterPreference::onClickSetMiddleMouse, this));
 	mCommitCallbackRegistrar.add("Pref.SetSounds",				boost::bind(&LLFloaterPreference::onClickSetSounds, this));
 	mCommitCallbackRegistrar.add("Pref.ClickEnablePopup",		boost::bind(&LLFloaterPreference::onClickEnablePopup, this));
 	mCommitCallbackRegistrar.add("Pref.ClickDisablePopup",		boost::bind(&LLFloaterPreference::onClickDisablePopup, this));	
@@ -397,13 +305,12 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	mCommitCallbackRegistrar.add("Pref.TranslationSettings",	boost::bind(&LLFloaterPreference::onClickTranslationSettings, this));
 	mCommitCallbackRegistrar.add("Pref.AutoReplace",            boost::bind(&LLFloaterPreference::onClickAutoReplace, this));
 	mCommitCallbackRegistrar.add("Pref.PermsDefault",           boost::bind(&LLFloaterPreference::onClickPermsDefault, this));
+	mCommitCallbackRegistrar.add("Pref.RememberedUsernames",    boost::bind(&LLFloaterPreference::onClickRememberedUsernames, this));
 	mCommitCallbackRegistrar.add("Pref.SpellChecker",           boost::bind(&LLFloaterPreference::onClickSpellChecker, this));
 	mCommitCallbackRegistrar.add("Pref.Advanced",				boost::bind(&LLFloaterPreference::onClickAdvanced, this));
 
 	sSkin = gSavedSettings.getString("SkinCurrent");
 
-	mCommitCallbackRegistrar.add("Pref.ClickActionChange",		boost::bind(&LLFloaterPreference::onClickActionChange, this));
-
 	gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged,  _2));	
 	gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged,  _2));	
 	gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged,  _2));
@@ -670,12 +577,6 @@ void LLFloaterPreference::apply()
 	}
 
 	saveAvatarProperties();
-
-	if (mClickActionDirty)
-	{
-		updateClickActionSettings();
-		mClickActionDirty = false;
-	}
 }
 
 void LLFloaterPreference::cancel()
@@ -708,12 +609,6 @@ void LLFloaterPreference::cancel()
 	// reverts any changes to current skin
 	gSavedSettings.setString("SkinCurrent", sSkin);
 
-	if (mClickActionDirty)
-	{
-		updateClickActionControls();
-		mClickActionDirty = false;
-	}
-
 	LLFloaterPreferenceProxy * advanced_proxy_settings = LLFloaterReg::findTypedInstance<LLFloaterPreferenceProxy>("prefs_proxy");
 	if (advanced_proxy_settings)
 	{
@@ -795,9 +690,6 @@ void LLFloaterPreference::onOpen(const LLSD& key)
 	onChangeTextureFolder();
 	onChangeSoundFolder();
 	onChangeAnimationFolder();
-
-	// Load (double-)click to walk/teleport settings.
-	updateClickActionControls();
 	
 	// Enabled/disabled popups, might have been changed by user actions
 	// while preferences floater was closed.
@@ -1219,7 +1111,7 @@ void LLFloaterPreference::buildPopupLists()
 		LLNotificationFormPtr formp = templatep->mForm;
 		
 		LLNotificationForm::EIgnoreType ignore = formp->getIgnoreType();
-		if (ignore == LLNotificationForm::IGNORE_NO)
+		if (ignore <= LLNotificationForm::IGNORE_NO)
 			continue;
 		
 		LLSD row;
@@ -1244,12 +1136,12 @@ void LLFloaterPreference::buildPopupLists()
 						if (it->second.asBoolean())
 						{
 							row["columns"][1]["value"] = formp->getElement(it->first)["ignore"].asString();
+							row["columns"][1]["font"] = "SANSSERIF_SMALL";
+							row["columns"][1]["width"] = 360;
 							break;
 						}
 					}
 				}
-				row["columns"][1]["font"] = "SANSSERIF_SMALL";
-				row["columns"][1]["width"] = 360;
 			}
 			item = disabled_popups.addElement(row);
 		}
@@ -1678,37 +1570,6 @@ void LLFloaterPreference::onChangeQuality(const LLSD& data)
 	refresh();
 }
 
-void LLFloaterPreference::onClickSetKey()
-{
-	LLVoiceSetKeyDialog* dialog = LLFloaterReg::showTypedInstance<LLVoiceSetKeyDialog>("voice_set_key", LLSD(), TRUE);
-	if (dialog)
-	{
-		dialog->setParent(this);
-	}
-}
-
-void LLFloaterPreference::setKey(KEY key)
-{
-	getChild<LLUICtrl>("modifier_combo")->setValue(LLKeyboard::stringFromKey(key));
-	// update the control right away since we no longer wait for apply
-	getChild<LLUICtrl>("modifier_combo")->onCommit();
-}
-
-void LLFloaterPreference::onClickSetMiddleMouse()
-{
-	LLUICtrl* p2t_line_editor = getChild<LLUICtrl>("modifier_combo");
-
-	// update the control right away since we no longer wait for apply
-	p2t_line_editor->setControlValue(MIDDLE_MOUSE_CV);
-
-	//push2talk button "middle mouse" control value is in English, need to localize it for presentation
-	LLPanel* advanced_preferences = dynamic_cast<LLPanel*>(p2t_line_editor->getParent());
-	if (advanced_preferences)
-	{
-		p2t_line_editor->setValue(advanced_preferences->getString("middle_mouse"));
-	}
-}
-
 void LLFloaterPreference::onClickSetSounds()
 {
 	// Disable Enable gesture sounds checkbox if the master sound is disabled 
@@ -1716,18 +1577,6 @@ void LLFloaterPreference::onClickSetSounds()
 	getChild<LLCheckBoxCtrl>("gesture_audio_play_btn")->setEnabled(!gSavedSettings.getBOOL("MuteSounds"));
 }
 
-/*
-void LLFloaterPreference::onClickSkipDialogs()
-{
-	LLNotificationsUtil::add("SkipShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_skip_dialogs, _1, _2, this));
-}
-
-void LLFloaterPreference::onClickResetDialogs()
-{
-	LLNotificationsUtil::add("ResetShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_reset_dialogs, _1, _2, this));
-}
- */
-
 void LLFloaterPreference::onClickEnablePopup()
 {	
 	LLScrollListCtrl& disabled_popups = getChildRef<LLScrollListCtrl>("disabled_popups");
@@ -1766,7 +1615,7 @@ void LLFloaterPreference::resetAllIgnored()
 		 iter != LLNotifications::instance().templatesEnd();
 		 ++iter)
 	{
-		if (iter->second->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
+		if (iter->second->mForm->getIgnoreType() > LLNotificationForm::IGNORE_NO)
 		{
 			iter->second->mForm->setIgnored(false);
 		}
@@ -1779,7 +1628,7 @@ void LLFloaterPreference::setAllIgnored()
 		 iter != LLNotifications::instance().templatesEnd();
 		 ++iter)
 	{
-		if (iter->second->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
+		if (iter->second->mForm->getIgnoreType() > LLNotificationForm::IGNORE_NO)
 		{
 			iter->second->mForm->setIgnored(true);
 		}
@@ -2189,14 +2038,14 @@ void LLFloaterPreference::onClickAdvanced()
 	}
 }
 
-void LLFloaterPreference::onClickActionChange()
+void LLFloaterPreference::onClickPermsDefault()
 {
-	mClickActionDirty = true;
+	LLFloaterReg::showInstance("perms_default");
 }
 
-void LLFloaterPreference::onClickPermsDefault()
+void LLFloaterPreference::onClickRememberedUsernames()
 {
-	LLFloaterReg::showInstance("perms_default");
+    LLFloaterReg::showInstance("forget_username");
 }
 
 void LLFloaterPreference::onDeleteTranscripts()
@@ -2226,26 +2075,6 @@ void LLFloaterPreference::onLogChatHistorySaved()
 	}
 }
 
-void LLFloaterPreference::updateClickActionSettings()
-{
-	const int single_clk_action = getChild<LLComboBox>("single_click_action_combo")->getValue().asInteger();
-	const int double_clk_action = getChild<LLComboBox>("double_click_action_combo")->getValue().asInteger();
-
-	gSavedSettings.setBOOL("ClickToWalk",			single_clk_action == 1);
-	gSavedSettings.setBOOL("DoubleClickAutoPilot",	double_clk_action == 1);
-	gSavedSettings.setBOOL("DoubleClickTeleport",	double_clk_action == 2);
-}
-
-void LLFloaterPreference::updateClickActionControls()
-{
-	const bool click_to_walk = gSavedSettings.getBOOL("ClickToWalk");
-	const bool dbl_click_to_walk = gSavedSettings.getBOOL("DoubleClickAutoPilot");
-	const bool dbl_click_to_teleport = gSavedSettings.getBOOL("DoubleClickTeleport");
-
-	getChild<LLComboBox>("single_click_action_combo")->setValue((int)click_to_walk);
-	getChild<LLComboBox>("double_click_action_combo")->setValue(dbl_click_to_teleport ? 2 : (int)dbl_click_to_walk);
-}
-
 void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param)
 {
 	LLUIColorTable::instance().setColor(param.asString(), LLColor4(ctrl->getValue()));
@@ -2427,16 +2256,6 @@ BOOL LLPanelPreference::postBuild()
 		getChild<LLTextBox>("mute_chb_label")->setClickedCallback(boost::bind(&toggleMuteWhenMinimized));
 	}
 
-	//////////////////////PanelAdvanced ///////////////////
-	if (hasChild("modifier_combo", TRUE))
-	{
-		//localizing if push2talk button is set to middle mouse
-		if (MIDDLE_MOUSE_CV == getChild<LLUICtrl>("modifier_combo")->getValue().asString())
-		{
-			getChild<LLUICtrl>("modifier_combo")->setValue(getString("middle_mouse"));
-		}
-	}
-
 	//////////////////////PanelSetup ///////////////////
 	if (hasChild("max_bandwidth"), TRUE)
 	{
@@ -2602,7 +2421,7 @@ void LLPanelPreference::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl)
 		bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->get();
 		bool media_enabled = getChild<LLCheckBoxCtrl>("enable_media")->get();
 
-		getChild<LLCheckBoxCtrl>("media_auto_play_btn")->setEnabled(music_enabled || media_enabled);
+		getChild<LLCheckBoxCtrl>("media_auto_play_combo")->setEnabled(music_enabled || media_enabled);
 	}
 }
 
@@ -2722,7 +2541,7 @@ void LLPanelPreferenceGraphics::setPresetText()
 		}
 	}
 
-	if (hasDirtyChilds() && !preset_graphic_active.empty())
+    if (hasDirtyChilds() && !preset_graphic_active.empty())
 	{
 		gSavedSettings.setString("PresetGraphicActive", "");
 		preset_graphic_active.clear();
@@ -2842,6 +2661,373 @@ void LLPanelPreferenceGraphics::setHardwareDefaults()
 	resetDirtyChilds();
 }
 
+//------------------------LLPanelPreferenceControls--------------------------------
+static LLPanelInjector<LLPanelPreferenceControls> t_pref_contrls("panel_preference_controls");
+
+LLPanelPreferenceControls::LLPanelPreferenceControls()
+    :LLPanelPreference(),
+    mEditingColumn(-1),
+    mEditingMode(0)
+{
+    // MODE_COUNT - 1 because there are currently no settings assigned to 'saved settings'.
+    for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
+    {
+        mConflictHandler[i].setLoadMode((LLKeyConflictHandler::ESourceMode)i);
+    }
+}
+
+LLPanelPreferenceControls::~LLPanelPreferenceControls()
+{
+}
+
+BOOL LLPanelPreferenceControls::postBuild()
+{
+    // populate list of controls
+    pControlsTable = getChild<LLScrollListCtrl>("controls_list");
+    pKeyModeBox = getChild<LLComboBox>("key_mode");
+
+    pControlsTable->setCommitCallback(boost::bind(&LLPanelPreferenceControls::onListCommit, this));
+    pKeyModeBox->setCommitCallback(boost::bind(&LLPanelPreferenceControls::onModeCommit, this));
+    getChild<LLButton>("restore_defaults")->setCommitCallback(boost::bind(&LLPanelPreferenceControls::onRestoreDefaultsBtn, this));
+
+    return TRUE;
+}
+
+void LLPanelPreferenceControls::regenerateControls()
+{
+    mEditingMode = pKeyModeBox->getValue().asInteger();
+    mConflictHandler[mEditingMode].loadFromSettings((LLKeyConflictHandler::ESourceMode)mEditingMode);
+    populateControlTable();
+}
+
+void LLPanelPreferenceControls::populateControlTable()
+{
+    pControlsTable->clearRows();
+    pControlsTable->clearColumns();
+
+    std::string filename;
+    switch ((LLKeyConflictHandler::ESourceMode)mEditingMode)
+    {
+    case LLKeyConflictHandler::MODE_THIRD_PERSON:
+    case LLKeyConflictHandler::MODE_FIRST_PERSON:
+    case LLKeyConflictHandler::MODE_EDIT_AVATAR:
+    case LLKeyConflictHandler::MODE_SITTING:
+        filename = "control_table_contents.xml";
+        break;
+    default:
+        // 'saved settings' mode doesn't have UI or actual settings yet
+        LL_INFOS() << "Unimplemented mode" << LL_ENDL;
+        return;
+    }
+
+    LLXMLNodePtr xmlNode;
+    LLScrollListCtrl::Contents contents;
+    if (!LLUICtrlFactory::getLayeredXMLNode(filename, xmlNode))
+    {
+    LL_WARNS() << "Failed to load " << filename << LL_ENDL;
+    return;
+    }
+    LLXUIParser parser;
+    parser.readXUI(xmlNode, contents, filename);
+
+    if (!contents.validateBlock())
+    {
+        return;
+    }
+
+    for (LLInitParam::ParamIterator<LLScrollListColumn::Params>::const_iterator col_it = contents.columns.begin();
+        col_it != contents.columns.end();
+        ++col_it)
+    {
+        pControlsTable->addColumn(*col_it);
+    }
+
+    LLScrollListCell::Params cell_params;
+    // init basic cell params
+    cell_params.font = LLFontGL::getFontSansSerif();
+    cell_params.font_halign = LLFontGL::LEFT;
+    cell_params.column = "";
+    cell_params.value = "";
+
+
+    for (LLInitParam::ParamIterator<LLScrollListItem::Params>::const_iterator row_it = contents.rows.begin();
+        row_it != contents.rows.end();
+        ++row_it)
+    {
+        std::string control = row_it->value.getValue().asString();
+        if (!control.empty() && control != "menu_separator")
+        {
+            // At the moment 4 collumns are hardcoded
+            LLScrollListItem::Params item_params(*row_it);
+            bool enabled = mConflictHandler[mEditingMode].canAssignControl(control);
+            item_params.enabled.setValue(enabled);
+            cell_params.column = "lst_ctrl1";
+            cell_params.value = mConflictHandler[mEditingMode].getControlString(control, 0);
+            item_params.columns.add(cell_params);
+            cell_params.column = "lst_ctrl2";
+            cell_params.value = mConflictHandler[mEditingMode].getControlString(control, 1);
+            item_params.columns.add(cell_params);
+            cell_params.column = "lst_ctrl3";
+            cell_params.value = mConflictHandler[mEditingMode].getControlString(control, 2);
+            item_params.columns.add(cell_params);
+            pControlsTable->addRow(item_params, EAddPosition::ADD_BOTTOM);
+        }
+        else
+        {
+            pControlsTable->addRow(*row_it, EAddPosition::ADD_BOTTOM);
+        }
+    }
+}
+
+// Just a workaround to not care about first separator before headers (we can start from random header)
+void LLPanelPreferenceControls::addSeparator()
+{
+    if (pControlsTable->getItemCount() > 0)
+    {
+        pControlsTable->addSeparator(EAddPosition::ADD_BOTTOM);
+    }
+}
+
+void LLPanelPreferenceControls::updateTable()
+{
+    mEditingControl.clear();
+    std::vector<LLScrollListItem*> list = pControlsTable->getAllData();
+    for (S32 i = 0; i < list.size(); ++i)
+    {
+        std::string control = list[i]->getValue();
+        if (!control.empty())
+        {
+            LLScrollListCell* cell = list[i]->getColumn(1);
+            cell->setValue(mConflictHandler[mEditingMode].getControlString(control, 0));
+            cell = list[i]->getColumn(2);
+            cell->setValue(mConflictHandler[mEditingMode].getControlString(control, 1));
+            cell = list[i]->getColumn(3);
+            cell->setValue(mConflictHandler[mEditingMode].getControlString(control, 2));
+        }
+    }
+    pControlsTable->deselectAllItems();
+}
+
+void LLPanelPreferenceControls::apply()
+{
+    for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
+    {
+        if (mConflictHandler[i].hasUnsavedChanges())
+        {
+            mConflictHandler[i].saveToSettings();
+        }
+    }
+}
+
+void LLPanelPreferenceControls::cancel()
+{
+    for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
+    {
+        if (mConflictHandler[i].hasUnsavedChanges())
+        {
+            mConflictHandler[i].clear();
+        }
+    }
+    pControlsTable->clear();
+}
+
+void LLPanelPreferenceControls::saveSettings()
+{
+    for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
+    {
+        if (mConflictHandler[i].hasUnsavedChanges())
+        {
+            mConflictHandler[i].saveToSettings();
+            mConflictHandler[i].clear();
+        }
+    }
+
+    S32 mode = pKeyModeBox->getValue().asInteger();
+    if (mConflictHandler[mode].empty())
+    {
+        regenerateControls();
+    }
+}
+
+void LLPanelPreferenceControls::resetDirtyChilds()
+{
+    regenerateControls();
+}
+
+void LLPanelPreferenceControls::onListCommit()
+{
+    LLScrollListItem* item = pControlsTable->getFirstSelected();
+    if (item == NULL)
+    {
+        return;
+    }
+
+    std::string control = item->getValue();
+
+    if (control.empty())
+    {
+        pControlsTable->deselectAllItems();
+        return;
+    }
+
+    if (!mConflictHandler[mEditingMode].canAssignControl(control))
+    {
+        pControlsTable->deselectAllItems();
+        return;
+    }
+
+    S32 cell_ind = item->getSelectedCell();
+    if (cell_ind <= 0)
+    {
+        pControlsTable->deselectAllItems();
+        return;
+    }
+
+    // List does not tell us what cell was clicked, so we have to figure it out manually, but
+    // fresh mouse coordinates are not yet accessible during onCommit() and there are other issues,
+    // so we cheat: remember item user clicked at, trigger 'key dialog' on hover that comes next,
+    // use coordinates from hover to calculate cell
+
+    LLScrollListCell* cell = item->getColumn(cell_ind);
+    if (cell)
+    {
+        LLSetKeyBindDialog* dialog = LLFloaterReg::getTypedInstance<LLSetKeyBindDialog>("keybind_dialog", LLSD());
+        if (dialog)
+        {
+            mEditingControl = control;
+            mEditingColumn = cell_ind;
+            dialog->setParent(this, pControlsTable, DEFAULT_KEY_FILTER);
+
+            LLFloater* root_floater = gFloaterView->getParentFloater(this);
+            if (root_floater)
+                root_floater->addDependentFloater(dialog);
+            dialog->openFloater();
+            dialog->setFocus(TRUE);
+        }
+    }
+    else
+    {
+        pControlsTable->deselectAllItems();
+    }
+}
+
+void LLPanelPreferenceControls::onModeCommit()
+{
+    mEditingMode = pKeyModeBox->getValue().asInteger();
+    if (mConflictHandler[mEditingMode].empty())
+    {
+        // opening for first time
+        mConflictHandler[mEditingMode].loadFromSettings((LLKeyConflictHandler::ESourceMode)mEditingMode);
+    }
+    populateControlTable();
+}
+
+void LLPanelPreferenceControls::onRestoreDefaultsBtn()
+{
+    LLNotificationsUtil::add("PreferenceControlsDefaults", LLSD(), LLSD(), boost::bind(&LLPanelPreferenceControls::onRestoreDefaultsResponse, this, _1, _2));
+}
+
+void LLPanelPreferenceControls::onRestoreDefaultsResponse(const LLSD& notification, const LLSD& response)
+{
+    S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+    switch(option)
+    {
+    case 0: // All
+        for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
+        {
+            mConflictHandler[i].resetToDefaults();
+            // Apply changes to viewer as 'temporary'
+            mConflictHandler[i].saveToSettings(true);
+        }
+
+        updateTable();
+        break;
+    case 1: // Current
+        mConflictHandler[mEditingMode].resetToDefaults();
+        // Apply changes to viewer as 'temporary'
+        mConflictHandler[mEditingMode].saveToSettings(true);
+
+        updateTable();
+        break;
+    case 2: // Cancel
+    default:
+        //exit;
+        break;
+    }
+}
+
+// todo: copy onSetKeyBind to interface and inherit from interface
+bool LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes)
+{
+    if (!mConflictHandler[mEditingMode].canAssignControl(mEditingControl))
+    {
+        return true;
+    }
+
+    if ( mEditingColumn > 0)
+    {
+        if (all_modes)
+        {
+            for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
+            {
+                if (mConflictHandler[i].empty())
+                {
+                    mConflictHandler[i].loadFromSettings((LLKeyConflictHandler::ESourceMode)i);
+                }
+                mConflictHandler[i].registerControl(mEditingControl, mEditingColumn - 1, click, key, mask, true);
+                // Apply changes to viewer as 'temporary'
+                mConflictHandler[i].saveToSettings(true);
+            }
+        }
+        else
+        {
+            mConflictHandler[mEditingMode].registerControl(mEditingControl, mEditingColumn - 1, click, key, mask, true);
+            // Apply changes to viewer as 'temporary'
+            mConflictHandler[mEditingMode].saveToSettings(true);
+        }
+    }
+
+    updateTable();
+    return true;
+}
+
+void LLPanelPreferenceControls::onDefaultKeyBind(bool all_modes)
+{
+    if (!mConflictHandler[mEditingMode].canAssignControl(mEditingControl))
+    {
+        return;
+    }
+    
+    if (mEditingColumn > 0)
+    {
+        if (all_modes)
+        {
+            for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
+            {
+                if (mConflictHandler[i].empty())
+                {
+                    mConflictHandler[i].loadFromSettings((LLKeyConflictHandler::ESourceMode)i);
+                }
+                mConflictHandler[i].resetToDefault(mEditingControl, mEditingColumn - 1);
+                // Apply changes to viewer as 'temporary'
+                mConflictHandler[i].saveToSettings(true);
+            }
+        }
+        else
+        {
+            mConflictHandler[mEditingMode].resetToDefault(mEditingControl, mEditingColumn - 1);
+            // Apply changes to viewer as 'temporary'
+            mConflictHandler[mEditingMode].saveToSettings(true);
+        }
+    }
+    updateTable();
+}
+
+void LLPanelPreferenceControls::onCancelKeyBind()
+{
+    pControlsTable->deselectAllItems();
+}
+
 LLFloaterPreferenceGraphicsAdvanced::LLFloaterPreferenceGraphicsAdvanced(const LLSD& key)
 	: LLFloater(key)
 {
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 1b8229ada6cc3e2b4148fab02ab2a40aa147788b..9ede7d5bcf2cec64332d112092b9cd659cf56a79 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -37,13 +37,17 @@
 #include "llavatarpropertiesprocessor.h"
 #include "llconversationlog.h"
 #include "llsearcheditor.h"
+#include "llsetkeybinddialog.h"
+#include "llkeyconflict.h"
 
 class LLConversationLogObserver;
 class LLPanelPreference;
 class LLPanelLCD;
 class LLPanelDebug;
 class LLMessageSystem;
+class LLComboBox;
 class LLScrollListCtrl;
+class LLScrollListCell;
 class LLSliderCtrl;
 class LLSD;
 class LLTextBox;
@@ -127,13 +131,6 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver,
 	// callback for when client turns on impostors
 	void onAvatarImpostorsEnable();
 
-	// callback for commit in the "Single click on land" and "Double click on land" comboboxes.
-	void onClickActionChange();
-	// updates click/double-click action settings depending on controls values
-	void updateClickActionSettings();
-	// updates click/double-click action controls depending on values from settings.xml
-	void updateClickActionControls();
-
 public:
 	// This function squirrels away the current values of the controls so that
 	// cancel() can restore them.	
@@ -146,9 +143,6 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver,
 	void onClickResetCache();
 	void onClickSkin(LLUICtrl* ctrl,const LLSD& userdata);
 	void onSelectSkin();
-	void onClickSetKey();
-	void setKey(KEY key);
-	void onClickSetMiddleMouse();
 	void onClickSetSounds();
 	void onClickEnablePopup();
 	void onClickDisablePopup();	
@@ -167,7 +161,6 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver,
 	
 	void refreshUI();
 
-	void onCommitParcelMediaAutoPlayEnable();
 	void onCommitMediaEnabled();
 	void onCommitMusicEnabled();
 	void applyResolution();
@@ -180,6 +173,7 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver,
 	void onClickProxySettings();
 	void onClickTranslationSettings();
 	void onClickPermsDefault();
+	void onClickRememberedUsernames();
 	void onClickAutoReplace();
 	void onClickSpellChecker();
 	void onClickRenderExceptions();
@@ -202,7 +196,6 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver,
 
 	static std::string sSkin;
 	notifications_map mNotificationOptions;
-	bool mClickActionDirty; ///< Set to true when the click/double-click options get changed by user.
 	bool mGotPersonalInfo;
 	bool mOriginalIMViaEmail;
 	bool mLanguageChanged;
@@ -292,6 +285,44 @@ class LLPanelPreferenceGraphics : public LLPanelPreference
 	LOG_CLASS(LLPanelPreferenceGraphics);
 };
 
+class LLPanelPreferenceControls : public LLPanelPreference, public LLKeyBindResponderInterface
+{
+	LOG_CLASS(LLPanelPreferenceControls);
+public:
+	LLPanelPreferenceControls();
+	virtual ~LLPanelPreferenceControls();
+
+	BOOL postBuild();
+
+	void apply();
+	void cancel();
+	void saveSettings();
+	void resetDirtyChilds();
+
+	void onListCommit();
+	void onModeCommit();
+	void onRestoreDefaultsBtn();
+	void onRestoreDefaultsResponse(const LLSD& notification, const LLSD& response);
+	/*virtual*/ bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes);
+    /*virtual*/ void onDefaultKeyBind(bool all_modes);
+	/*virtual*/ void onCancelKeyBind();
+
+private:
+	// reloads settings, discards current changes, updates table
+	void regenerateControls();
+
+	void populateControlTable();
+	void addSeparator();
+	void updateTable();
+
+	LLScrollListCtrl* pControlsTable;
+	LLComboBox *pKeyModeBox;
+	LLKeyConflictHandler mConflictHandler[LLKeyConflictHandler::MODE_COUNT];
+	std::string mEditingControl;
+	S32 mEditingColumn;
+	S32 mEditingMode;
+};
+
 class LLFloaterPreferenceGraphicsAdvanced : public LLFloater
 {
   public: 
diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp
index fbb7432f71caf4539bfcb4aa85c4e74b052bf516..64ad40f4195a7b73b353ded636c400b049fcf910 100644
--- a/indra/newview/llfloaterproperties.cpp
+++ b/indra/newview/llfloaterproperties.cpp
@@ -85,7 +85,7 @@ class LLPropertiesObserver : public LLInventoryObserver
 	}
 	virtual void changed(U32 mask);
 private:
-	LLFloaterProperties* mFloater;
+	LLFloaterProperties* mFloater; // Not a handle because LLFloaterProperties is managing LLPropertiesObserver
 };
 
 void LLPropertiesObserver::changed(U32 mask)
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 960fd9620d8a6bf66b9e3e1f8fa559b0d6c12be5..60cb22c4de4a5678cb0ddd40a79b635a3f59c1bc 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -936,7 +936,7 @@ void LLFloaterReporter::takeNewSnapshot()
 
 	// Take a screenshot, but don't draw this floater.
 	setVisible(FALSE);
-	if( !gViewerWindow->rawSnapshot(mImageRaw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE, TRUE, FALSE))
+    if (!gViewerWindow->rawSnapshot(mImageRaw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE, gSavedSettings.getBOOL("RenderHUDInSnapshot"), TRUE, FALSE))
 	{
 		LL_WARNS() << "Unable to take screenshot" << LL_ENDL;
 		setVisible(TRUE);
diff --git a/indra/newview/llhudeffectbeam.cpp b/indra/newview/llhudeffectbeam.cpp
index 54e683e048371e9c834346c09cbf8b42b4d35445..d1d83e6e03847b5bb9379d37c7f677fb79546674 100644
--- a/indra/newview/llhudeffectbeam.cpp
+++ b/indra/newview/llhudeffectbeam.cpp
@@ -90,7 +90,7 @@ void LLHUDEffectBeam::packData(LLMessageSystem *mesgsys)
 	memset(packed_data, 0, 41);
 	if (mSourceObject)
 	{
-		htonmemcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
+		htolememcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
 	}
 
 	if (mTargetObject)
@@ -104,11 +104,11 @@ void LLHUDEffectBeam::packData(LLMessageSystem *mesgsys)
 
 	if (mTargetObject)
 	{
-		htonmemcpy(&(packed_data[17]), mTargetObject->mID.mData, MVT_LLUUID, 16);
+		htolememcpy(&(packed_data[17]), mTargetObject->mID.mData, MVT_LLUUID, 16);
 	}
 	else
 	{
-		htonmemcpy(&(packed_data[17]), mTargetPos.mdV, MVT_LLVector3d, 24);
+		htolememcpy(&(packed_data[17]), mTargetPos.mdV, MVT_LLVector3d, 24);
 	}
 	mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41);
 }
@@ -131,7 +131,7 @@ void LLHUDEffectBeam::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
 	}
 	mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 41, blocknum);
 	
-	htonmemcpy(source_id.mData, packed_data, MVT_LLUUID, 16);
+	htolememcpy(source_id.mData, packed_data, MVT_LLUUID, 16);
 
 	LLViewerObject *objp = gObjectList.findObject(source_id);
 	if (objp)
@@ -143,7 +143,7 @@ void LLHUDEffectBeam::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
 
 	if (use_target_object)
 	{
-		htonmemcpy(target_id.mData, &packed_data[17], MVT_LLUUID, 16);
+		htolememcpy(target_id.mData, &packed_data[17], MVT_LLUUID, 16);
 
 		LLViewerObject *objp = gObjectList.findObject(target_id);
 		if (objp)
@@ -153,7 +153,7 @@ void LLHUDEffectBeam::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
 	}
 	else
 	{
-		htonmemcpy(new_target.mdV, &(packed_data[17]), MVT_LLVector3d, 24);
+		htolememcpy(new_target.mdV, &(packed_data[17]), MVT_LLVector3d, 24);
 		setTargetPos(new_target);
 	}
 
diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp
index f46152dcec96844d9bc88f66f15f07db2e1261dd..6898dce7b10f75f285c39613cf5653d4b481e653 100644
--- a/indra/newview/llhudeffectlookat.cpp
+++ b/indra/newview/llhudeffectlookat.cpp
@@ -269,29 +269,29 @@ void LLHUDEffectLookAt::packData(LLMessageSystem *mesgsys)
 
 	if (mSourceObject)
 	{
-		htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
+		htolememcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
 	}
 	else
 	{
-		htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
+		htolememcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
 	}
 
 	// pack both target object and position
 	// position interpreted as offset if target object is non-null
 	if (mTargetObject)
 	{
-		htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
+		htolememcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
 	}
 	else
 	{
-		htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
+		htolememcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
 	}
 
-	htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
+	htolememcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
 
 	U8 lookAtTypePacked = (U8)mTargetType;
 	
-	htonmemcpy(&(packed_data[LOOKAT_TYPE]), &lookAtTypePacked, MVT_U8, 1);
+	htolememcpy(&(packed_data[LOOKAT_TYPE]), &lookAtTypePacked, MVT_U8, 1);
 
 	mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE);
 
@@ -325,7 +325,7 @@ void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
 	}
 	mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum);
 	
-	htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
+	htolememcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
 
 	LLViewerObject *objp = gObjectList.findObject(source_id);
 	if (objp && objp->isAvatar())
@@ -338,11 +338,11 @@ void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
 		return;
 	}
 
-	htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
+	htolememcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
 
 	objp = gObjectList.findObject(target_id);
 
-	htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
+	htolememcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
 
 	if (objp)
 	{
@@ -358,7 +358,7 @@ void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
 	}
 
 	U8 lookAtTypeUnpacked = 0;
-	htonmemcpy(&lookAtTypeUnpacked, &(packed_data[LOOKAT_TYPE]), MVT_U8, 1);
+	htolememcpy(&lookAtTypeUnpacked, &(packed_data[LOOKAT_TYPE]), MVT_U8, 1);
 	mTargetType = (ELookAtType)lookAtTypeUnpacked;
 
 	if (mTargetType == LOOKAT_TARGET_NONE)
diff --git a/indra/newview/llhudeffectpointat.cpp b/indra/newview/llhudeffectpointat.cpp
index cc772c8f5c0aa2f1e11afc0a576bf2215e02ddbb..ecf6d42d692af8f0e14028c9db10bf76a36adc3b 100644
--- a/indra/newview/llhudeffectpointat.cpp
+++ b/indra/newview/llhudeffectpointat.cpp
@@ -107,28 +107,28 @@ void LLHUDEffectPointAt::packData(LLMessageSystem *mesgsys)
 
 	if (mSourceObject)
 	{
-		htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
+		htolememcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
 	}
 	else
 	{
-		htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
+		htolememcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
 	}
 
 	// pack both target object and position
 	// position interpreted as offset if target object is non-null
 	if (mTargetObject)
 	{
-		htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
+		htolememcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
 	}
 	else
 	{
-		htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
+		htolememcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
 	}
 
-	htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
+	htolememcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
 
 	U8 pointAtTypePacked = (U8)mTargetType;
-	htonmemcpy(&(packed_data[POINTAT_TYPE]), &pointAtTypePacked, MVT_U8, 1);
+	htolememcpy(&(packed_data[POINTAT_TYPE]), &pointAtTypePacked, MVT_U8, 1);
 
 	mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE);
 
@@ -164,10 +164,10 @@ void LLHUDEffectPointAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
 	}
 	mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum);
 	
-	htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
-	htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
-	htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
-	htonmemcpy(&pointAtTypeUnpacked, &(packed_data[POINTAT_TYPE]), MVT_U8, 1);
+	htolememcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
+	htolememcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
+	htolememcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
+	htolememcpy(&pointAtTypeUnpacked, &(packed_data[POINTAT_TYPE]), MVT_U8, 1);
 
 	LLViewerObject *objp = gObjectList.findObject(source_id);
 	if (objp && objp->isAvatar())
diff --git a/indra/newview/llhudeffecttrail.cpp b/indra/newview/llhudeffecttrail.cpp
index fc6efdb840f03cf03a621bd188f60054fa610f79..2ba8aa422bd1b70335222ca1c12e69d299fe3029 100644
--- a/indra/newview/llhudeffecttrail.cpp
+++ b/indra/newview/llhudeffecttrail.cpp
@@ -87,15 +87,15 @@ void LLHUDEffectSpiral::packData(LLMessageSystem *mesgsys)
 
 	if (mSourceObject)
 	{
-		htonmemcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
+		htolememcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
 	}
 	if (mTargetObject)
 	{
-		htonmemcpy(packed_data + 16, mTargetObject->mID.mData, MVT_LLUUID, 16);
+		htolememcpy(packed_data + 16, mTargetObject->mID.mData, MVT_LLUUID, 16);
 	}
 	if (!mPositionGlobal.isExactlyZero())
 	{
-		htonmemcpy(packed_data + 32, mPositionGlobal.mdV, MVT_LLVector3d, 24);
+		htolememcpy(packed_data + 32, mPositionGlobal.mdV, MVT_LLVector3d, 24);
 	}
 	mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 56);
 }
@@ -116,9 +116,9 @@ void LLHUDEffectSpiral::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
 	mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, 
 		packed_data, EFFECT_SIZE, blocknum, EFFECT_SIZE);
 	
-	htonmemcpy(object_id.mData, packed_data, MVT_LLUUID, 16);
-	htonmemcpy(target_object_id.mData, packed_data + 16, MVT_LLUUID, 16);
-	htonmemcpy(mPositionGlobal.mdV, packed_data + 32, MVT_LLVector3d, 24);
+	htolememcpy(object_id.mData, packed_data, MVT_LLUUID, 16);
+	htolememcpy(target_object_id.mData, packed_data + 16, MVT_LLUUID, 16);
+	htolememcpy(mPositionGlobal.mdV, packed_data + 32, MVT_LLVector3d, 24);
 
 	LLViewerObject *objp = NULL;
 
diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp
index 3606a439a69fc2abdccda3a83e1dc5ce5fdf62b5..48101bf0d9c8c9cd6029a0f24a73bf4cec45a074 100644
--- a/indra/newview/llimprocessing.cpp
+++ b/indra/newview/llimprocessing.cpp
@@ -29,6 +29,7 @@
 #include "llimprocessing.h"
 
 #include "llagent.h"
+#include "llappviewer.h"
 #include "llavatarnamecache.h"
 #include "llfirstuse.h"
 #include "llfloaterreg.h"
@@ -61,6 +62,8 @@
 #pragma warning (disable:4702)
 #endif
 
+extern void on_new_message(const LLSD& msg);
+
 // Strip out "Resident" for display, but only if the message came from a user
 // (rather than a script)
 static std::string clean_name_from_im(const std::string& name, EInstantMessage type)
@@ -715,7 +718,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
             {
                 info = new LLOfferInfo();
 
-                info->mIM = IM_GROUP_NOTICE;
+                info->mIM = dialog;
                 info->mFromID = from_id;
                 info->mFromGroup = from_group;
                 info->mTransactionID = session_id;
@@ -854,39 +857,18 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
             }
             else // IM_TASK_INVENTORY_OFFERED
             {
-                if (offline == IM_OFFLINE && session_id.isNull() && aux_id.notNull() && binary_bucket_size > sizeof(S8)* 5)
-                {
-                    // cap received offline message
-                    std::string str_bucket = ll_safe_string((char*)binary_bucket, binary_bucket_size);
-                    typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
-                    boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
-                    tokenizer tokens(str_bucket, sep);
-                    tokenizer::iterator iter = tokens.begin();
-
-                    info->mType = (LLAssetType::EType)(atoi((*(iter++)).c_str()));
-                    // Note There is more elements in 'tokens' ...
-
-                    info->mObjectID = LLUUID::null;
-                    info->mFromObject = TRUE;
-                }
-                else
-                {
-                    if (sizeof(S8) != binary_bucket_size)
-                    {
-                        LL_WARNS("Messaging") << "Malformed inventory offer from object" << LL_ENDL;
-                        delete info;
-                        break;
-                    }
-                    info->mType = (LLAssetType::EType) binary_bucket[0];
-                    info->mObjectID = LLUUID::null;
-                    info->mFromObject = TRUE;
-                }
+                info->mType = (LLAssetType::EType) binary_bucket[0];
+                info->mObjectID = LLUUID::null;
+                info->mFromObject = TRUE;
             }
 
+            // In the case of an offline message, the transaction id will be in aux_id and th session_id will be null
+            // (conversely when online the transaction id is passed as session_id)
+            info->mTransactionID = session_id.isNull() ? aux_id : session_id;
+
             info->mIM = dialog;
             info->mFromID = from_id;
             info->mFromGroup = from_group;
-            info->mTransactionID = session_id;
             info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType));
 
             info->mFromName = name;
@@ -896,12 +878,18 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
             if (is_muted)
             {
                 // Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331)
-                LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID);
-                fetch_item->startFetch();
-                delete fetch_item;
-
-                // Same as closing window
-                info->forceResponse(IOR_DECLINE);
+                if (IM_INVENTORY_OFFERED == dialog)
+                {
+                    LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID);
+                    fetch_item->startFetch();
+                    delete fetch_item;
+                    // Same as closing window
+                    info->forceResponse(IOR_DECLINE);
+                }
+                else
+                {
+                    info->forceResponse(IOR_MUTE);
+                }
             }
             // old logic: busy mode must not affect interaction with objects (STORM-565)
             // new logic: inventory offers from in-world objects should be auto-declined (CHUI-519)
@@ -1021,6 +1009,14 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
                 }
 
                 LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args);
+                if (message != "")
+                {
+                    LLSD msg_notify;
+                    msg_notify["session_id"] = LLUUID();
+                    msg_notify["from_id"] = chat.mFromID;
+                    msg_notify["source_type"] = chat.mSourceType;
+                    on_new_message(msg_notify);
+                }
             }
 
 
@@ -1468,6 +1464,7 @@ void LLIMProcessing::requestOfflineMessages()
     static BOOL requested = FALSE;
     if (!requested
         && gMessageSystem
+        && !gDisconnected
         && LLMuteList::getInstance()->isLoaded()
         && isAgentAvatarValid()
         && gAgent.getRegion()
@@ -1555,7 +1552,7 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url)
 
     std::vector<U8> data;
     S32 binary_bucket_size = 0;
-    LLHost sender = gAgent.getRegion()->getHost();
+    LLHost sender = gAgent.getRegionHost();
 
     LLSD::array_iterator i = messages.beginArray();
     LLSD::array_iterator iEnd = messages.endArray();
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index e331a51bda76220197e21dc08c9078fce942c966..d5142a4496a9b2bc3e9a6c2894d80a6ba3a73f7d 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -843,7 +843,7 @@ void LLIMModel::LLIMSession::loadHistory()
 		std::list<LLSD> chat_history;
 
 		//involves parsing of a chat history
-		LLLogChat::loadChatHistory(mHistoryFileName, chat_history);
+		LLLogChat::loadChatHistory(mHistoryFileName, chat_history, LLSD(), isGroupChat());
 		addMessagesFromHistory(chat_history);
 	}
 }
@@ -907,6 +907,11 @@ bool LLIMModel::LLIMSession::isP2P()
 	return IM_NOTHING_SPECIAL == mType;
 }
 
+bool LLIMModel::LLIMSession::isGroupChat()
+{
+	return IM_SESSION_GROUP_START == mType || (IM_SESSION_INVITE == mType && gAgent.isInGroup(mSessionID));
+}
+
 bool LLIMModel::LLIMSession::isOtherParticipantAvaline()
 {
 	return !mOtherParticipantIsAvatar;
@@ -964,6 +969,10 @@ void LLIMModel::LLIMSession::buildHistoryFileName()
 			mHistoryFileName = LLCacheName::buildUsername(mName);
 		}
 	}
+	else if (isGroupChat())
+	{
+		mHistoryFileName = mName + GROUP_CHAT_SUFFIX;
+	}
 }
 
 //static
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 2a9e4679a8bd1dd8447ee8dbe42aab39f82edec3..79c831ebb6a6981d2f3695ee43c6bdc003bb615f 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -91,6 +91,7 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 		bool isOutgoingAdHoc() const;
 		bool isAdHoc();
 		bool isP2P();
+		bool isGroupChat();
 		bool isOtherParticipantAvaline();
 
 		bool isP2PSessionType() const { return mSessionType == P2P_SESSION;}
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 349ba6183ba61ca5be91b73b1e5379d92c049aa0..d460aa145246c901e92f4e368362d5441a1358b5 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1797,7 +1797,7 @@ void LLItemBridge::restoreToWorld()
 
 		msg->nextBlockFast(_PREHASH_InventoryData);
 		itemp->packMessage(msg);
-		msg->sendReliable(gAgent.getRegion()->getHost());
+		msg->sendReliable(gAgent.getRegionHost());
 
 		//remove local inventory copy, sim will deal with permissions and removing the item
 		//from the actual inventory if its a no-copy etc
@@ -2270,7 +2270,7 @@ class LLIsItemRemovable : public LLFolderViewFunctor
 // Can be destroyed (or moved to trash)
 BOOL LLFolderBridge::isItemRemovable() const
 {
-	if (!get_is_category_removable(getInventoryModel(), mUUID) || isMarketplaceListingsFolder())
+	if (!get_is_category_removable(getInventoryModel(), mUUID))
 	{
 		return FALSE;
 	}
@@ -2287,6 +2287,11 @@ BOOL LLFolderBridge::isItemRemovable() const
 		}
 	}
 
+	if (isMarketplaceListingsFolder() && (!LLMarketplaceData::instance().isSLMDataFetched() || LLMarketplaceData::instance().getActivationState(mUUID)))
+	{
+		return FALSE;
+	}
+
 	return TRUE;
 }
 
@@ -4662,7 +4667,7 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
 		{
 			LLInventoryObject::object_list_t inventory_objects;
 			object->getInventoryContents(inventory_objects);
-			int contents_count = inventory_objects.size()-1; //subtract one for containing folder
+			int contents_count = inventory_objects.size();
 			LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count, cat_and_wear->mFolderResponded,
 																									cat_and_wear->mReplace);
 			
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 16385928b4d8e9e88d71289e5b48ef63d419956a..e8bc915f22975233b0c49195cd179913ac141695 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -42,7 +42,7 @@
 #include "llviewerfoldertype.h"
 #include "llradiogroup.h"
 #include "llstartup.h"
-
+#include <boost/regex.hpp>
 // linden library includes
 #include "llclipboard.h"
 #include "lltrans.h"
@@ -116,7 +116,39 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
 			break;
 	}
 
-	bool passed = (mFilterSubString.size() ? desc.find(mFilterSubString) != std::string::npos : true);
+
+	bool passed = true;
+	if (!mExactToken.empty() && (mSearchType == SEARCHTYPE_NAME))
+	{
+		passed = false;
+		typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+		boost::char_separator<char> sep(" ");
+		tokenizer tokens(desc, sep);
+
+		for (auto token_iter : tokens)
+		{
+			if (token_iter == mExactToken)
+			{
+				passed = true;
+				break;
+			}
+		}	
+	}
+	else if ((mFilterTokens.size() > 0) && (mSearchType == SEARCHTYPE_NAME))
+	{
+		for (auto token_iter : mFilterTokens)
+		{
+			if (desc.find(token_iter) == std::string::npos)
+			{
+				return false;
+			}
+		}
+	}
+	else
+	{
+		passed = (mFilterSubString.size() ? desc.find(mFilterSubString) != std::string::npos : true);
+	}
+
 	passed = passed && checkAgainstFilterType(listener);
 	passed = passed && checkAgainstPermissions(listener);
 	passed = passed && checkAgainstFilterLinks(listener);
@@ -693,6 +725,38 @@ void LLInventoryFilter::setFilterSubString(const std::string& string)
 
 	if (mFilterSubString != filter_sub_string_new)
 	{
+		
+		mFilterTokens.clear();
+		if (filter_sub_string_new.find_first_of("+") != std::string::npos)
+		{
+			typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+			boost::char_separator<char> sep("+");
+			tokenizer tokens(filter_sub_string_new, sep);
+
+			for (auto token_iter : tokens)
+			{
+				mFilterTokens.push_back(token_iter);
+			}
+		}
+
+		std::string old_token = mExactToken;
+		mExactToken.clear();
+		bool exact_token_changed = false;
+		if (mFilterTokens.empty() && filter_sub_string_new.size() > 2)
+		{
+			boost::regex mPattern = boost::regex("\"\\s*([^<]*)?\\s*\"",
+				boost::regex::perl | boost::regex::icase);
+			boost::match_results<std::string::const_iterator> matches;
+			mExactToken = (boost::regex_match(filter_sub_string_new, matches, mPattern) && matches[1].matched)
+				? matches[1]
+				: LLStringUtil::null;
+			if ((old_token.empty() && !mExactToken.empty()) 
+				|| (!old_token.empty() && mExactToken.empty()))
+			{
+				exact_token_changed = true;
+			}
+		}
+
 		// hitting BACKSPACE, for example
 		const BOOL less_restrictive = mFilterSubString.size() >= filter_sub_string_new.size()
 			&& !mFilterSubString.substr(0, filter_sub_string_new.size()).compare(filter_sub_string_new);
@@ -702,7 +766,11 @@ void LLInventoryFilter::setFilterSubString(const std::string& string)
 			&& !filter_sub_string_new.substr(0, mFilterSubString.size()).compare(mFilterSubString);
 
 		mFilterSubString = filter_sub_string_new;
-		if (less_restrictive)
+		if (exact_token_changed)
+		{
+			setModified(FILTER_RESTART);
+		}
+		else if (less_restrictive)
 		{
 			setModified(FILTER_LESS_RESTRICTIVE);
 		}
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index 4a1fec8454893963b0d2c338bbf95894742607bf..3f24211f4127f20e334df9be192be060e853822b 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -327,6 +327,9 @@ class LLInventoryFilter : public LLFolderViewFilter
 	std::string 			mEmptyLookupMessage;
 
 	ESearchType 			mSearchType;
+
+	std::vector<std::string> mFilterTokens;
+	std::string				 mExactToken;
 };
 
 #endif
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index d4993a1091a2cfa225a031e016d1a69faccc55e5..6f461673ee0580752b9b88a9b35aae8e057e97f0 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -291,7 +291,6 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
 	if (!gSavedSettings.getBOOL("InventoryOutboxMakeVisible"))
 	{
 		getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX));
-		getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX));
 	}
     // hide marketplace listing box, unless we are a marketplace panel
 	if (!gSavedSettings.getBOOL("InventoryOutboxMakeVisible") && !mParams.use_marketplace_folders)
diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a94836c59d0580accb3d548c05c121e969ae7c3f
--- /dev/null
+++ b/indra/newview/llkeyconflict.cpp
@@ -0,0 +1,852 @@
+/** 
+ * @file llkeyconflict.cpp
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, 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$
+ */
+
+/*
+ * App-wide preferences.  Note that these are not per-user,
+ * because we need to load many preferences before we have
+ * a login name.
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llkeyconflict.h"
+
+#include "llinitparam.h"
+#include "llkeyboard.h"
+#include "lltrans.h"
+#include "llviewercontrol.h"
+#include "llviewerinput.h"
+#include "llviewermenu.h"
+#include "llxuiparser.h"
+
+static const std::string saved_settings_key_controls[] = { "placeholder" }; // add settings from gSavedSettings here
+
+static const std::string filename_default = "key_bindings.xml";
+static const std::string filename_temporary = "key_bindings_tmp.xml"; // used to apply uncommited changes on the go.
+
+// LLKeyboard::stringFromMask is meant for UI and is OS dependent,
+// so this class uses it's own version
+std::string string_from_mask(MASK mask)
+{
+    std::string res;
+    if ((mask & MASK_CONTROL) != 0)
+    {
+        res = "CTL";
+    }
+    if ((mask & MASK_ALT) != 0)
+    {
+        if (!res.empty()) res += "_";
+        res += "ALT";
+    }
+    if ((mask & MASK_SHIFT) != 0)
+    {
+        if (!res.empty()) res += "_";
+        res += "SHIFT";
+    }
+
+    if (mask == MASK_NONE)
+    {
+        res = "NONE";
+    }
+    return res;
+}
+
+std::string string_from_mouse(EMouseClickType click, bool translate)
+{
+    std::string res;
+    switch (click)
+    {
+    case CLICK_LEFT:
+        res = "LMB";
+        break;
+    case CLICK_MIDDLE:
+        res = "MMB";
+        break;
+    case CLICK_RIGHT:
+        res = "RMB";
+        break;
+    case CLICK_BUTTON4:
+        res = "MB4";
+        break;
+    case CLICK_BUTTON5:
+        res = "MB5";
+        break;
+    case CLICK_DOUBLELEFT:
+        res = "Double LMB";
+        break;
+    default:
+        break;
+    }
+
+    if (translate && !res.empty())
+    {
+        res = LLTrans::getString(res);
+    }
+    return res;
+}
+
+// LLKeyConflictHandler
+
+S32 LLKeyConflictHandler::sTemporaryFileUseCount = 0;
+
+LLKeyConflictHandler::LLKeyConflictHandler()
+:   mHasUnsavedChanges(false),
+    mUsesTemporaryFile(false),
+    mLoadMode(MODE_COUNT)
+{
+}
+
+LLKeyConflictHandler::LLKeyConflictHandler(ESourceMode mode)
+:   mHasUnsavedChanges(false),
+    mUsesTemporaryFile(false),
+    mLoadMode(mode)
+{
+    loadFromSettings(mode);
+}
+
+LLKeyConflictHandler::~LLKeyConflictHandler()
+{
+    clearUnsavedChanges();
+    // Note: does not reset bindings if temporary file was used
+}
+
+bool LLKeyConflictHandler::canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask)
+{
+    return mControlsMap[control_name].canHandle(mouse_ind, key, mask);
+}
+
+bool LLKeyConflictHandler::canHandleKey(const std::string &control_name, KEY key, MASK mask)
+{
+    return canHandleControl(control_name, CLICK_NONE, key, mask);
+}
+
+bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask)
+{
+    return canHandleControl(control_name, mouse_ind, KEY_NONE, mask);
+}
+
+bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask)
+{
+    return canHandleControl(control_name, (EMouseClickType)mouse_ind, KEY_NONE, mask);
+}
+
+bool LLKeyConflictHandler::canAssignControl(const std::string &control_name)
+{
+    control_map_t::iterator iter = mControlsMap.find(control_name);
+    if (iter != mControlsMap.end())
+    {
+        return iter->second.mAssignable;
+    }
+    // If we don't know this control means it wasn't assigned by user yet and thus is editable
+    return true;
+}
+
+// static
+bool LLKeyConflictHandler::isReservedByMenu(const KEY &key, const MASK &mask)
+{
+    if (key == KEY_NONE)
+    {
+        return false;
+    }
+    return (gMenuBarView && gMenuBarView->hasAccelerator(key, mask))
+           || (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(key, mask));
+}
+
+// static
+bool LLKeyConflictHandler::isReservedByMenu(const LLKeyData &data)
+{
+    if (data.mMouse != CLICK_NONE || data.mKey == KEY_NONE)
+    {
+        return false;
+    }
+    return (gMenuBarView && gMenuBarView->hasAccelerator(data.mKey, data.mMask))
+           || (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(data.mKey, data.mMask));
+}
+
+bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask)
+{
+    if (control_name.empty())
+    {
+        return false;
+    }
+    LLKeyConflict &type_data = mControlsMap[control_name];
+    if (!type_data.mAssignable)
+    {
+        LL_ERRS() << "Error in code, user or system should not be able to change certain controls" << LL_ENDL;
+    }
+    LLKeyData data(mouse, key, mask, ignore_mask);
+    if (type_data.mKeyBind.getKeyData(index) == data)
+    {
+        return true;
+    }
+    if (isReservedByMenu(data))
+    {
+        return false;
+    }
+    if (removeConflicts(data, type_data.mConflictMask))
+    {
+        type_data.mKeyBind.replaceKeyData(data, index);
+        mHasUnsavedChanges = true;
+        return true;
+    }
+    // control already in use/blocked
+    return false;
+}
+
+LLKeyData LLKeyConflictHandler::getControl(const std::string &control_name, U32 index)
+{
+    if (control_name.empty())
+    {
+        return LLKeyData();
+    }
+    return mControlsMap[control_name].getKeyData(index);
+}
+
+// static
+std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata)
+{
+    std::string result;
+
+    if (keydata.mMask != MASK_NONE && keydata.mKey != KEY_NONE)
+    {
+        result = LLKeyboard::stringFromAccelerator(keydata.mMask, keydata.mKey);
+    }
+    else if (keydata.mKey != KEY_NONE)
+    {
+        result = LLKeyboard::stringFromKey(keydata.mKey);
+    }
+    else if (keydata.mMask != MASK_NONE)
+    {
+        result = LLKeyboard::stringFromAccelerator(keydata.mMask);
+    }
+
+    result += string_from_mouse(keydata.mMouse, true);
+
+    return result;
+}
+
+std::string LLKeyConflictHandler::getControlString(const std::string &control_name, U32 index)
+{
+    if (control_name.empty())
+    {
+        return "";
+    }
+    return getStringFromKeyData(mControlsMap[control_name].getKeyData(index));
+}
+
+void LLKeyConflictHandler::loadFromControlSettings(const std::string &name)
+{
+    LLControlVariablePtr var = gSavedSettings.getControl(name);
+    if (var)
+    {
+        LLKeyBind bind(var->getValue());
+        LLKeyConflict key(bind, true, 0);
+        mControlsMap[name] = key;
+    }
+}
+
+void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymode, control_map_t *destination)
+{
+    for (LLInitParam::ParamIterator<LLViewerInput::KeyBinding>::const_iterator it = keymode.bindings.begin(),
+        end_it = keymode.bindings.end();
+        it != end_it;
+    ++it)
+    {
+        KEY key;
+        MASK mask;
+        EMouseClickType mouse = CLICK_NONE;
+        if (it->mouse.isProvided())
+        {
+            LLViewerInput::mouseFromString(it->mouse.getValue(), &mouse);
+        }
+        if (it->key.getValue().empty())
+        {
+            key = KEY_NONE;
+        }
+        else
+        {
+            LLKeyboard::keyFromString(it->key, &key);
+        }
+        LLKeyboard::maskFromString(it->mask, &mask);
+        // Note: it->command is also the name of UI element, howhever xml we are loading from
+        // might not know all the commands, so UI will have to know what to fill by its own
+        LLKeyConflict &type_data = (*destination)[it->command];
+        type_data.mAssignable = true;
+        type_data.mKeyBind.addKeyData(mouse, key, mask, true);
+    }
+}
+
+bool LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination)
+{
+    if (filename.empty())
+    {
+        return false;
+    }
+
+    bool res = false;
+
+    LLViewerInput::Keys keys;
+    LLSimpleXUIParser parser;
+
+    if (parser.readXUI(filename, keys)
+        && keys.validateBlock())
+    {
+        switch (load_mode)
+        {
+        case MODE_FIRST_PERSON:
+            if (keys.first_person.isProvided())
+            {
+                loadFromSettings(keys.first_person, destination);
+                res = true;
+            }
+            break;
+        case MODE_THIRD_PERSON:
+            if (keys.third_person.isProvided())
+            {
+                loadFromSettings(keys.third_person, destination);
+                res = true;
+            }
+            break;
+        case MODE_EDIT_AVATAR:
+            if (keys.edit_avatar.isProvided())
+            {
+                loadFromSettings(keys.edit_avatar, destination);
+                res = true;
+            }
+            break;
+        case MODE_SITTING:
+            if (keys.sitting.isProvided())
+            {
+                loadFromSettings(keys.sitting, destination);
+                res = true;
+            }
+            break;
+        default:
+            LL_ERRS() << "Not implememted mode " << load_mode << LL_ENDL;
+            break;
+        }
+    }
+    return res;
+}
+
+void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode)
+{
+    mControlsMap.clear();
+    mDefaultsMap.clear();
+
+    // E.X. In case we need placeholder keys for conflict resolution.
+    generatePlaceholders(load_mode);
+
+    if (load_mode == MODE_SAVED_SETTINGS)
+    {
+        // load settings clss knows about, but it also possible to load settings by name separately
+        const S32 size = std::extent<decltype(saved_settings_key_controls)>::value;
+        for (U32 i = 0; i < size; i++)
+        {
+            loadFromControlSettings(saved_settings_key_controls[i]);
+        }
+    }
+    else
+    {
+        // load defaults
+        std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename_default);
+        if (!loadFromSettings(load_mode, filename, &mDefaultsMap))
+        {
+            LL_WARNS() << "Failed to load default settings, aborting" << LL_ENDL;
+            return;
+        }
+
+        // load user's
+        filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default);
+        if (!gDirUtilp->fileExists(filename) || !loadFromSettings(load_mode, filename, &mControlsMap))
+        {
+            // mind placeholders
+            mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end());
+        }
+    }
+    mLoadMode = load_mode;
+}
+
+void LLKeyConflictHandler::saveToSettings(bool temporary)
+{
+    if (mControlsMap.empty())
+    {
+        return;
+    }
+
+    if (mLoadMode == MODE_SAVED_SETTINGS)
+    {
+        // Does not support 'temporary', preferences handle that themself
+        // so in case of saved settings we just do not clear mHasUnsavedChanges
+        control_map_t::iterator iter = mControlsMap.begin();
+        control_map_t::iterator end = mControlsMap.end();
+
+        for (; iter != end; ++iter)
+        {
+            if (iter->first.empty())
+            {
+                continue;
+            }
+
+            LLKeyConflict &key = iter->second;
+            key.mKeyBind.trimEmpty();
+            if (!key.mAssignable)
+            {
+                continue;
+            }
+
+            if (gSavedSettings.controlExists(iter->first))
+            {
+                gSavedSettings.setLLSD(iter->first, key.mKeyBind.asLLSD());
+            }
+            else if (!key.mKeyBind.empty())
+            {
+                // Note: this is currently not in use, might be better for load mechanics to ask for and retain control group
+                // otherwise settings loaded from other control groups will end in this one
+                LL_INFOS() << "Creating new keybinding " << iter->first << LL_ENDL;
+                gSavedSettings.declareLLSD(iter->first, key.mKeyBind.asLLSD(), "comment", LLControlVariable::PERSIST_ALWAYS);
+            }
+        }
+    }
+    else
+    {
+        // Determine what file to load and load full copy of that file
+        std::string filename;
+
+        if (temporary)
+        {
+            filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_temporary);
+            if (!gDirUtilp->fileExists(filename))
+            {
+                filename.clear();
+            }
+        }
+
+        if (filename.empty())
+        {
+            filename = gDirUtilp->findFile(filename_default,
+                gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
+                gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+        }
+
+        LLViewerInput::Keys keys;
+        LLSimpleXUIParser parser;
+
+        if (parser.readXUI(filename, keys)
+            && keys.validateBlock())
+        {
+            // replace category we edited
+
+            // mode is a HACK to correctly reset bindings without reparsing whole file and avoid doing
+            // own param container (which will face issues with inasseesible members of LLInitParam)
+            LLViewerInput::KeyMode mode;
+            LLViewerInput::KeyBinding binding;
+
+            control_map_t::iterator iter = mControlsMap.begin();
+            control_map_t::iterator end = mControlsMap.end();
+            for (; iter != end; ++iter)
+            {
+                // By default xml have (had) up to 6 elements per function
+                // eventually it will be cleaned up and UI will only shows 3 per function,
+                // so make sure to cleanup.
+                // Also this helps in keeping file small.
+                iter->second.mKeyBind.trimEmpty();
+                U32 size = iter->second.mKeyBind.getDataCount();
+                for (U32 i = 0; i < size; ++i)
+                {
+                    if (iter->first.empty())
+                    {
+                        continue;
+                    }
+
+                    LLKeyConflict &key = iter->second;
+                    key.mKeyBind.trimEmpty();
+                    if (key.mKeyBind.empty() || !key.mAssignable)
+                    {
+                        continue;
+                    }
+
+                    LLKeyData data = key.mKeyBind.getKeyData(i);
+                    // Still write empty LLKeyData to make sure we will maintain UI position
+                    if (data.mKey == KEY_NONE)
+                    {
+                        // Might be better idea to be consistent and use NONE. LLViewerInput can work with both cases
+                        binding.key = "";
+                    }
+                    else
+                    {
+                        binding.key = LLKeyboard::stringFromKey(data.mKey, false /*Do not localize*/);
+                    }
+                    binding.mask = string_from_mask(data.mMask);
+                    if (data.mMouse == CLICK_NONE)
+                    {
+                        binding.mouse.setProvided(false);
+                    }
+                    else
+                    {
+                        // set() because 'optional', for compatibility purposes
+                        // just copy old keys.xml and rename to key_bindings.xml, it should work
+                        binding.mouse.set(string_from_mouse(data.mMouse, false), true);
+                    }
+                    binding.command = iter->first;
+                    mode.bindings.add(binding);
+                }
+            }
+
+            switch (mLoadMode)
+            {
+            case MODE_FIRST_PERSON:
+                if (keys.first_person.isProvided())
+                {
+                    keys.first_person.bindings.set(mode.bindings, true);
+                }
+                break;
+            case MODE_THIRD_PERSON:
+                if (keys.third_person.isProvided())
+                {
+                    keys.third_person.bindings.set(mode.bindings, true);
+                }
+                break;
+            case MODE_EDIT_AVATAR:
+                if (keys.edit_avatar.isProvided())
+                {
+                    keys.edit_avatar.bindings.set(mode.bindings, true);
+                }
+                break;
+            case MODE_SITTING:
+                if (keys.sitting.isProvided())
+                {
+                    keys.sitting.bindings.set(mode.bindings, true);
+                }
+                break;
+            default:
+                LL_ERRS() << "Not implememted mode " << mLoadMode << LL_ENDL;
+                break;
+            }
+
+            if (temporary)
+            {
+                // write to temporary xml and use it for gViewerInput
+                filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_temporary);
+                if (!mUsesTemporaryFile)
+                {
+                    mUsesTemporaryFile = true;
+                    sTemporaryFileUseCount++;
+                }
+            }
+            else
+            {
+                // write back to user's xml and use it for gViewerInput
+                filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default);
+                // Don't reset mUsesTemporaryFile, it will be reset at cleanup stage
+            }
+
+            LLXMLNodePtr output_node = new LLXMLNode("keys", false);
+            LLXUIParser parser;
+            parser.writeXUI(output_node, keys);
+
+            // Write the resulting XML to file
+            if (!output_node->isNull())
+            {
+                LLFILE *fp = LLFile::fopen(filename, "w");
+                if (fp != NULL)
+                {
+                    LLXMLNode::writeHeaderToFile(fp);
+                    output_node->writeToFile(fp);
+                    fclose(fp);
+                }
+            }
+            // Now force a rebind for keyboard
+            if (gDirUtilp->fileExists(filename))
+            {
+                // Ideally instead of rebinding immediately we should shedule
+                // the rebind since single file can have multiple handlers,
+                // one per mode, saving simultaneously.
+                // Or whatever uses LLKeyConflictHandler should control the process.
+                gViewerInput.loadBindingsXML(filename);
+            }
+        }
+    }
+
+    if (!temporary)
+    {
+        // will remove any temporary file if there were any
+        clearUnsavedChanges();
+    }
+}
+
+LLKeyData LLKeyConflictHandler::getDefaultControl(const std::string &control_name, U32 index)
+{
+    if (control_name.empty())
+    {
+        return LLKeyData();
+    }
+    if (mLoadMode == MODE_SAVED_SETTINGS)
+    {
+        LLControlVariablePtr var = gSavedSettings.getControl(control_name);
+        if (var)
+        {
+            return LLKeyBind(var->getDefault()).getKeyData(index);
+        }
+        return LLKeyData();
+    }
+    else
+    {
+        control_map_t::iterator iter = mDefaultsMap.find(control_name);
+        if (iter != mDefaultsMap.end())
+        {
+            return iter->second.mKeyBind.getKeyData(index);
+        }
+        return LLKeyData();
+    }
+}
+
+void LLKeyConflictHandler::resetToDefault(const std::string &control_name, U32 index)
+{
+    if (control_name.empty())
+    {
+        return;
+    }
+    LLKeyData data = getDefaultControl(control_name, index);
+
+    if (data != mControlsMap[control_name].getKeyData(index))
+    {
+        // reset controls that might have been switched to our current control
+        removeConflicts(data, mControlsMap[control_name].mConflictMask);
+        mControlsMap[control_name].setKeyData(data, index);
+    }
+}
+
+void LLKeyConflictHandler::resetToDefaultAndResolve(const std::string &control_name, bool ignore_conflicts)
+{
+    if (control_name.empty())
+    {
+        return;
+    }
+    if (mLoadMode == MODE_SAVED_SETTINGS)
+    {
+        LLControlVariablePtr var = gSavedSettings.getControl(control_name);
+        if (var)
+        {
+            LLKeyBind bind(var->getDefault());
+            if (!ignore_conflicts)
+            {
+                for (S32 i = 0; i < bind.getDataCount(); ++i)
+                {
+                    removeConflicts(bind.getKeyData(i), mControlsMap[control_name].mConflictMask);
+                }
+            }
+            mControlsMap[control_name].mKeyBind = bind;
+        }
+        else
+        {
+            mControlsMap[control_name].mKeyBind.clear();
+        }
+    }
+    else
+    {
+        control_map_t::iterator iter = mDefaultsMap.find(control_name);
+        if (iter != mDefaultsMap.end())
+        {
+            if (!ignore_conflicts)
+            {
+                for (S32 i = 0; i < iter->second.mKeyBind.getDataCount(); ++i)
+                {
+                    removeConflicts(iter->second.mKeyBind.getKeyData(i), mControlsMap[control_name].mConflictMask);
+                }
+            }
+            mControlsMap[control_name].mKeyBind = iter->second.mKeyBind;
+        }
+        else
+        {
+            mControlsMap[control_name].mKeyBind.clear();
+        }
+    }
+}
+
+void LLKeyConflictHandler::resetToDefault(const std::string &control_name)
+{
+    // reset specific binding without ignoring conflicts
+    resetToDefaultAndResolve(control_name, false);
+}
+
+void LLKeyConflictHandler::resetToDefaults(ESourceMode mode)
+{
+    if (mode == MODE_SAVED_SETTINGS)
+    {
+        control_map_t::iterator iter = mControlsMap.begin();
+        control_map_t::iterator end = mControlsMap.end();
+
+        for (; iter != end; ++iter)
+        {
+            resetToDefaultAndResolve(iter->first, true);
+        }
+    }
+    else
+    {
+        mControlsMap.clear();
+        generatePlaceholders(mode);
+        mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end());
+    }
+
+    mHasUnsavedChanges = true;
+}
+
+void LLKeyConflictHandler::resetToDefaults()
+{
+    if (!empty())
+    {
+        resetToDefaults(mLoadMode);
+    }
+    else
+    {
+        // not optimal since:
+        // 1. We are not sure that mLoadMode was set
+        // 2. We are not sure if there are any changes in comparison to default
+        // 3. We are loading 'current' only to replace it
+        // but it is reliable and works Todo: consider optimizing.
+        loadFromSettings(mLoadMode);
+        resetToDefaults(mLoadMode);
+    }
+}
+
+void LLKeyConflictHandler::clear()
+{
+    if (clearUnsavedChanges())
+    {
+        // temporary file was removed, this means we were using it and need to reload keyboard's bindings
+        resetKeyboardBindings();
+    }
+    mControlsMap.clear();
+    mDefaultsMap.clear();
+}
+
+// static
+void LLKeyConflictHandler::resetKeyboardBindings()
+{
+    // Try to load User's bindings first
+    std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default);
+    if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file))
+    {
+        // Failed to load custom bindings, try default ones
+        key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename_default);
+        if (!gViewerInput.loadBindingsXML(key_bindings_file))
+        {
+            LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL;
+        }
+    }
+}
+
+void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode)
+{
+    // These controls are meant to cause conflicts when user tries to assign same control somewhere else
+    // also this can be used to pre-record controls that should not conflict or to assign conflict groups/masks
+    /*registerTemporaryControl(CONTROL_RESERVED_MENU, CLICK_RIGHT, KEY_NONE, MASK_NONE, 0);
+    registerTemporaryControl(CONTROL_DELETE, CLICK_NONE, KEY_DELETE, MASK_NONE, 0);*/
+}
+
+bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &conlict_mask)
+{
+    if (conlict_mask == CONFLICT_NOTHING)
+    {
+        // Can't conflict
+        return true;
+    }
+    std::map<std::string, S32> conflict_list;
+    control_map_t::iterator cntrl_iter = mControlsMap.begin();
+    control_map_t::iterator cntrl_end = mControlsMap.end();
+    for (; cntrl_iter != cntrl_end; ++cntrl_iter)
+    {
+        S32 index = cntrl_iter->second.mKeyBind.findKeyData(data);
+        if (index >= 0
+            && cntrl_iter->second.mConflictMask != CONFLICT_NOTHING
+            && (cntrl_iter->second.mConflictMask & conlict_mask) != 0)
+        {
+            if (cntrl_iter->second.mAssignable)
+            {
+                // Potentially we can have multiple conflict flags conflicting
+                // including unassignable keys.
+                // So record the conflict and find all others before doing any changes.
+                // Assume that there is only one conflict per bind
+                conflict_list[cntrl_iter->first] = index;
+            }
+            else
+            {
+                return false;
+            }
+        }
+    }
+
+    std::map<std::string, S32>::iterator cnflct_iter = conflict_list.begin();
+    std::map<std::string, S32>::iterator cnflct_end = conflict_list.end();
+    for (; cnflct_iter != cnflct_end; ++cnflct_iter)
+    {
+        mControlsMap[cnflct_iter->first].mKeyBind.resetKeyData(cnflct_iter->second);
+    }
+    return true;
+}
+
+void LLKeyConflictHandler::registerTemporaryControl(const std::string &control_name, EMouseClickType mouse, KEY key, MASK mask, U32 conflict_mask)
+{
+    LLKeyConflict *type_data = &mControlsMap[control_name];
+    type_data->mAssignable = false;
+    type_data->mConflictMask = conflict_mask;
+    type_data->mKeyBind.addKeyData(mouse, key, mask, false);
+}
+
+bool LLKeyConflictHandler::clearUnsavedChanges()
+{
+    bool result = false;
+    mHasUnsavedChanges = false;
+
+    if (mUsesTemporaryFile)
+    {
+        mUsesTemporaryFile = false;
+        sTemporaryFileUseCount--;
+        if (!sTemporaryFileUseCount)
+        {
+            result = clearTemporaryFile();
+        }
+        // else: might be usefull to overwrite content of temp file with defaults
+        // but at the moment there is no such need
+    }
+    return result;
+}
+
+//static
+bool LLKeyConflictHandler::clearTemporaryFile()
+{
+    // At the moment single file needs five handlers (one per mode), so doing this
+    // will remove file for all hadlers
+    std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_temporary);
+    if (gDirUtilp->fileExists(filename))
+    {
+        LLFile::remove(filename);
+        return true;
+    }
+    return false;
+}
+
diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h
new file mode 100644
index 0000000000000000000000000000000000000000..84730e4d4f27b3b75ca8014ef73423caf58f7582
--- /dev/null
+++ b/indra/newview/llkeyconflict.h
@@ -0,0 +1,156 @@
+/** 
+ * @file llkeyconflict.h
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, 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$
+ */
+
+#ifndef LL_LLKEYCONFLICT_H
+#define LL_LLKEYCONFLICT_H
+
+#include "llkeybind.h"
+#include "llviewerinput.h"
+
+
+class LLKeyConflict
+{
+public:
+    LLKeyConflict() : mAssignable(true), mConflictMask(U32_MAX) {} //temporary assignable, don't forget to change once all keys are recorded
+    LLKeyConflict(bool assignable, U32 conflict_mask)
+        : mAssignable(assignable), mConflictMask(conflict_mask) {}
+    LLKeyConflict(const LLKeyBind &bind, bool assignable, U32 conflict_mask)
+        : mAssignable(assignable), mConflictMask(conflict_mask), mKeyBind(bind) {}
+
+    LLKeyData getPrimaryKeyData() { return mKeyBind.getKeyData(0); }
+    LLKeyData getKeyData(U32 index) { return mKeyBind.getKeyData(index); }
+    void setPrimaryKeyData(const LLKeyData& data) { mKeyBind.replaceKeyData(data, 0); }
+    void setKeyData(const LLKeyData& data, U32 index) { mKeyBind.replaceKeyData(data, index); }
+    bool canHandle(EMouseClickType mouse, KEY key, MASK mask) { return mKeyBind.canHandle(mouse, key, mask); }
+
+    LLKeyBind mKeyBind;
+    bool mAssignable; // whether user can change key or key simply acts as placeholder
+    U32 mConflictMask;
+};
+
+class LLKeyConflictHandler
+{
+public:
+
+    enum ESourceMode // partially repeats e_keyboard_mode
+    {
+        MODE_FIRST_PERSON,
+        MODE_THIRD_PERSON,
+        MODE_EDIT_AVATAR,
+        MODE_SITTING,
+        MODE_SAVED_SETTINGS, // for settings from saved settings
+        MODE_COUNT
+    };
+
+    const U32 CONFLICT_NOTHING = 0;
+    // at the moment this just means that key will conflict with everything that is identical
+    const U32 CONFLICT_ANY = U32_MAX;
+
+    // Note: missed selection and edition commands (would be really nice to go through selection via MB4/5 or wheel)
+
+    LLKeyConflictHandler();
+    LLKeyConflictHandler(ESourceMode mode);
+    ~LLKeyConflictHandler();
+
+    bool canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask);
+    bool canHandleKey(const std::string &control_name, KEY key, MASK mask);
+    bool canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask);
+    bool canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask); //Just for convinience
+    bool canAssignControl(const std::string &control_name);
+    static bool isReservedByMenu(const KEY &key, const MASK &mask);
+    static bool isReservedByMenu(const LLKeyData &data);
+    bool registerControl(const std::string &control_name, U32 data_index, EMouseClickType mouse_ind, KEY key, MASK mask, bool ignore_mask); //todo: return conflicts?
+
+    LLKeyData getControl(const std::string &control_name, U32 data_index);
+
+    // localized string
+    static std::string getStringFromKeyData(const LLKeyData& keydata);
+    std::string getControlString(const std::string &control_name, U32 data_index);
+
+    // Load single control, overrides existing one if names match
+    void loadFromControlSettings(const std::string &name);
+    // Drops any changes loads controls with ones from 'saved settings' or from xml
+    void loadFromSettings(ESourceMode load_mode);
+
+    // Saves settings to 'saved settings' or to xml
+    // If 'temporary' is set, function will save settings to temporary
+    // file and reload input bindings from temporary file.
+    // 'temporary' does not support gSavedSettings, those are handled
+    // by preferences, so 'temporary' is such case will simply not
+    // reset mHasUnsavedChanges
+    void saveToSettings(bool apply_temporary = false);
+
+    LLKeyData getDefaultControl(const std::string &control_name, U32 data_index);
+    // Resets keybinding to default variant from 'saved settings' or xml
+    void resetToDefault(const std::string &control_name, U32 index);
+    void resetToDefault(const std::string &control_name);
+    // resets current mode to defaults
+    void resetToDefaults();
+
+    bool empty() { return mControlsMap.empty(); }
+    void clear();
+
+    // reloads bindings from last valid user's xml or from default xml
+    // to keyboard's handler
+    static void resetKeyboardBindings();
+
+    bool hasUnsavedChanges() { return mHasUnsavedChanges; }
+    void setLoadMode(ESourceMode mode) { mLoadMode = mode; }
+    ESourceMode getLoadMode() { return mLoadMode; }
+
+private:
+    void resetToDefaultAndResolve(const std::string &control_name, bool ignore_conflicts);
+    void resetToDefaults(ESourceMode mode);
+
+    // at the moment these kind of control is not savable, but takes part will take part in conflict resolution
+    void registerTemporaryControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask, U32 conflict_mask);
+
+    typedef std::map<std::string, LLKeyConflict> control_map_t;
+    void loadFromSettings(const LLViewerInput::KeyMode& keymode, control_map_t *destination);
+    bool loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination);
+    void generatePlaceholders(ESourceMode load_mode); //E.x. non-assignable values
+    // returns false in case user is trying to reuse control that can't be reassigned
+    bool removeConflicts(const LLKeyData &data, const U32 &conlict_mask);
+
+    // removes flags and removes temporary file, returns 'true' if file was removed
+    bool clearUnsavedChanges();
+    // return true if there was a file to remove
+    static bool clearTemporaryFile();
+
+    control_map_t mControlsMap;
+    control_map_t mDefaultsMap;
+    bool mHasUnsavedChanges;
+    ESourceMode mLoadMode;
+
+    // To implement 'apply immediately'+revert on cancel, class applies changes to temporary file
+    // but this only works for settings from keybndings files (key_bindings.xml)
+    // saved setting rely onto external mechanism of preferences floater
+    bool mUsesTemporaryFile;
+    static S32 sTemporaryFileUseCount;
+};
+
+
+#endif  // LL_LLKEYCONFLICT_H
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 42b5ff38907cced1436c0c22f186c946d8aa1629..802e4941e634c6137f7faee131054389ac7b7ce1 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -1100,9 +1100,7 @@ void LLLocationInputCtrl::changeLocationPresentation()
 
 	//change location presentation only if user does not select/paste anything and 
 	//human-readable region name is being displayed
-	std::string text = mTextEntry->getText();
-	LLStringUtil::trim(text);
-	if(!mTextEntry->hasSelection() && text == mHumanReadableLocation)
+	if(!mTextEntry->hasSelection() && mTextEntry->getText() == mHumanReadableLocation)
 	{
 		//needs unescaped one
 		LLSLURL slurl;
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 453bf17b119bf9fef9c8eff362a8272d498dd61e..0c64531783b6cfa32c73626fd068dc313bfb4373 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -67,6 +67,8 @@ const std::string LL_IM_FROM("from");
 const std::string LL_IM_FROM_ID("from_id");
 const std::string LL_TRANSCRIPT_FILE_EXTENSION("txt");
 
+const std::string GROUP_CHAT_SUFFIX(" (group)");
+
 const static char IM_SYMBOL_SEPARATOR(':');
 const static std::string IM_SEPARATOR(std::string() + IM_SYMBOL_SEPARATOR + " ");
 const static std::string NEW_LINE("\n");
@@ -355,7 +357,7 @@ void LLLogChat::saveHistory(const std::string& filename,
 }
 
 // static
-void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params)
+void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params, bool is_group)
 {
 	if (file_name.empty())
 	{
@@ -368,10 +370,25 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m
 	LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
 	if (!fptr)
 	{
-		fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+		if (is_group)
+		{
+			std::string old_name(file_name);
+			old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size());
+			fptr = LLFile::fopen(LLLogChat::makeLogFileName(old_name), "r");
+			if (fptr)
+			{
+				fclose(fptr);
+				LLFile::copy(LLLogChat::makeLogFileName(old_name), LLLogChat::makeLogFileName(file_name));
+			}
+			fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");
+		}
 		if (!fptr)
 		{
-			return;						//No previous conversation with this name.
+			fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+			if (!fptr)
+			{
+				return;						//No previous conversation with this name.
+			}
 		}
 	}
 
@@ -1053,12 +1070,28 @@ void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list<LL
 
 	if (!fptr)
 	{
-		fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+		bool is_group = load_params.has("is_group") ? load_params["is_group"].asBoolean() : false;
+		if (is_group)
+		{
+			std::string old_name(file_name);
+			old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size());
+			fptr = LLFile::fopen(LLLogChat::makeLogFileName(old_name), "r");
+			if (fptr)
+			{
+				fclose(fptr);
+				LLFile::copy(LLLogChat::makeLogFileName(old_name), LLLogChat::makeLogFileName(file_name));
+			}
+			fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");
+		}
 		if (!fptr)
 		{
-			mNewLoad = false;
-			(*mLoadEndSignal)(messages, file_name);
-			return;						//No previous conversation with this name.
+			fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+			if (!fptr)
+			{
+				mNewLoad = false;
+				(*mLoadEndSignal)(messages, file_name);
+				return;						//No previous conversation with this name.
+			}
 		}
 	}
 
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index b71a34ae0aaac1a7b6d3cc3c0b05637b8417e35f..8b7fe14e1684ad4c6c4b7596a09aaa948978f154 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -106,7 +106,7 @@ class LLLogChat : public LLSingleton<LLLogChat>
 	static void getListOfTranscriptFiles(std::vector<std::string>& list);
 	static void getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions);
 
-	static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD());
+	static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD(), bool is_group = false);
 
 	typedef boost::signals2::signal<void ()> save_history_signal_t;
 	boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb);
@@ -196,6 +196,7 @@ class LLChatLogParser
 	virtual ~LLChatLogParser() {};
 };
 
+extern const std::string GROUP_CHAT_SUFFIX;
 
 // LLSD map lookup constants
 extern const std::string LL_IM_TIME; //("time");
diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp
index eca34c0d4d47ae1bf7521ee1175b370bd1ddfba9..22cedf450eb9a009c2fe422573ba51ad9d634d80 100644
--- a/indra/newview/llloginhandler.cpp
+++ b/indra/newview/llloginhandler.cpp
@@ -139,8 +139,11 @@ LLPointer<LLCredential> LLLoginHandler::initializeLoginInfo()
 	// so try to load it from the UserLoginInfo                                                                          
 	result = loadSavedUserLoginInfo();                                                                                   
 	if (result.isNull())                                                                                                 
-	{                                                                                                                    
-		result =  gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());                       
+	{
+        // Since legacy viewer store login info one per grid, newer viewers have to
+        // reuse same information to remember last user and for compatibility,
+        // but otherwise login info is stored in separate map in gSecAPIHandler
+        result = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
 	}                                                                                                                    
 	
 	return result;                                                                                                       
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 805c25508fe4f5d5e9da0d6550846154b7cdc73d..aa0c7fb73bcbe46d739a249d0fe020fedbf1c28a 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -1294,6 +1294,11 @@ void LLMarketplaceData::setSLMDataFetched(U32 status)
     }
 }
 
+bool LLMarketplaceData::isSLMDataFetched()
+{
+    return mMarketPlaceDataFetched == MarketplaceFetchCodes::MARKET_FETCH_DONE;
+}
+
 // Creation / Deletion / Update
 // Methods publicly called
 bool LLMarketplaceData::createListing(const LLUUID& folder_id)
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index ec312baca395b65116c27286cfe73c53ec7f3229..fee9225f77c5905d04f5530e2694c14ece2e1c74 100644
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -204,7 +204,9 @@ class LLMarketplaceData
     void setDataFetchedSignal(const status_updated_signal_t::slot_type& cb);
     void setSLMDataFetched(U32 status);
     U32 getSLMDataFetched() { return mMarketPlaceDataFetched; }
-    
+
+    bool isSLMDataFetched();
+
     // High level create/delete/set Marketplace data: each method returns true if the function succeeds, false if error
     bool createListing(const LLUUID& folder_id);
     bool activateListing(const LLUUID& folder_id, bool activate, S32 depth = -1);
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index b399ab9bc4f5d0dd11e7c36b834b6fae06ab3c78..0affe8efb4b51f15efb57b8560ade06b949b4e08 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -202,11 +202,28 @@ BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks )
 {
 	if (LLPanel::handleScrollWheel(x, y, clicks)) return TRUE;
 	if (mMediaSource && mMediaSource->hasMedia())
-		mMediaSource->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE));
+	{
+		convertInputCoords(x, y);
+		mMediaSource->scrollWheel(x, y, 0, clicks, gKeyboard->currentMask(TRUE));
+	}
 
 	return TRUE;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+    if (LLPanel::handleScrollHWheel(x, y, clicks)) return TRUE;
+    if (mMediaSource && mMediaSource->hasMedia())
+    {
+        convertInputCoords(x, y);
+        mMediaSource->scrollWheel(x, y, clicks, 0, gKeyboard->currentMask(TRUE));
+    }
+
+    return TRUE;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 //	virtual 
 BOOL LLMediaCtrl::handleToolTip(S32 x, S32 y, MASK mask)
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 11400c82742cb624df901cf222ffe36f846ba2a8..958c76f2613fb855a94ab3a4a0b03ce24ccb3f92 100644
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -92,6 +92,7 @@ class LLMediaCtrl :
 		virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
 		virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
 		virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
+		virtual BOOL handleScrollHWheel( S32 x, S32 y, S32 clicks );
 		virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
 
 		// navigation
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 31e3d408d7d95c5cd440ad38c3d9429e1fc6deaf..ce41e2bd3519c380f8c8f1b394dee64f4e90b3e8 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1889,7 +1889,7 @@ EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_p
 		std::string mesh_string((char*)data, data_size);
 		stream.str(mesh_string);
 	}
-	catch (std::bad_alloc)
+	catch (std::bad_alloc&)
 	{
 		// out of memory, we won't be able to process this mesh
 		return MESH_OUT_OF_MEMORY;
@@ -2772,7 +2772,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
 
 			if (observer)
 			{
-				observer->setModelPhysicsFeeErrorStatus(status.toULong(), reason);
+				observer->setModelPhysicsFeeErrorStatus(status.toULong(), reason, body["error"]);
 			}
 		}
 		else
@@ -2805,7 +2805,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
 
 				if (observer)
 				{
-					observer->setModelPhysicsFeeErrorStatus(status.toULong(), reason);
+					observer->setModelPhysicsFeeErrorStatus(status.toULong(), reason, body["error"]);
 				}
 			}
 		}
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index 8fc356c9282045bbe75dded7e944ac2c95aa083d..54409a69943fb201bec596cfad43d18d656fefa5 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -574,6 +574,8 @@ BOOL LLPanelStandStopFlying::postBuild()
 	//mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE));
 	mStopFlyingButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStopFlyingButtonClick, this));
 	mStopFlyingButton->setVisible(FALSE);
+
+	gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLPanelStandStopFlying::updatePosition, this));
 	
 	return TRUE;
 }
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index fc1039b37257467074a5dfb53eaf9f5dd6cfe843..112da556825647b5d5d1ed65cd2119c8f576b1e2 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -354,7 +354,7 @@ void LLNetMap::draw()
 
 			LLColor4 color = show_as_friend ? map_avatar_friend_color : map_avatar_color;
 
-			unknown_relative_z = positions[i].mdV[VZ] == COARSEUPDATE_MAX_Z &&
+			unknown_relative_z = positions[i].mdV[VZ] >= COARSEUPDATE_MAX_Z &&
 					camera_position.mV[VZ] >= COARSEUPDATE_MAX_Z;
 
 			LLWorldMapView::drawAvatar(
diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp
index b405d3dca24ef96598dd8c2c0173a2f05dc2824a..6a79a0c68cf9224f873f5332187fda8a24e33443 100644
--- a/indra/newview/llnotificationlistitem.cpp
+++ b/indra/newview/llnotificationlistitem.cpp
@@ -262,6 +262,7 @@ std::set<std::string> LLTransactionNotificationListItem::getTypes()
     std::set<std::string> types;
     types.insert("PaymentReceived");
     types.insert("PaymentSent");
+    types.insert("UploadPayment");
     return types;
 }
 
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index b2b6de94b3bedf231fbedfebb19c5d11371875df..12b46e9bb23cdd96221b60f294214c6421abf13e 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -1364,6 +1364,7 @@ void LLOutfitGallery::onSelectPhoto(LLUUID selected_outfit_id)
                 texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLOutfitGallery::onTexturePickerCommit, this, _1, _2));
                 texture_floaterp->setOnUpdateImageStatsCallback(boost::bind(&LLOutfitGallery::onTexturePickerUpdateImageStats, this, _1));
                 texture_floaterp->setLocalTextureEnabled(FALSE);
+                texture_floaterp->setCanApply(false, true);
             }
 
             floaterp->openFloater();
diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp
index 7f6c065bb9f8b3ba62d16d8e9a21b2d9e4e7fd0c..e9fe493d7ec294b11df910feb00d62b0310fa8aa 100644
--- a/indra/newview/lloutputmonitorctrl.cpp
+++ b/indra/newview/lloutputmonitorctrl.cpp
@@ -245,11 +245,11 @@ void LLOutputMonitorCtrl::draw()
 // virtual
 BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
 {
-	if (mSpeakerId != gAgentID && !mShowParticipantsSpeaking)
+	if (mSpeakerId != gAgentID)
 	{
 		LLFloaterReg::showInstance("floater_voice_volume", LLSD().with("avatar_id", mSpeakerId));
 	}
-	else if(mShowParticipantsSpeaking)
+	else if (mShowParticipantsSpeaking)
 	{
 		LLFloaterReg::showInstance("chat_voice", LLSD());
 	}
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 6d0c30fbf336917ddb1630503979178e3ff26464..c0342eef4e4de70ffe4e5b4101364c5a93946024 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -764,6 +764,7 @@ void LLPanelClassifiedEdit::processProperties(void* data, EAvatarProcessorType t
 			setClassifiedName(c_info->name);
 			setDescription(c_info->description);
 			setSnapshotId(c_info->snapshot_id);
+			setParcelId(c_info->parcel_id);
 			setPosGlobal(c_info->pos_global);
 
 			setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global));
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 0efb234015b52252f745b9798eefdd92ac554b3b..e3d75d5604d7368ed74d093e5444d325d9d67a58 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -1153,7 +1153,7 @@ void LLPanelGroupMembersSubTab::onInviteMember(void *userdata)
 
 void LLPanelGroupMembersSubTab::handleInviteMember()
 {
-	LLFloaterGroupInvite::showForGroup(mGroupID);
+	LLFloaterGroupInvite::showForGroup(mGroupID, NULL, false);
 }
 
 void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index e253557797de8c149132fbffcde1d8a1fce24e05..fd76a360444116063c8d9b5bc3d84d15d7e6010b 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -41,7 +41,6 @@
 #include "llcommandhandler.h"		// for secondlife:///app/login/
 #include "llcombobox.h"
 #include "llviewercontrol.h"
-#include "llfloaterpreference.h"
 #include "llfocusmgr.h"
 #include "lllineeditor.h"
 #include "llnotificationsutil.h"
@@ -77,6 +76,60 @@ LLPanelLogin *LLPanelLogin::sInstance = NULL;
 BOOL LLPanelLogin::sCapslockDidNotification = FALSE;
 BOOL LLPanelLogin::sCredentialSet = FALSE;
 
+// Helper functions
+
+LLPointer<LLCredential> load_user_credentials(std::string &user_key)
+{
+    if (gSecAPIHandler->hasCredentialMap("login_list", LLGridManager::getInstance()->getGrid()))
+    {
+        // user_key should be of "name Resident" format
+        return gSecAPIHandler->loadFromCredentialMap("login_list", LLGridManager::getInstance()->getGrid(), user_key);
+    }
+    else
+    {
+        // legacy (or legacy^2, since it also tries to load from settings)
+        return gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+    }
+}
+
+// keys are lower case to be case insensitive so they are not always
+// identical to names which retain user input, like:
+// "AwEsOmE Resident" -> "awesome_resident"
+std::string get_user_key_from_name(const std::string &username)
+{
+    std::string key = username;
+    LLStringUtil::trim(key);
+    LLStringUtil::toLower(key);
+    if (!LLGridManager::getInstance()->isSystemGrid())
+    {
+        size_t separator_index = username.find_first_of(" ");
+        if (separator_index == username.npos)
+        {
+            // CRED_IDENTIFIER_TYPE_ACCOUNT
+            return key;
+        }
+    }
+    // CRED_IDENTIFIER_TYPE_AGENT
+    size_t separator_index = username.find_first_of(" ._");
+    std::string first = username.substr(0, separator_index);
+    std::string last;
+    if (separator_index != username.npos)
+    {
+        last = username.substr(separator_index + 1, username.npos);
+        LLStringUtil::trim(last);
+    }
+    else
+    {
+        // ...on Linden grids, single username users as considered to have
+        // last name "Resident"
+        // *TODO: Make login.cgi support "account_name" like above
+        last = "resident";
+    }
+
+    key = first + "_" + last;
+    return key;
+}
+
 class LLLoginLocationAutoHandler : public LLCommandHandler
 {
 public:
@@ -168,6 +221,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 	mCallback(callback),
 	mCallbackData(cb_data),
 	mListener(new LLPanelLoginListener(this)),
+	mFirstLoginThisInstall(gSavedSettings.getBOOL("FirstLoginThisInstall")),
 	mUsernameLength(0),
 	mPasswordLength(0),
 	mLocationLength(0),
@@ -186,7 +240,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 		login_holder->addChild(this);
 	}
 
-	if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
+	if (mFirstLoginThisInstall)
 	{
 		buildFromFile( "panel_login_first.xml");
 	}
@@ -206,35 +260,39 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 	sendChildToBack(getChildView("forgot_password_text"));
 	sendChildToBack(getChildView("sign_up_text"));
 
-	LLComboBox* favorites_combo = getChild<LLComboBox>("start_location_combo");
-	updateLocationSelectorsVisibility(); // separate so that it can be called from preferences
-	favorites_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
-	favorites_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onLocationSLURL, this));
-	
-	LLComboBox* server_choice_combo = getChild<LLComboBox>("server_combo");
-	server_choice_combo->setCommitCallback(boost::bind(&LLPanelLogin::onSelectServer, this));
-	
-	// Load all of the grids, sorted, and then add a bar and the current grid at the top
-	server_choice_combo->removeall();
-
-	std::string current_grid = LLGridManager::getInstance()->getGrid();
-	std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
-	for (std::map<std::string, std::string>::iterator grid_choice = known_grids.begin();
-		 grid_choice != known_grids.end();
-		 grid_choice++)
-	{
-		if (!grid_choice->first.empty() && current_grid != grid_choice->first)
-		{
-			LL_DEBUGS("AppInit")<<"adding "<<grid_choice->first<<LL_ENDL;
-			server_choice_combo->add(grid_choice->second, grid_choice->first);
-		}
-	}
-	server_choice_combo->sortByName();
-	LL_DEBUGS("AppInit")<<"adding current "<<current_grid<<LL_ENDL;
-	server_choice_combo->add(LLGridManager::getInstance()->getGridLabel(), 
-							 current_grid,
-							 ADD_TOP);	
-	server_choice_combo->selectFirstItem();
+    std::string current_grid = LLGridManager::getInstance()->getGrid();
+    if (!mFirstLoginThisInstall)
+    {
+        LLComboBox* favorites_combo = getChild<LLComboBox>("start_location_combo");
+        updateLocationSelectorsVisibility(); // separate so that it can be called from preferences
+        favorites_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
+        favorites_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onLocationSLURL, this));
+
+        LLComboBox* server_choice_combo = getChild<LLComboBox>("server_combo");
+        server_choice_combo->setCommitCallback(boost::bind(&LLPanelLogin::onSelectServer, this));
+
+        // Load all of the grids, sorted, and then add a bar and the current grid at the top
+        server_choice_combo->removeall();
+
+        std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
+        for (std::map<std::string, std::string>::iterator grid_choice = known_grids.begin();
+            grid_choice != known_grids.end();
+            grid_choice++)
+        {
+            if (!grid_choice->first.empty() && current_grid != grid_choice->first)
+            {
+                LL_DEBUGS("AppInit") << "adding " << grid_choice->first << LL_ENDL;
+                server_choice_combo->add(grid_choice->second, grid_choice->first);
+            }
+        }
+        server_choice_combo->sortByName();
+
+        LL_DEBUGS("AppInit") << "adding current " << current_grid << LL_ENDL;
+        server_choice_combo->add(LLGridManager::getInstance()->getGridLabel(),
+            current_grid,
+            ADD_TOP);
+        server_choice_combo->selectFirstItem();
+    }
 
 	LLSLURL start_slurl(LLStartUp::getStartSLURL());
 	// The StartSLURL might have been set either by an explicit command-line
@@ -297,14 +355,30 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 	loadLoginPage();
 
 	LLComboBox* username_combo(getChild<LLComboBox>("username_combo"));
-	username_combo->setTextChangedCallback(boost::bind(&LLPanelLogin::addFavoritesToStartLocation, this));
+	username_combo->setTextChangedCallback(boost::bind(&LLPanelLogin::onUserNameTextEnty, this));
 	// STEAM-14: When user presses Enter with this field in focus, initiate login
-	username_combo->setCommitCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
+	username_combo->setCommitCallback(boost::bind(&LLPanelLogin::onUserListCommit, this));
+	username_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
 	username_combo->setKeystrokeOnEsc(TRUE);
+
+    if (!mFirstLoginThisInstall)
+    {
+        LLCheckBoxCtrl* remember_name = getChild<LLCheckBoxCtrl>("remember_name");
+        remember_name->setCommitCallback(boost::bind(&LLPanelLogin::onRememberUserCheck, this));
+    }
 }
 
 void LLPanelLogin::addFavoritesToStartLocation()
 {
+    if (mFirstLoginThisInstall)
+    {
+        // first login panel has no favorites, just update name length and buttons
+        std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple();
+        mUsernameLength = user_defined_name.length();
+        updateLoginButtons();
+        return;
+    }
+
 	// Clear the combo.
 	LLComboBox* combo = getChild<LLComboBox>("start_location_combo");
 	if (!combo) return;
@@ -316,14 +390,14 @@ void LLPanelLogin::addFavoritesToStartLocation()
 
 	// Load favorites into the combo.
 	std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple();
+	LLStringUtil::trim(user_defined_name);
 	LLStringUtil::toLower(user_defined_name);
-	std::replace(user_defined_name.begin(), user_defined_name.end(), '.', ' ');
 	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites_" + LLGridManager::getInstance()->getGrid() + ".xml");
 	std::string old_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
 	mUsernameLength = user_defined_name.length();
 	updateLoginButtons();
 
-	std::string::size_type index = user_defined_name.find(' ');
+	std::string::size_type index = user_defined_name.find_first_of(" ._");
 	if (index != std::string::npos)
 	{
 		std::string username = user_defined_name.substr(0, index);
@@ -332,6 +406,10 @@ void LLPanelLogin::addFavoritesToStartLocation()
 		{
 			user_defined_name = username;
 		}
+		else
+		{
+			user_defined_name = username + " " + lastname;
+		}
 	}
 
 	LLSD fav_llsd;
@@ -377,6 +455,10 @@ void LLPanelLogin::addFavoritesToStartLocation()
 		}
 		break;
 	}
+	if (combo->getValue().asString().empty())
+	{
+		combo->selectFirstItem();
+	}
 }
 
 LLPanelLogin::~LLPanelLogin()
@@ -442,24 +524,6 @@ void LLPanelLogin::giveFocus()
 	}
 }
 
-// static
-void LLPanelLogin::showLoginWidgets()
-{
-	if (sInstance)
-	{
-		// *NOTE: Mani - This may or may not be obselete code.
-		// It seems to be part of the defunct? reg-in-client project.
-		sInstance->getChildView("login_widgets")->setVisible( true);
-		LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
-
-		// *TODO: Append all the usual login parameters, like first_login=Y etc.
-		std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage();
-		web_browser->navigateTo( splash_screen_url, "text/html" );
-		LLUICtrl* username_combo = sInstance->getChild<LLUICtrl>("username_combo");
-		username_combo->setFocus(TRUE);
-	}
-}
-
 // static
 void LLPanelLogin::show(const LLRect &rect,
 						void (*callback)(S32 option, void* user_data),
@@ -480,9 +544,55 @@ void LLPanelLogin::show(const LLRect &rect,
 	gFocusMgr.setDefaultKeyboardFocus(sInstance);
 }
 
+//static
+void LLPanelLogin::populateFields(LLPointer<LLCredential> credential, bool remember_user, bool remember_psswrd)
+{
+    if (!sInstance)
+    {
+        LL_WARNS() << "Attempted fillFields with no login view shown" << LL_ENDL;
+        return;
+    }
+    LLUICtrl* remember_check = sInstance->getChild<LLUICtrl>("remember_check");
+    remember_check->setValue(remember_psswrd);
+    if (sInstance->mFirstLoginThisInstall)
+    {
+        // no list to populate
+        setFields(credential, remember_psswrd);
+    }
+    else
+    {
+        sInstance->getChild<LLUICtrl>("remember_name")->setValue(remember_user);
+        sInstance->populateUserList(credential, remember_psswrd);
+        remember_check->setEnabled(remember_user);
+    }
+}
+
+//static
+void LLPanelLogin::resetFields()
+{
+    if (!sInstance)
+    {
+        // class not existing at this point might happen since this
+        // function is used to reset list in case of changes by external sources
+        return;
+    }
+    if (sInstance->mFirstLoginThisInstall)
+    {
+        // no list to populate
+        LL_WARNS() << "Shouldn't happen, user should have no ability to modify list on first install" << LL_ENDL;
+    }
+    else
+    {
+        LLUICtrl* remember_check = sInstance->getChild<LLUICtrl>("remember_check");
+        bool remember_psswrd = remember_check->getValue();
+        LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+        sInstance->populateUserList(cred, remember_psswrd);
+    }
+}
+
 // static
 void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
-							 BOOL remember)
+							 bool remember_psswrd)
 {
 	if (!sInstance)
 	{
@@ -492,13 +602,15 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
 	sCredentialSet = TRUE;
 	LL_INFOS("Credentials") << "Setting login fields to " << *credential << LL_ENDL;
 
-	LLSD identifier = credential->getIdentifier();
-	if((std::string)identifier["type"] == "agent") 
+	LLSD identifier = credential.notNull() ? credential->getIdentifier() : LLSD();
+
+	if(identifier.has("type") && (std::string)identifier["type"] == "agent") 
 	{
+		// not nessesary for panel_login.xml, needed for panel_login_first.xml
 		std::string firstname = identifier["first_name"].asString();
 		std::string lastname = identifier["last_name"].asString();
 	    std::string login_id = firstname;
-	    if (!lastname.empty() && lastname != "Resident")
+	    if (!lastname.empty() && lastname != "Resident" && lastname != "resident")
 	    {
 		    // support traditional First Last name SLURLs
 		    login_id += " ";
@@ -506,22 +618,23 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
 	    }
 		sInstance->getChild<LLComboBox>("username_combo")->setLabel(login_id);	
 	}
-	else if((std::string)identifier["type"] == "account")
+	else if(identifier.has("type") && (std::string)identifier["type"] == "account")
 	{
 		sInstance->getChild<LLComboBox>("username_combo")->setLabel((std::string)identifier["account_name"]);		
 	}
 	else
 	{
-	  sInstance->getChild<LLComboBox>("username_combo")->setLabel(std::string());	
+		sInstance->getChild<LLComboBox>("username_combo")->setLabel(std::string());	
 	}
+
 	sInstance->addFavoritesToStartLocation();
 	// if the password exists in the credential, set the password field with
 	// a filler to get some stars
-	LLSD authenticator = credential->getAuthenticator();
+	LLSD authenticator = credential.notNull() ? credential->getAuthenticator() : LLSD();
 	LL_INFOS("Credentials") << "Setting authenticator field " << authenticator["type"].asString() << LL_ENDL;
 	if(authenticator.isMap() && 
 	   authenticator.has("secret") && 
-	   (authenticator["secret"].asString().size() > 0) && remember)
+	   (authenticator["secret"].asString().size() > 0) && remember_psswrd)
 	{
 		
 		// This is a MD5 hex digest of a password.
@@ -537,36 +650,25 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
 	{
 		sInstance->getChild<LLUICtrl>("password_edit")->setValue(std::string());		
 	}
-	sInstance->getChild<LLUICtrl>("remember_check")->setValue(remember);
 }
 
-
 // static
 void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
-							 BOOL& remember)
+							 bool& remember_user,
+							 bool& remember_psswrd)
 {
 	if (!sInstance)
 	{
 		LL_WARNS() << "Attempted getFields with no login view shown" << LL_ENDL;
 		return;
 	}
-	
-	// load the credential so we can pass back the stored password or hash if the user did
-	// not modify the password field.
-	
-	credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
 
 	LLSD identifier = LLSD::emptyMap();
 	LLSD authenticator = LLSD::emptyMap();
-	
-	if(credential.notNull())
-	{
-		authenticator = credential->getAuthenticator();
-	}
 
-	std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
-	LLStringUtil::trim(username);
+	std::string username = sInstance->getChild<LLComboBox>("username_combo")->getValue().asString();
 	std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
+	LLStringUtil::trim(username);
 
 	LL_INFOS("Credentials", "Authentication") << "retrieving username:" << username << LL_ENDL;
 	// determine if the username is a first/last form or not.
@@ -586,6 +688,14 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
 			authenticator["type"] = CRED_AUTHENTICATOR_TYPE_CLEAR;
 			authenticator["secret"] = password;
 		}
+        else
+        {
+            credential = load_user_credentials(username);
+            if (credential.notNull())
+            {
+                authenticator = credential->getAuthenticator();
+            }
+        }
 	}
 	else
 	{
@@ -597,7 +707,7 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
 		if (separator_index != username.npos)
 		{
 			last = username.substr(separator_index+1, username.npos);
-		LLStringUtil::trim(last);
+			LLStringUtil::trim(last);
 		}
 		else
 		{
@@ -625,10 +735,28 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
 				pass.hex_digest(md5pass);
 				authenticator["secret"] = md5pass;
 			}
+            else
+            {
+                std::string key = first + "_" + last;
+                LLStringUtil::toLower(key);
+                credential = load_user_credentials(key);
+                if (credential.notNull())
+                {
+                    authenticator = credential->getAuthenticator();
+                }
+            }
 		}
 	}
 	credential = gSecAPIHandler->createCredential(LLGridManager::getInstance()->getGrid(), identifier, authenticator);
-	remember = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+	remember_psswrd = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+    if (!sInstance->mFirstLoginThisInstall)
+    {
+        remember_user = sInstance->getChild<LLUICtrl>("remember_name")->getValue();
+    }
+    else
+    {
+        remember_user = true;
+    }
 }
 
 
@@ -898,8 +1026,8 @@ void LLPanelLogin::onClickConnect(void *)
 		{
 			sCredentialSet = FALSE;
 			LLPointer<LLCredential> cred;
-			BOOL remember;
-			getFields(cred, remember);
+			bool remember_1, remember_2;
+			getFields(cred, remember_1, remember_2);
 			std::string identifier_type;
 			cred->identifierType(identifier_type);
 			LLSD allowed_credential_types;
@@ -952,6 +1080,57 @@ void LLPanelLogin::onClickSignUp(void*)
 	}
 }
 
+// static
+void LLPanelLogin::onUserNameTextEnty(void*)
+{
+    sInstance->mPasswordModified = true;
+    sInstance->getChild<LLUICtrl>("password_edit")->setValue(std::string());
+    sInstance->addFavoritesToStartLocation(); //will call updateLoginButtons()
+}
+
+// static
+void LLPanelLogin::onUserListCommit(void*)
+{
+    if (sInstance)
+    {
+        LLComboBox* username_combo(sInstance->getChild<LLComboBox>("username_combo"));
+        static S32 ind = -1;
+        if (ind != username_combo->getCurrentIndex())
+        {
+            std::string user_key = username_combo->getSelectedValue();
+            LLPointer<LLCredential> cred = gSecAPIHandler->loadFromCredentialMap("login_list", LLGridManager::getInstance()->getGrid(), user_key);
+            bool remember_psswrd = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+            setFields(cred, remember_psswrd);
+            sInstance->mPasswordModified = false;
+        }
+        else
+        {
+           std::string pass = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
+           if (pass.empty())
+           {
+               sInstance->giveFocus();
+           }
+           else
+           {
+               onClickConnect(NULL);
+           }
+        }
+    }
+}
+
+// static
+void LLPanelLogin::onRememberUserCheck(void*)
+{
+    if (sInstance)
+    {
+        LLCheckBoxCtrl* remember_name(sInstance->getChild<LLCheckBoxCtrl>("remember_name"));
+        LLCheckBoxCtrl* remember_psswrd(sInstance->getChild<LLCheckBoxCtrl>("remember_check"));
+
+        bool remember = remember_name->getValue().asBoolean();
+        remember_psswrd->setEnabled(remember);
+    }
+}
+
 // static
 void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data)
 {
@@ -979,9 +1158,11 @@ void LLPanelLogin::updateServer()
 			// for that grid and set them to the UI.
 			if(!sInstance->areCredentialFieldsDirty())
 			{
-				LLPointer<LLCredential> credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());	
-				bool remember = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
-				sInstance->setFields(credential, remember);
+				// populate dropbox and setFields
+				bool remember_psswrd = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+				// Note: following call is related to initializeLoginInfo()
+				LLPointer<LLCredential> credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+				sInstance->populateUserList(credential, remember_psswrd);
 			}
 
 			// update the login panel links 
@@ -1011,14 +1192,63 @@ void LLPanelLogin::updateLoginButtons()
 	LLButton* login_btn = getChild<LLButton>("connect_btn");
 
 	login_btn->setEnabled(mUsernameLength != 0 && mPasswordLength != 0);
+
+    if (!mFirstLoginThisInstall)
+    {
+        LLComboBox* user_combo = getChild<LLComboBox>("username_combo");
+        LLCheckBoxCtrl* remember_name = getChild<LLCheckBoxCtrl>("remember_name");
+        remember_name->setEnabled(user_combo->getCurrentIndex() == -1);
+    }
+}
+
+void LLPanelLogin::populateUserList(LLPointer<LLCredential> credential, bool remember_psswrd)
+{
+    LLComboBox* user_combo = getChild<LLComboBox>("username_combo");
+    user_combo->removeall();
+    user_combo->clear();
+
+    if (gSecAPIHandler->hasCredentialMap("login_list", LLGridManager::getInstance()->getGrid()))
+    {
+        LLSecAPIHandler::credential_map_t credencials;
+        gSecAPIHandler->loadCredentialMap("login_list", LLGridManager::getInstance()->getGrid(), credencials);
+
+        LLSecAPIHandler::credential_map_t::iterator cr_iter = credencials.begin();
+        LLSecAPIHandler::credential_map_t::iterator cr_end = credencials.end();
+        while (cr_iter != cr_end)
+        {
+            if (cr_iter->second.notNull()) // basic safety in case of future changes
+            {
+                // cr_iter->first == user_id , to be able to be find it in case we select it
+                user_combo->add(LLPanelLogin::getUserName(cr_iter->second), cr_iter->first, ADD_BOTTOM, TRUE);
+            }
+            cr_iter++;
+        }
+
+        if (credential.isNull() || !user_combo->setSelectedByValue(LLSD(credential->userID()), true))
+        {
+            // selection failed, just deselect whatever might be selected
+            user_combo->setValue(std::string());
+        }
+        else
+        {
+            setFields(credential, remember_psswrd);
+        }
+    }
+    else
+    {
+        if (credential.notNull())
+        {
+            user_combo->add(LLPanelLogin::getUserName(credential), credential->userID(), ADD_BOTTOM, TRUE);
+            setFields(credential, remember_psswrd);
+        }
+    }
 }
 
+
 void LLPanelLogin::onSelectServer()
 {
 	// The user twiddled with the grid choice ui.
 	// apply the selection to the grid setting.
-	LLPointer<LLCredential> credential;
-
 	LLComboBox* server_combo = getChild<LLComboBox>("server_combo");
 	LLSD server_combo_val = server_combo->getSelectedValue();
 	LL_INFOS("AppInit") << "grid "<<server_combo_val.asString()<< LL_ENDL;
@@ -1048,13 +1278,13 @@ void LLPanelLogin::onSelectServer()
 		{
 			std::string location = location_combo->getValue().asString();
 			LLSLURL slurl(location); // generata a slurl from the location combo contents
-			if (   slurl.getType() == LLSLURL::LOCATION
-				&& slurl.getGrid() != LLGridManager::getInstance()->getGrid()
-				)
+			if (location.empty()
+				|| (slurl.getType() == LLSLURL::LOCATION
+				    && slurl.getGrid() != LLGridManager::getInstance()->getGrid())
+				   )
 			{
 				// the grid specified by the location is not this one, so clear the combo
 				location_combo->setCurrentByIndex(0); // last location on the new grid
-				location_combo->setTextEntry(LLStringUtil::null);
 			}
 		}			
 		break;
@@ -1077,3 +1307,34 @@ bool LLPanelLogin::getShowFavorites()
 {
 	return gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin");
 }
+
+// static
+std::string LLPanelLogin::getUserName(LLPointer<LLCredential> &cred)
+{
+    if (cred.isNull())
+    {
+        return "unknown";
+    }
+    const LLSD &ident = cred->getIdentifier();
+
+    if (!ident.isMap())
+    {
+        return "unknown";
+    }
+    else if ((std::string)ident["type"] == "agent")
+    {
+        std::string second_name = ident["last_name"];
+        if (second_name == "resident" || second_name == "Resident")
+        {
+            return (std::string)ident["first_name"];
+        }
+        return (std::string)ident["first_name"] + " " + (std::string)ident["last_name"];
+    }
+    else if ((std::string)ident["type"] == "account")
+    {
+        return LLCacheName::cleanFullName((std::string)ident["account_name"]);
+    }
+
+    return "unknown";
+}
+
diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
index c633582d89886ea55e669e942d65222079a85fbd..3eb7b68949f1ed9b3d6a37c9d3454971231185b3 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -55,9 +55,9 @@ class LLPanelLogin:
 		void (*callback)(S32 option, void* user_data), 
 		void* callback_data);
 
-	static void setFields(LLPointer<LLCredential> credential, BOOL remember);
-  
-	static void getFields(LLPointer<LLCredential>& credential, BOOL& remember);
+	static void populateFields(LLPointer<LLCredential> credential, bool remember_user, bool remember_psswrd);
+	static void resetFields();
+	static void getFields(LLPointer<LLCredential>& credential, bool& remember_user, bool& remember_psswrd);
 
 	static BOOL isCredentialSet() { return sCredentialSet; }
 
@@ -72,8 +72,6 @@ class LLPanelLogin:
 
 	void setSiteIsAlive( bool alive );
 
-	void showLoginWidgets();
-
 	static void loadLoginPage();	
 	static void giveFocus();
 	static void setAlwaysRefresh(bool refresh); 
@@ -88,6 +86,9 @@ class LLPanelLogin:
 	// called from prefs when initializing panel
 	static bool getShowFavorites();
 
+	// extract name from cred in a format apropriate for username field
+	static std::string getUserName(LLPointer<LLCredential> &cred);
+
 private:
 	friend class LLPanelLoginListener;
 	void addFavoritesToStartLocation();
@@ -95,11 +96,16 @@ class LLPanelLogin:
 	void onSelectServer();
 	void onLocationSLURL();
 
+	static void setFields(LLPointer<LLCredential> credential, bool remember_psswrd);
+
 	static void onClickConnect(void*);
 	static void onClickNewAccount(void*);
 	static void onClickVersion(void*);
 	static void onClickForgotPassword(void*);
 	static void onClickSignUp(void*);
+	static void onUserNameTextEnty(void*);
+	static void onUserListCommit(void*);
+	static void onRememberUserCheck(void*);
 	static void onPassKey(LLLineEditor* caller, void* user_data);
 	static void updateServerCombo();
 
@@ -107,6 +113,7 @@ class LLPanelLogin:
 	boost::scoped_ptr<LLPanelLoginListener> mListener;
 
 	void updateLoginButtons();
+	void populateUserList(LLPointer<LLCredential> credential, bool remember_psswrd);
 
 	void			(*mCallback)(S32 option, void *userdata);
 	void*			mCallbackData;
diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp
index 2dca55514d2b39f3ed28dc6464a3ce478e7c4e25..b654e928e2effb2ae4cd04f0c10a71d648bab450 100644
--- a/indra/newview/llpanelnearbymedia.cpp
+++ b/indra/newview/llpanelnearbymedia.cpp
@@ -43,6 +43,7 @@
 #include "llbutton.h"
 #include "lltextbox.h"
 #include "llviewermedia.h"
+#include "llviewerparcelaskplay.h"
 #include "llviewerparcelmedia.h"
 #include "llviewerregion.h"
 #include "llviewermediafocus.h"
@@ -83,10 +84,11 @@ LLPanelNearByMedia::LLPanelNearByMedia()
 {
 	mHoverTimer.stop();
 
-	mParcelAudioAutoStart = gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
-							gSavedSettings.getBOOL("MediaTentativeAutoPlay");
+    // This is just an initial value, mParcelAudioAutoStart does not affect ParcelMediaAutoPlayEnable
+    mParcelAudioAutoStart = gSavedSettings.getS32("ParcelMediaAutoPlayEnable") != 0
+                            && gSavedSettings.getBOOL("MediaTentativeAutoPlay");
 
-	gSavedSettings.getControl(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING)->getSignal()->connect(boost::bind(&LLPanelNearByMedia::handleMediaAutoPlayChanged, this, _2));
+    gSavedSettings.getControl("ParcelMediaAutoPlayEnable")->getSignal()->connect(boost::bind(&LLPanelNearByMedia::handleMediaAutoPlayChanged, this, _2));
 
 	mCommitCallbackRegistrar.add("MediaListCtrl.EnableAll",		boost::bind(&LLPanelNearByMedia::onClickEnableAll, this));
 	mCommitCallbackRegistrar.add("MediaListCtrl.DisableAll",		boost::bind(&LLPanelNearByMedia::onClickDisableAll, this));
@@ -177,9 +179,18 @@ BOOL LLPanelNearByMedia::postBuild()
 
 void LLPanelNearByMedia::handleMediaAutoPlayChanged(const LLSD& newvalue)
 {
-	// update mParcelAudioAutoStart if AUTO_PLAY_MEDIA_SETTING changes
-	mParcelAudioAutoStart = gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
-							gSavedSettings.getBOOL("MediaTentativeAutoPlay");
+	// update mParcelAudioAutoStartMode if "ParcelMediaAutoPlayEnable" changes
+    S32 value = gSavedSettings.getS32("ParcelMediaAutoPlayEnable");
+    mParcelAudioAutoStart = value != 0
+                            && gSavedSettings.getBOOL("MediaTentativeAutoPlay");
+
+    LLViewerParcelAskPlay *inst = LLViewerParcelAskPlay::getInstance();
+    if (value == 2 && !inst->hasData())
+    {
+        // Init if nessesary
+        inst->loadSettings();
+    }
+    inst->cancelNotification();
 }
 
 /*virtual*/
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 961e2599472ff47caf1c00aef286dbc41f916319..2ef82d0cf907c0702a9370e51eb03498e07a1f99 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -675,6 +675,12 @@ void LLPanelPlaces::onShowOnMapButtonClicked()
 		}
 		else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
 		{
+			if (mItem.isNull())
+			{
+				LL_WARNS() << "NULL landmark item" << LL_ENDL;
+				llassert(mItem.notNull());
+				return;
+			}
 			LLLandmark* landmark = gLandmarkList.getAsset(mItem->getAssetUUID());
 			if (!landmark)
 				return;
diff --git a/indra/newview/llpanelpresetspulldown.cpp b/indra/newview/llpanelpresetspulldown.cpp
index 9b4dc5474a08e644ed0121935862e91ebb848958..0ca4a83779d41eb974853f9ae98475828cad52df 100644
--- a/indra/newview/llpanelpresetspulldown.cpp
+++ b/indra/newview/llpanelpresetspulldown.cpp
@@ -33,8 +33,8 @@
 
 #include "llbutton.h"
 #include "lltabcontainer.h"
+#include "llfloater.h"
 #include "llfloaterreg.h"
-#include "llfloaterpreference.h"
 #include "llpresetsmanager.h"
 #include "llsliderctrl.h"
 #include "llscrolllistctrl.h"
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 8105beae1b971cf4c81c19dae7142c1d1b3e5571..3c74aed734ccdd7864fa7dc55387b99e48a2d382 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -547,17 +547,17 @@ void LLPanelPrimMediaControls::updateShape()
 			switch (mScrollState) 
 			{
 				case SCROLL_UP:
-					media_impl->scrollWheel(0, -1, MASK_NONE);
+					media_impl->scrollWheel(0, 0, 0, -1, MASK_NONE);
 					break;
 				case SCROLL_DOWN:
-					media_impl->scrollWheel(0, 1, MASK_NONE);
+					media_impl->scrollWheel(0, 0, 0, 1, MASK_NONE);
 					break;
 				case SCROLL_LEFT:
-					media_impl->scrollWheel(1, 0, MASK_NONE);
+					media_impl->scrollWheel(0, 0, 1, 0, MASK_NONE);
 					//				media_impl->handleKeyHere(KEY_LEFT, MASK_NONE);
 					break;
 				case SCROLL_RIGHT:
-					media_impl->scrollWheel(-1, 0, MASK_NONE);
+					media_impl->scrollWheel(0, 0, -1, 0, MASK_NONE);
 					//				media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
 					break;
 				case SCROLL_NONE:
@@ -1134,7 +1134,7 @@ void LLPanelPrimMediaControls::onScrollUp(void* user_data)
 	
 	if(impl)
 	{
-		impl->scrollWheel(0, -1, MASK_NONE);
+		impl->scrollWheel(0, 0, 0, -1, MASK_NONE);
 	}
 }
 void LLPanelPrimMediaControls::onScrollUpHeld(void* user_data)
@@ -1151,7 +1151,7 @@ void LLPanelPrimMediaControls::onScrollRight(void* user_data)
 
 	if(impl)
 	{
-		impl->scrollWheel(-1, 0, MASK_NONE);
+		impl->scrollWheel(0, 0, -1, 0, MASK_NONE);
 //		impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
 	}
 }
@@ -1170,7 +1170,7 @@ void LLPanelPrimMediaControls::onScrollLeft(void* user_data)
 
 	if(impl)
 	{
-		impl->scrollWheel(1, 0, MASK_NONE);
+		impl->scrollWheel(0, 0, 1, 0, MASK_NONE);
 //		impl->handleKeyHere(KEY_LEFT, MASK_NONE);
 	}
 }
@@ -1189,7 +1189,7 @@ void LLPanelPrimMediaControls::onScrollDown(void* user_data)
 	
 	if(impl)
 	{
-		impl->scrollWheel(0, 1, MASK_NONE);
+		impl->scrollWheel(0, 0, 0, 1, MASK_NONE);
 	}
 }
 void LLPanelPrimMediaControls::onScrollDownHeld(void* user_data)
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 735eaa423dc6a5f5ef2bf5fed0eec1d76b37ce8f..58bc0493388ed69123c308e0c34240c5109191d3 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -82,8 +82,11 @@
 
 #include <boost/bind.hpp>
 
-// "Features" Tab
 
+const F32 DEFAULT_GRAVITY_MULTIPLIER = 1.f;
+const F32 DEFAULT_DENSITY = 1000.f;
+
+// "Features" Tab
 BOOL	LLPanelVolume::postBuild()
 {
 	// Flexible Objects Parameters
@@ -830,7 +833,7 @@ void LLPanelVolume::onLightSelectTexture(const LLSD& data)
 // static
 void LLPanelVolume::onCommitMaterial( LLUICtrl* ctrl, void* userdata )
 {
-	//LLPanelObject* self = (LLPanelObject*) userdata;
+	LLPanelVolume* self = (LLPanelVolume*)userdata;
 	LLComboBox* box = (LLComboBox*) ctrl;
 
 	if (box)
@@ -841,6 +844,19 @@ void LLPanelVolume::onCommitMaterial( LLUICtrl* ctrl, void* userdata )
 		if (material_name != LEGACY_FULLBRIGHT_DESC)
 		{
 			U8 material_code = LLMaterialTable::basic.getMCode(material_name);
+			if (self)
+			{
+				LLViewerObject* objectp = self->mObject;
+				if (objectp)
+				{
+					objectp->setPhysicsGravity(DEFAULT_GRAVITY_MULTIPLIER);
+					objectp->setPhysicsFriction(LLMaterialTable::basic.getFriction(material_code));
+					//currently density is always set to 1000 serverside regardless of chosen material,
+					//actual material density should be used here, if this behavior change
+					objectp->setPhysicsDensity(DEFAULT_DENSITY);
+					objectp->setPhysicsRestitution(LLMaterialTable::basic.getRestitution(material_code));
+				}
+			}
 			LLSelectMgr::getInstance()->selectionSetMaterial(material_code);
 		}
 	}
diff --git a/indra/newview/llpanelvolumepulldown.cpp b/indra/newview/llpanelvolumepulldown.cpp
index 6792137350bd01292537f6c33238a3a74830ad2d..f063d8427283b670a1f732f8691b9947e3040de3 100644
--- a/indra/newview/llpanelvolumepulldown.cpp
+++ b/indra/newview/llpanelvolumepulldown.cpp
@@ -140,7 +140,7 @@ void LLPanelVolumePulldown::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl)
 		bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->get();
 		bool media_enabled = getChild<LLCheckBoxCtrl>("enable_media")->get();
 
-		getChild<LLCheckBoxCtrl>("media_auto_play_btn")->setEnabled(music_enabled || media_enabled);
+		getChild<LLCheckBoxCtrl>("media_auto_play_combo")->setEnabled(music_enabled || media_enabled);
 	}
 }
 
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 1533a2746952765787b5130195ce7b5467f7f691..2f534ac2456eb9690c6892d9dde30ab652e9d895 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -367,6 +367,7 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs,
 			previewEditor->makePristine();
 			BOOL modifiable = preview->canModify(preview->mObjectID, preview->getItem());
 			preview->setEnabled(modifiable);
+			preview->syncExternal();
 			preview->mAssetStatus = PREVIEW_ASSET_LOADED;
 		}
 		else
@@ -503,10 +504,6 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem, bool sync)
 		}
 
 		editor->makePristine();
-		if (sync)
-		{
-			syncExternal();
-		}
 		const LLInventoryItem* item = getItem();
 		// save it out to database
         if (item)
@@ -755,6 +752,7 @@ void LLPreviewNotecard::openInExternalEditor()
 
     // Start watching file changes.
     mLiveFile = new LLLiveLSLFile(filename, boost::bind(&LLPreviewNotecard::onExternalChange, this, _1));
+    mLiveFile->ignoreNextUpdate();
     mLiveFile->addToEventTimer();
 
     // Open it in external editor.
diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h
index 1b4295ddad9509bec5e03f0e332981db889bd8ad..18b669ff4fc81be07d5f47d1a1c78dee5aeae1e5 100644
--- a/indra/newview/llrecentpeople.h
+++ b/indra/newview/llrecentpeople.h
@@ -53,7 +53,7 @@ class LLRecentPeople: public LLSingleton<LLRecentPeople>, public LLOldEvents::LL
 	LLSINGLETON_EMPTY_CTOR(LLRecentPeople);
 	LOG_CLASS(LLRecentPeople);
 public:
-	typedef std::map <LLUUID, F32> id_to_time_map_t;
+	typedef std::map <LLUUID, F64> id_to_time_map_t;
 	typedef boost::signals2::signal<void ()> signal_t;
 	
 	/**
diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp
index 72d7cf1e4522eebcf56bfb455976d79dd7abc000..10e510b8428a777587476c42062ef26004bb58e8 100644
--- a/indra/newview/llsecapi.cpp
+++ b/indra/newview/llsecapi.cpp
@@ -64,7 +64,7 @@ void initializeSecHandler()
 		{
 			handler->init();
 		}
-		catch (LLProtectedDataException e)
+		catch (LLProtectedDataException& e)
 		{
 			exception_msg = e.what();
 		}
diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h
index d207f3b5b78a5d072696eb58197eb8d7928c3cea..c0f0a367c75a5efd7be869bf177768703391ceb4 100644
--- a/indra/newview/llsecapi.h
+++ b/indra/newview/llsecapi.h
@@ -464,7 +464,19 @@ class LLSecAPIHandler : public LLThreadSafeRefCount
 	// delete a protected data item from the store
 	virtual void deleteProtectedData(const std::string& data_type,
 									 const std::string& data_id)=0;
-	
+
+	// persist data in a protected store's map
+	virtual void addToProtectedMap(const std::string& data_type,
+								   const std::string& data_id,
+								   const std::string& map_elem,
+								   const LLSD& data)=0;
+
+	// remove data from protected store's map
+	virtual void removeFromProtectedMap(const std::string& data_type,
+										const std::string& data_id,
+										const std::string& map_elem)=0;
+
+public:
 	virtual LLPointer<LLCredential> createCredential(const std::string& grid,
 													 const LLSD& identifier, 
 													 const LLSD& authenticator)=0;
@@ -474,6 +486,38 @@ class LLSecAPIHandler : public LLThreadSafeRefCount
 	virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator)=0;
 	
 	virtual void deleteCredential(LLPointer<LLCredential> cred)=0;
+
+	// has map of credentials declared as specific storage
+	virtual bool hasCredentialMap(const std::string& storage,
+								  const std::string& grid)=0;
+
+	// load map of credentials from specific storage
+	typedef std::map<std::string, LLPointer<LLCredential> > credential_map_t;
+	virtual void loadCredentialMap(const std::string& storage,
+								   const std::string& grid,
+								   credential_map_t& credential_map)=0;
+
+	// load single username from map of credentials from specific storage
+	virtual LLPointer<LLCredential> loadFromCredentialMap(const std::string& storage,
+														  const std::string& grid,
+														  const std::string& userid)=0;
+
+	// add item to map of credentials from specific storage
+	virtual void addToCredentialMap(const std::string& storage,
+									LLPointer<LLCredential> cred,
+									bool save_authenticator)=0;
+
+	// remove item from map of credentials from specific storage
+	virtual void removeFromCredentialMap(const std::string& storage,
+										 LLPointer<LLCredential> cred)=0;
+
+	// remove item from map of credentials from specific storage
+	virtual void removeFromCredentialMap(const std::string& storage,
+										 const std::string& grid,
+										 const std::string& userid)=0;
+
+	virtual void removeCredentialMap(const std::string& storage,
+									 const std::string& grid)=0;
 	
 };
 
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index 9ab9e4a1a24b15775d63915375b61533bc904291..a8bb54a90ed0949640506ff5a6709e4178e48fdd 100644
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -52,6 +52,7 @@
 #include "llmachineid.h"
 
 
+static const std::string DEFAULT_CREDENTIAL_STORAGE = "credential";
 
 // 128 bits of salt data...
 #define STORE_SALT_SIZE 16 
@@ -1533,6 +1534,38 @@ void LLSecAPIBasicHandler::setProtectedData(const std::string& data_type,
 	mProtectedDataMap[data_type][data_id] = data; 
 }
 
+// persist data in a protected store's map
+void LLSecAPIBasicHandler::addToProtectedMap(const std::string& data_type,
+											 const std::string& data_id,
+											 const std::string& map_elem,
+											 const LLSD& data)
+{
+    if (!mProtectedDataMap.has(data_type) || !mProtectedDataMap[data_type].isMap()) {
+        mProtectedDataMap[data_type] = LLSD::emptyMap();
+    }
+
+    if (!mProtectedDataMap[data_type].has(data_id) || !mProtectedDataMap[data_type][data_id].isMap()) {
+        mProtectedDataMap[data_type][data_id] = LLSD::emptyMap();
+    }
+
+    mProtectedDataMap[data_type][data_id][map_elem] = data;
+}
+
+// remove data from protected store's map
+void LLSecAPIBasicHandler::removeFromProtectedMap(const std::string& data_type,
+												  const std::string& data_id,
+												  const std::string& map_elem)
+{
+    if (mProtectedDataMap.has(data_type) &&
+        mProtectedDataMap[data_type].isMap() &&
+        mProtectedDataMap[data_type].has(data_id) &&
+        mProtectedDataMap[data_type][data_id].isMap() &&
+        mProtectedDataMap[data_type][data_id].has(map_elem))
+    {
+        mProtectedDataMap[data_type][data_id].erase(map_elem);
+    }
+}
+
 //
 // Create a credential object from an identifier and authenticator.  credentials are
 // per grid.
@@ -1545,10 +1578,10 @@ LLPointer<LLCredential> LLSecAPIBasicHandler::createCredential(const std::string
 	return result;
 }
 
-// Load a credential from the credential store, given the grid
+// Load a credential from default credential store, given the grid
 LLPointer<LLCredential> LLSecAPIBasicHandler::loadCredential(const std::string& grid)
 {
-	LLSD credential = getProtectedData("credential", grid);
+	LLSD credential = getProtectedData(DEFAULT_CREDENTIAL_STORAGE, grid);
 	LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
 	if(credential.isMap() && 
 	   credential.has("identifier"))
@@ -1603,7 +1636,7 @@ void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool sav
 		credential["authenticator"] = cred->getAuthenticator();
 	}
 	LL_DEBUGS("SECAPI") << "Saving Credential " << cred->getGrid() << ":" << cred->userID() << " " << save_authenticator << LL_ENDL;
-	setProtectedData("credential", cred->getGrid(), credential);
+	setProtectedData(DEFAULT_CREDENTIAL_STORAGE, cred->getGrid(), credential);
 	//*TODO: If we're saving Agni credentials, should we write the
 	// credentials to the legacy password.dat/etc?
 	_writeProtectedData();
@@ -1613,11 +1646,137 @@ void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool sav
 void LLSecAPIBasicHandler::deleteCredential(LLPointer<LLCredential> cred)
 {
 	LLSD undefVal;
-	deleteProtectedData("credential", cred->getGrid());
+	deleteProtectedData(DEFAULT_CREDENTIAL_STORAGE, cred->getGrid());
 	cred->setCredentialData(undefVal, undefVal);
 	_writeProtectedData();
 }
 
+// has map of credentials declared as specific storage
+bool LLSecAPIBasicHandler::hasCredentialMap(const std::string& storage, const std::string& grid)
+{
+    if (storage == DEFAULT_CREDENTIAL_STORAGE)
+    {
+        LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+    }
+
+    LLSD credential = getProtectedData(storage, grid);
+
+    return credential.isMap();
+}
+
+// Load map of credentials from specified credential store, given the grid
+void LLSecAPIBasicHandler::loadCredentialMap(const std::string& storage, const std::string& grid, credential_map_t& credential_map)
+{
+    if (storage == DEFAULT_CREDENTIAL_STORAGE)
+    {
+        LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+    }
+
+    LLSD credential = getProtectedData(storage, grid);
+    if (credential.isMap())
+    {
+        LLSD::map_const_iterator crd_it = credential.beginMap();
+        for (; crd_it != credential.endMap(); crd_it++)
+        {
+            LLSD::String name = crd_it->first;
+            const LLSD &link_map = crd_it->second;
+            LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
+            if (link_map.has("identifier"))
+            {
+                LLSD identifier = link_map["identifier"];
+                LLSD authenticator;
+                if (link_map.has("authenticator"))
+                {
+                    authenticator = link_map["authenticator"];
+                }
+                result->setCredentialData(identifier, authenticator);
+            }
+            credential_map[name] = result;
+        }
+    }
+}
+
+LLPointer<LLCredential> LLSecAPIBasicHandler::loadFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userkey)
+{
+    if (storage == DEFAULT_CREDENTIAL_STORAGE)
+    {
+        LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+    }
+
+    LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
+
+    LLSD credential = getProtectedData(storage, grid);
+    if (credential.isMap() && credential.has(userkey) && credential[userkey].has("identifier"))
+    {
+        LLSD identifier = credential[userkey]["identifier"];
+        LLSD authenticator;
+        if (credential[userkey].has("authenticator"))
+        {
+            authenticator = credential[userkey]["authenticator"];
+        }
+        result->setCredentialData(identifier, authenticator);
+    }
+
+    return result;
+}
+
+// add item to map of credentials from specific storage
+void LLSecAPIBasicHandler::addToCredentialMap(const std::string& storage, LLPointer<LLCredential> cred, bool save_authenticator)
+{
+    if (storage == DEFAULT_CREDENTIAL_STORAGE)
+    {
+        LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+    }
+
+    std::string user_id = cred->userID();
+    LLSD credential = LLSD::emptyMap();
+    credential["identifier"] = cred->getIdentifier();
+    if (save_authenticator)
+    {
+        credential["authenticator"] = cred->getAuthenticator();
+    }
+    LL_DEBUGS("SECAPI") << "Saving Credential " << cred->getGrid() << ":" << cred->userID() << " " << save_authenticator << LL_ENDL;
+    addToProtectedMap(storage, cred->getGrid(), user_id, credential);
+
+    _writeProtectedData();
+}
+
+// remove item from map of credentials from specific storage
+void LLSecAPIBasicHandler::removeFromCredentialMap(const std::string& storage, LLPointer<LLCredential> cred)
+{
+    if (storage == DEFAULT_CREDENTIAL_STORAGE)
+    {
+        LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+    }
+
+    LLSD undefVal;
+    removeFromProtectedMap(storage, cred->getGrid(), cred->userID());
+    cred->setCredentialData(undefVal, undefVal);
+    _writeProtectedData();
+}
+
+// remove item from map of credentials from specific storage
+void LLSecAPIBasicHandler::removeFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userkey)
+{
+    if (storage == DEFAULT_CREDENTIAL_STORAGE)
+    {
+        LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+    }
+
+    LLSD undefVal;
+    LLPointer<LLCredential> cred = loadFromCredentialMap(storage, grid, userkey);
+    removeFromProtectedMap(storage, grid, userkey);
+    cred->setCredentialData(undefVal, undefVal);
+    _writeProtectedData();
+}
+
+// remove item from map of credentials from specific storage
+void LLSecAPIBasicHandler::removeCredentialMap(const std::string& storage, const std::string& grid)
+{
+    deleteProtectedData(storage, grid);
+    _writeProtectedData();
+}
+
 // load the legacy hash for agni, and decrypt it given the 
 // mac address
 std::string LLSecAPIBasicHandler::_legacyLoadPassword()
@@ -1656,15 +1815,18 @@ std::string LLSecAPIBasicCredential::userID() const
 	}
 	else if ((std::string)mIdentifier["type"] == "agent")
 	{
-		return  (std::string)mIdentifier["first_name"] + "_" + (std::string)mIdentifier["last_name"];
+		std::string id = (std::string)mIdentifier["first_name"] + "_" + (std::string)mIdentifier["last_name"];
+		LLStringUtil::toLower(id);
+		return id;
 	}
 	else if ((std::string)mIdentifier["type"] == "account")
 	{
-		return (std::string)mIdentifier["account_name"];
+		std::string id = (std::string)mIdentifier["account_name"];
+		LLStringUtil::toLower(id);
+		return id;
 	}
 
 	return "unknown";
-
 }
 
 // return a printable user identifier
diff --git a/indra/newview/llsechandler_basic.h b/indra/newview/llsechandler_basic.h
index c35617f564905983659c33b45db4032b71b37635..426b5d392aeb1f3ecfc23fcd20318afbbb56e1cb 100644
--- a/indra/newview/llsechandler_basic.h
+++ b/indra/newview/llsechandler_basic.h
@@ -211,8 +211,9 @@ class LLSecAPIBasicCredential : public LLCredential
 public:
 	LLSecAPIBasicCredential(const std::string& grid) : LLCredential(grid) {} 
 	virtual ~LLSecAPIBasicCredential() {}
-	// return a value representing the user id, (could be guid, name, whatever)
-	virtual std::string userID() const;	
+	// return a value representing the user id, used for server and voice
+	// (could be guid, name in format "name_resident", whatever)
+	virtual std::string userID() const;
 	
 	// printible string identifying the credential.
 	virtual std::string asString() const;
@@ -246,7 +247,10 @@ class LLSecAPIBasicHandler : public LLSecAPIHandler
 	// exists, it'll be loaded.  If not, one will be created (but not
 	// persisted)
 	virtual LLPointer<LLCertificateStore> getCertificateStore(const std::string& store_id);
-	
+
+	// protectedData functions technically should be pretected or private,
+	// they are not because of llsechandler_basic_test imlementation
+
 	// persist data in a protected store
 	virtual void setProtectedData(const std::string& data_type,
 								  const std::string& data_id,
@@ -259,19 +263,64 @@ class LLSecAPIBasicHandler : public LLSecAPIHandler
 	// delete a protected data item from the store
 	virtual void deleteProtectedData(const std::string& data_type,
 									 const std::string& data_id);
-	
+
+	// persist data in a protected store's map
+	virtual void addToProtectedMap(const std::string& data_type,
+								   const std::string& data_id,
+								   const std::string& map_elem,
+								   const LLSD& data);
+
+	// remove data from protected store's map
+	virtual void removeFromProtectedMap(const std::string& data_type,
+										const std::string& data_id,
+										const std::string& map_elem);
+
 	// credential management routines
 	
 	virtual LLPointer<LLCredential> createCredential(const std::string& grid,
 													 const LLSD& identifier, 
 													 const LLSD& authenticator);
-	
+
+	// load single credencial from default storage
 	virtual LLPointer<LLCredential> loadCredential(const std::string& grid);
 
+	// save credencial to default storage
 	virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator);
 	
 	virtual void deleteCredential(LLPointer<LLCredential> cred);
-	
+
+	// has map of credentials declared as specific storage
+	virtual bool hasCredentialMap(const std::string& storage,
+								  const std::string& grid);
+
+	// load map of credentials from specific storage
+	virtual void loadCredentialMap(const std::string& storage,
+								   const std::string& grid,
+								   credential_map_t& credential_map);
+
+	// load single username from map of credentials from specific storage
+	virtual LLPointer<LLCredential> loadFromCredentialMap(const std::string& storage,
+														  const std::string& grid,
+														  const std::string& userid);
+
+	// add item to map of credentials from specific storage
+	virtual void addToCredentialMap(const std::string& storage,
+									LLPointer<LLCredential> cred,
+									bool save_authenticator);
+
+	// remove item from map of credentials from specific storage
+	virtual void removeFromCredentialMap(const std::string& storage,
+										 LLPointer<LLCredential> cred);
+
+	// remove item from map of credentials from specific storage
+	virtual void removeFromCredentialMap(const std::string& storage,
+										 const std::string& grid,
+										 const std::string& userid);
+
+	virtual void removeCredentialMap(const std::string& storage,
+									 const std::string& grid);
+
+
 protected:
 	void _readProtectedData();
 	void _writeProtectedData();
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 90f8f84ea4c3081e5b994975f2538a4305391e50..f849fecaf6a15332fba06bb1d7da522f2fa6ff0a 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -153,6 +153,53 @@ struct LLDeRezInfo
 // Imports
 //
 
+//-----------------------------------------------------------------------------
+// ~LLSelectionCallbackData()
+//-----------------------------------------------------------------------------
+
+LLSelectionCallbackData::LLSelectionCallbackData()
+{
+    LLSelectMgr *instance = LLSelectMgr::getInstance();
+    LLObjectSelectionHandle selection = instance->getSelection();
+    if (!selection->getNumNodes())
+    {
+        return;
+    }
+    mSelectedObjects = new LLObjectSelection();
+
+    for (LLObjectSelection::iterator iter = selection->begin();
+        iter != selection->end();)
+    {
+        LLObjectSelection::iterator curiter = iter++;
+
+        LLSelectNode *nodep = *curiter;
+        LLViewerObject* objectp = nodep->getObject();
+
+        if (!objectp)
+        {
+            mSelectedObjects->mSelectType = SELECT_TYPE_WORLD;
+        }
+        else
+        {
+            LLSelectNode* new_nodep = new LLSelectNode(*nodep);
+            mSelectedObjects->addNode(new_nodep);
+
+            if (objectp->isHUDAttachment())
+            {
+                mSelectedObjects->mSelectType = SELECT_TYPE_HUD;
+            }
+            else if (objectp->isAttachment())
+            {
+                mSelectedObjects->mSelectType = SELECT_TYPE_ATTACHMENT;
+            }
+            else
+            {
+                mSelectedObjects->mSelectType = SELECT_TYPE_WORLD;
+            }
+        }
+    }
+}
+
 
 //
 // Functions
@@ -4119,20 +4166,20 @@ void LLSelectMgr::packMultipleUpdate(LLSelectNode* node, void *user_data)
 
 	if (type & UPD_POSITION)
 	{
-		htonmemcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12); 
+		htolememcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12); 
 		offset += 12;
 	}
 	if (type & UPD_ROTATION)
 	{
 		LLQuaternion quat = object->getRotation();
 		LLVector3 vec = quat.packToVector3();
-		htonmemcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12); 
+		htolememcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12); 
 		offset += 12;
 	}
 	if (type & UPD_SCALE)
 	{
 		//LL_INFOS() << "Sending object scale " << object->getScale() << LL_ENDL;
-		htonmemcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12); 
+		htolememcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12); 
 		offset += 12;
 	}
 	gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset);
@@ -4475,9 +4522,19 @@ void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info)
 
 void LLSelectMgr::sendAttach(U8 attachment_point, bool replace)
 {
-	LLViewerObject* attach_object = mSelectedObjects->getFirstRootObject();
+    sendAttach(mSelectedObjects, attachment_point, replace);
+}
+
+void LLSelectMgr::sendAttach(LLObjectSelectionHandle selection_handle, U8 attachment_point, bool replace)
+{
+	if (selection_handle.isNull())
+	{
+		return;
+	}
 
-	if (!attach_object || !isAgentAvatarValid() || mSelectedObjects->mSelectType != SELECT_TYPE_WORLD)
+	LLViewerObject* attach_object = selection_handle->getFirstRootObject();
+
+	if (!attach_object || !isAgentAvatarValid() || selection_handle->mSelectType != SELECT_TYPE_WORLD)
 	{
 		return;
 	}
@@ -4495,6 +4552,7 @@ void LLSelectMgr::sendAttach(U8 attachment_point, bool replace)
 		}
 
 		sendListToRegions(
+			selection_handle,
 			"ObjectAttach",
 			packAgentIDAndSessionAndAttachment, 
 			packObjectIDAndRotation, 
@@ -4506,6 +4564,7 @@ void LLSelectMgr::sendAttach(U8 attachment_point, bool replace)
 			// After "ObjectAttach" server will unsubscribe us from properties updates
 			// so either deselect objects or resend selection after attach packet reaches server
 			// In case of build_mode LLPanelObjectInventory::refresh() will deal with selection
+			// Still unsubscribe even in case selection_handle is not current selection
 			deselectAll();
 		}
 	}
@@ -5047,7 +5106,17 @@ void LLSelectMgr::packPermissions(LLSelectNode* node, void *user_data)
 void LLSelectMgr::sendListToRegions(const std::string& message_name,
 									void (*pack_header)(void *user_data), 
 									void (*pack_body)(LLSelectNode* node, void *user_data), 
-                                    void (*log_func)(LLSelectNode* node, void *user_data), 
+									void (*log_func)(LLSelectNode* node, void *user_data), 
+									void *user_data,
+									ESendType send_type)
+{
+    sendListToRegions(mSelectedObjects, message_name, pack_header, pack_body, log_func, user_data, send_type);
+}
+void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,
+									const std::string& message_name,
+									void (*pack_header)(void *user_data), 
+									void (*pack_body)(LLSelectNode* node, void *user_data), 
+									void (*log_func)(LLSelectNode* node, void *user_data), 
 									void *user_data,
 									ESendType send_type)
 {
@@ -5073,7 +5142,7 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
 			return true;
 		}
 	} func;
-	getSelection()->applyToNodes(&func);	
+	selected_handle->applyToNodes(&func);
 
 	std::queue<LLSelectNode*> nodes_to_send;
 
@@ -5116,25 +5185,25 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
 	{
 	  case SEND_ONLY_ROOTS:
 		  if(message_name == "ObjectBuy")
-			getSelection()->applyToRootNodes(&pushroots);
+			selected_handle->applyToRootNodes(&pushroots);
 		  else
-			getSelection()->applyToRootNodes(&pushall);
+			selected_handle->applyToRootNodes(&pushall);
 		  
 		break;
 	  case SEND_INDIVIDUALS:
-		getSelection()->applyToNodes(&pushall);
+		selected_handle->applyToNodes(&pushall);
 		break;
 	  case SEND_ROOTS_FIRST:
 		// first roots...
-		getSelection()->applyToNodes(&pushroots);
+		selected_handle->applyToNodes(&pushroots);
 		// then children...
-		getSelection()->applyToNodes(&pushnonroots);
+		selected_handle->applyToNodes(&pushnonroots);
 		break;
 	  case SEND_CHILDREN_FIRST:
 		// first children...
-		getSelection()->applyToNodes(&pushnonroots);
+		selected_handle->applyToNodes(&pushnonroots);
 		// then roots...
-		getSelection()->applyToNodes(&pushroots);
+		selected_handle->applyToNodes(&pushroots);
 		break;
 
 	default:
@@ -6686,8 +6755,7 @@ void LLSelectMgr::updateSelectionCenter()
 		if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && isAgentAvatarValid())
 		{
 			// reset hud ZOOM
-			gAgentCamera.mHUDTargetZoom = 1.f;
-			gAgentCamera.mHUDCurZoom = 1.f;
+			resetAgentHUDZoom();
 		}
 
 		mShowSelection = FALSE;
@@ -7060,8 +7128,11 @@ BOOL LLSelectMgr::setForceSelection(BOOL force)
 
 void LLSelectMgr::resetAgentHUDZoom()
 {
-	gAgentCamera.mHUDTargetZoom = 1.f;
-	gAgentCamera.mHUDCurZoom = 1.f;
+	if (gAgentCamera.mHUDTargetZoom != 1)
+	{
+		gAgentCamera.mHUDTargetZoom = 1.f;
+		gAgentCamera.mHUDCurZoom = 1.f;
+	}
 }
 
 void LLSelectMgr::getAgentHUDZoom(F32 &target_zoom, F32 &current_zoom) const
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 3e8bfdb00e597bf0953a493a2ab4c8542a7ce603..3bed484b588a0897fc2180c4d824ac738a787a3e 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -239,6 +239,7 @@ class LLObjectSelection : public LLRefCount
 {
 	friend class LLSelectMgr;
 	friend class LLSafeHandle<LLObjectSelection>;
+	friend class LLSelectionCallbackData;
 
 protected:
 	~LLObjectSelection();
@@ -396,6 +397,16 @@ extern template class LLSelectMgr* LLSingleton<class LLSelectMgr>::getInstance()
 // For use with getFirstTest()
 struct LLSelectGetFirstTest;
 
+// temporary storage, Ex: to attach objects after autopilot
+class LLSelectionCallbackData
+{
+public:
+    LLSelectionCallbackData();
+    LLObjectSelectionHandle	getSelection() { return mSelectedObjects; }
+private:
+    LLObjectSelectionHandle					mSelectedObjects;
+};
+
 class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr>
 {
 	LLSINGLETON(LLSelectMgr);
@@ -740,6 +751,7 @@ class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr>
 	// canceled
 	void sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, const LLSaleInfo sale_info);
 	void sendAttach(U8 attachment_point, bool replace);
+	void sendAttach(LLObjectSelectionHandle selection_handle, U8 attachment_point, bool replace);
 	void sendDetach();
 	void sendDropAttachment();
 	void sendLink();
@@ -787,6 +799,13 @@ class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr>
 							void (*log_func)(LLSelectNode* node, void *user_data), 
 							void *user_data,
 							ESendType send_type);
+	void sendListToRegions(	LLObjectSelectionHandle selected_handle,
+							const std::string& message_name,
+							void (*pack_header)(void *user_data),
+							void (*pack_body)(LLSelectNode* node, void *user_data),
+							void (*log_func)(LLSelectNode* node, void *user_data),
+							void *user_data,
+							ESendType send_type);
 
 
 	static void packAgentID(	void *);
diff --git a/indra/newview/llsetkeybinddialog.cpp b/indra/newview/llsetkeybinddialog.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4eb76c9d89fe8d5cc68fef05f5910d33c4ecd348
--- /dev/null
+++ b/indra/newview/llsetkeybinddialog.cpp
@@ -0,0 +1,346 @@
+/** 
+ * @file llsetkeybinddialog.cpp
+ * @brief LLSetKeyBindDialog class implementation.
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, 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 "llviewerprecompiledheaders.h"
+
+#include "llsetkeybinddialog.h"
+
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "lleventtimer.h"
+#include "llfloaterreg.h"
+#include "llfocusmgr.h"
+#include "llkeyconflict.h"
+#include "llviewercontrol.h"
+
+class LLSetKeyBindDialog::Updater : public LLEventTimer
+{
+public:
+
+    typedef boost::function<void(MASK)> callback_t;
+
+    Updater(callback_t cb, F32 period, MASK mask)
+        :LLEventTimer(period),
+        mMask(mask),
+        mCallback(cb)
+    {
+        mEventTimer.start();
+    }
+
+    virtual ~Updater(){}
+
+protected:
+    BOOL tick()
+    {
+        mCallback(mMask);
+        // Deletes itseft after execution
+        return TRUE;
+    }
+
+private:
+    MASK mMask;
+    callback_t mCallback;
+};
+
+bool LLSetKeyBindDialog::sRecordKeys = false;
+
+LLSetKeyBindDialog::LLSetKeyBindDialog(const LLSD& key)
+    : LLModalDialog(key),
+    pParent(NULL),
+    mKeyFilterMask(DEFAULT_KEY_FILTER),
+    pUpdater(NULL),
+    mContextConeOpacity(0.f),
+    mContextConeInAlpha(0.f),
+    mContextConeOutAlpha(0.f),
+    mContextConeFadeTime(0.f)
+{
+	mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
+	mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
+	mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
+}
+
+LLSetKeyBindDialog::~LLSetKeyBindDialog()
+{
+}
+
+//virtual
+BOOL LLSetKeyBindDialog::postBuild()
+{
+    childSetAction("SetEmpty", onBlank, this);
+    childSetAction("Default", onDefault, this);
+    childSetAction("Cancel", onCancel, this);
+    getChild<LLUICtrl>("Cancel")->setFocus(TRUE);
+
+    pCheckBox = getChild<LLCheckBoxCtrl>("apply_all");
+    pDesription = getChild<LLTextBase>("descritption");
+
+    gFocusMgr.setKeystrokesOnly(TRUE);
+
+    return TRUE;
+}
+
+//virtual
+void LLSetKeyBindDialog::onOpen(const LLSD& data)
+{
+     sRecordKeys = true;
+     LLModalDialog::onOpen(data);
+}
+
+//virtual
+void LLSetKeyBindDialog::onClose(bool app_quiting)
+{
+    sRecordKeys = false;
+    if (pParent)
+    {
+        pParent->onCancelKeyBind();
+        pParent = NULL;
+    }
+    if (pUpdater)
+    {
+        // Doubleclick timer has't fired, delete it
+        delete pUpdater;
+        pUpdater = NULL;
+    }
+    LLModalDialog::onClose(app_quiting);
+}
+
+void LLSetKeyBindDialog::drawFrustum()
+{
+    static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
+    drawConeToOwner(mContextConeOpacity, max_opacity, mFrustumOrigin.get(), mContextConeFadeTime, mContextConeInAlpha, mContextConeOutAlpha);
+}
+
+//virtual
+void LLSetKeyBindDialog::draw()
+{
+    drawFrustum();
+    LLModalDialog::draw();
+}
+
+void LLSetKeyBindDialog::setParent(LLKeyBindResponderInterface* parent, LLView* frustum_origin, U32 key_mask)
+{
+    pParent = parent;
+    mFrustumOrigin = frustum_origin->getHandle();
+    mKeyFilterMask = key_mask;
+
+    std::string input;
+    if ((key_mask & ALLOW_MOUSE) != 0)
+    {
+        input = getString("mouse");
+    }
+    if ((key_mask & ALLOW_KEYS) != 0)
+    {
+        if (!input.empty())
+        {
+            input += ", ";
+        }
+        input += getString("keyboard");
+    }
+    pDesription->setText(getString("basic_description"));
+    pDesription->setTextArg("[INPUT]", input);
+}
+
+// static
+bool LLSetKeyBindDialog::recordKey(KEY key, MASK mask)
+{
+    if (sRecordKeys)
+    {
+        LLSetKeyBindDialog* dialog = LLFloaterReg::getTypedInstance<LLSetKeyBindDialog>("keybind_dialog", LLSD());
+        if (dialog && dialog->getVisible())
+        {
+            return dialog->recordAndHandleKey(key, mask);
+        }
+        else
+        {
+            LL_WARNS() << "Key recording was set despite no open dialog" << LL_ENDL;
+            sRecordKeys = false;
+        }
+    }
+    return false;
+}
+
+bool LLSetKeyBindDialog::recordAndHandleKey(KEY key, MASK mask)
+{
+    if ((key == 'Q' && mask == MASK_CONTROL)
+        || key == KEY_ESCAPE)
+    {
+        sRecordKeys = false;
+        closeFloater();
+        return true;
+    }
+
+    if (key == KEY_DELETE)
+    {
+        setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false);
+        sRecordKeys = false;
+        closeFloater();
+        return false;
+    }
+
+    // forbidden keys
+    if (key == KEY_NONE
+        || key == KEY_RETURN
+        || key == KEY_BACKSPACE)
+    {
+        return false;
+    }
+
+    if ((mKeyFilterMask & ALLOW_MASKS) == 0
+        && (key == KEY_CONTROL || key == KEY_SHIFT || key == KEY_ALT))
+    {
+        // mask by themself are not allowed
+        return false;
+    }
+    else if ((mKeyFilterMask & ALLOW_KEYS) == 0)
+    {
+        // basic keys not allowed
+        return false;
+    }
+    else if ((mKeyFilterMask & ALLOW_MASK_KEYS) == 0 && mask != 0)
+    {
+        // masked keys not allowed
+        return false;
+    }
+
+    if (LLKeyConflictHandler::isReservedByMenu(key, mask))
+    {
+        pDesription->setText(getString("reserved_by_menu"));
+        pDesription->setTextArg("[KEYSTR]", LLKeyboard::stringFromAccelerator(mask,key));
+        return true;
+    }
+
+    setKeyBind(CLICK_NONE, key, mask, pCheckBox->getValue().asBoolean());
+    sRecordKeys = false;
+    closeFloater();
+    return true;
+}
+
+BOOL LLSetKeyBindDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
+{
+    BOOL result = FALSE;
+    if (!pParent)
+    {
+        // we already processed 'down' event, this is 'up', consume
+        closeFloater();
+        result = TRUE;
+    }
+    if (!result && clicktype == CLICK_LEFT)
+    {
+        // try handling buttons first
+        if (down)
+        {
+            result = LLView::handleMouseDown(x, y, mask);
+        }
+        else
+        {
+            result = LLView::handleMouseUp(x, y, mask);
+        }
+        if (result)
+        {
+            setFocus(TRUE);
+            gFocusMgr.setKeystrokesOnly(TRUE);
+        }
+        // ignore selection related combinations
+        else if (down && (mask & (MASK_SHIFT | MASK_CONTROL)) == 0)
+        {
+            // this can be a double click, wait a bit;
+            if (!pUpdater)
+            {
+                // Note: default doubleclick time is 500ms, but can stretch up to 5s
+                pUpdater = new Updater(boost::bind(&onClickTimeout, this, _1), 0.7f, mask);
+                result = TRUE;
+            }
+        }
+    }
+
+    if (!result
+        && (clicktype != CLICK_LEFT) // subcases were handled above
+        && ((mKeyFilterMask & ALLOW_MOUSE) != 0)
+        && (clicktype != CLICK_RIGHT || mask != 0) // reassigning menu button is not supported
+        && ((mKeyFilterMask & ALLOW_MASK_MOUSE) != 0 || mask == 0)) // reserved for selection
+    {
+        setKeyBind(clicktype, KEY_NONE, mask, pCheckBox->getValue().asBoolean());
+        result = TRUE;
+        if (!down)
+        {
+            // wait for 'up' event before closing
+            // alternative: set pUpdater
+            closeFloater();
+        }
+    }
+
+    return result;
+}
+
+//static
+void LLSetKeyBindDialog::onCancel(void* user_data)
+{
+    LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
+    self->closeFloater();
+}
+
+//static
+void LLSetKeyBindDialog::onBlank(void* user_data)
+{
+    LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
+    // tmp needs 'no key' button
+    self->setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false);
+    self->closeFloater();
+}
+
+//static
+void LLSetKeyBindDialog::onDefault(void* user_data)
+{
+    LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
+    if (self->pParent)
+    {
+        self->pParent->onDefaultKeyBind(self->pCheckBox->getValue().asBoolean());
+        self->pParent = NULL;
+    }
+    self->closeFloater();
+}
+
+//static
+void LLSetKeyBindDialog::onClickTimeout(void* user_data, MASK mask)
+{
+    LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
+
+    // timer will delete itself after timeout
+    self->pUpdater = NULL;
+
+    self->setKeyBind(CLICK_LEFT, KEY_NONE, mask, self->pCheckBox->getValue().asBoolean());
+    self->closeFloater();
+}
+
+void LLSetKeyBindDialog::setKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes)
+{
+    if (pParent)
+    {
+        pParent->onSetKeyBind(click, key, mask, all_modes);
+        pParent = NULL;
+    }
+}
+
diff --git a/indra/newview/llsetkeybinddialog.h b/indra/newview/llsetkeybinddialog.h
new file mode 100644
index 0000000000000000000000000000000000000000..70190230e4d025ac15ea28f1b1794a4ee74a327b
--- /dev/null
+++ b/indra/newview/llsetkeybinddialog.h
@@ -0,0 +1,105 @@
+/** 
+ * @file llsetkeybinddialog.h
+ * @brief LLSetKeyBindDialog class definition
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, 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$
+ */
+
+
+#ifndef LL_LLSETKEYBINDDIALOG_H
+#define LL_LLSETKEYBINDDIALOG_H
+
+#include "llmodaldialog.h"
+
+class LLCheckBoxCtrl;
+class LLTextBase;
+
+// Filters for LLSetKeyBindDialog
+static const U32 ALLOW_MOUSE = 1;
+static const U32 ALLOW_MASK_MOUSE = 2;
+static const U32 ALLOW_KEYS = 4; //keyboard
+static const U32 ALLOW_MASK_KEYS = 8;
+static const U32 ALLOW_MASKS = 16;
+static const U32 DEFAULT_KEY_FILTER = ALLOW_MOUSE | ALLOW_MASK_MOUSE | ALLOW_KEYS | ALLOW_MASK_KEYS;
+
+
+class LLKeyBindResponderInterface
+{
+public:
+    virtual ~LLKeyBindResponderInterface() {};
+
+    virtual void onCancelKeyBind() = 0;
+    virtual void onDefaultKeyBind(bool all_modes) = 0;
+    // returns true if parent failed to set key due to key being in use
+    virtual bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes) = 0;
+};
+
+class LLSetKeyBindDialog : public LLModalDialog
+{
+public:
+    LLSetKeyBindDialog(const LLSD& key);
+    ~LLSetKeyBindDialog();
+
+    /*virtual*/ BOOL postBuild();
+    /*virtual*/ void onOpen(const LLSD& data);
+    /*virtual*/ void onClose(bool app_quiting);
+    /*virtual*/ void draw();
+
+    void setParent(LLKeyBindResponderInterface* parent, LLView* frustum_origin, U32 key_mask = DEFAULT_KEY_FILTER);
+
+    // Wrapper around recordAndHandleKey
+    // It does not record, it handles, but handleKey function is already in use
+    static bool recordKey(KEY key, MASK mask);
+
+    BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
+    static void onCancel(void* user_data);
+    static void onBlank(void* user_data);
+    static void onDefault(void* user_data);
+    static void onClickTimeout(void* user_data, MASK mask);
+
+    class Updater;
+
+private:
+    bool recordAndHandleKey(KEY key, MASK mask);
+    void setKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes);
+    LLKeyBindResponderInterface *pParent;
+    LLCheckBoxCtrl *pCheckBox;
+    LLTextBase *pDesription;
+
+    U32 mKeyFilterMask;
+    Updater *pUpdater;
+
+    static bool sRecordKeys; // for convinience and not to check instance each time
+
+    // drawFrustum
+private:
+    void drawFrustum();
+
+    LLHandle <LLView>   mFrustumOrigin;
+    F32                 mContextConeOpacity;
+    F32                 mContextConeInAlpha;
+    F32                 mContextConeOutAlpha;
+    F32                 mContextConeFadeTime;
+};
+
+
+#endif  // LL_LLSETKEYBINDDIALOG_H
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index 2503e2a5e299d45d964dd5752b682577853b6ffd..d508621b41ff29e23bc6aaaf973e29416b4f556f 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -49,6 +49,29 @@
 #include "llviewerregion.h"
 
 
+class PropertiesChangedCallback : public LLInventoryCallback
+{
+public:
+    PropertiesChangedCallback(LLHandle<LLPanel> sidepanel_handle, LLUUID &item_id, S32 id)
+        : mHandle(sidepanel_handle), mItemId(item_id), mId(id)
+    {}
+
+    void fire(const LLUUID &inv_item)
+    {
+        // inv_item can be null for some reason
+        LLSidepanelItemInfo* sidepanel = dynamic_cast<LLSidepanelItemInfo*>(mHandle.get());
+        if (sidepanel)
+        {
+            // sidepanel waits only for most recent update
+            sidepanel->onUpdateCallback(mItemId, mId);
+        }
+    }
+private:
+    LLHandle<LLPanel> mHandle;
+    LLUUID mItemId;
+    S32 mId;
+};
+
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLItemPropertiesObserver
 //
@@ -68,7 +91,7 @@ class LLItemPropertiesObserver : public LLInventoryObserver
 	}
 	virtual void changed(U32 mask);
 private:
-	LLSidepanelItemInfo* mFloater;
+	LLSidepanelItemInfo* mFloater; // Not a handle because LLSidepanelItemInfo is managing LLItemPropertiesObserver
 };
 
 void LLItemPropertiesObserver::changed(U32 mask)
@@ -115,7 +138,7 @@ class LLObjectInventoryObserver : public LLVOInventoryListener
 									  S32 serial_num,
 									  void* user_data);
 private:
-	LLSidepanelItemInfo* mFloater;
+	LLSidepanelItemInfo* mFloater;  // Not a handle because LLSidepanelItemInfo is managing LLObjectInventoryObserver
 };
 
 /*virtual*/
@@ -138,6 +161,7 @@ LLSidepanelItemInfo::LLSidepanelItemInfo(const LLPanel::Params& p)
 	: LLSidepanelInventorySubpanel(p)
 	, mItemID(LLUUID::null)
 	, mObjectInventoryObserver(NULL)
+	, mUpdatePendingId(-1)
 {
 	mPropertiesObserver = new LLItemPropertiesObserver(this);
 }
@@ -168,19 +192,19 @@ BOOL LLSidepanelItemInfo::postBuild()
 	// owner permissions
 	// Permissions debug text
 	// group permissions
-	getChild<LLUICtrl>("CheckShareWithGroup")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
+	getChild<LLUICtrl>("CheckShareWithGroup")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
 	// everyone permissions
-	getChild<LLUICtrl>("CheckEveryoneCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
+	getChild<LLUICtrl>("CheckEveryoneCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
 	// next owner permissions
-	getChild<LLUICtrl>("CheckNextOwnerModify")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
-	getChild<LLUICtrl>("CheckNextOwnerCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
-	getChild<LLUICtrl>("CheckNextOwnerTransfer")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
+	getChild<LLUICtrl>("CheckNextOwnerModify")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
+	getChild<LLUICtrl>("CheckNextOwnerCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
+	getChild<LLUICtrl>("CheckNextOwnerTransfer")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
 	// Mark for sale or not, and sale info
-	getChild<LLUICtrl>("CheckPurchase")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
+	getChild<LLUICtrl>("CheckPurchase")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this, _1));
 	// Change sale type, and sale info
-	getChild<LLUICtrl>("ComboBoxSaleType")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
+	getChild<LLUICtrl>("ComboBoxSaleType")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this, _1));
 	// "Price" label for edit
-	getChild<LLUICtrl>("Edit Cost")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
+	getChild<LLUICtrl>("Edit Cost")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this, _1));
 	refresh();
 	return TRUE;
 }
@@ -192,11 +216,16 @@ void LLSidepanelItemInfo::setObjectID(const LLUUID& object_id)
 	// Start monitoring changes in the object inventory to update
 	// selected inventory item properties in Item Profile panel. See STORM-148.
 	startObjectInventoryObserver();
+	mUpdatePendingId = -1;
 }
 
 void LLSidepanelItemInfo::setItemID(const LLUUID& item_id)
 {
-	mItemID = item_id;
+    if (mItemID != item_id)
+    {
+        mItemID = item_id;
+        mUpdatePendingId = -1;
+    }
 }
 
 const LLUUID& LLSidepanelItemInfo::getObjectID() const
@@ -209,6 +238,15 @@ const LLUUID& LLSidepanelItemInfo::getItemID() const
 	return mItemID;
 }
 
+void LLSidepanelItemInfo::onUpdateCallback(const LLUUID& item_id, S32 received_update_id)
+{
+    if (mItemID == item_id && mUpdatePendingId == received_update_id)
+    {
+        mUpdatePendingId = -1;
+        refresh();
+    }
+}
+
 void LLSidepanelItemInfo::reset()
 {
 	LLSidepanelInventorySubpanel::reset();
@@ -242,24 +280,16 @@ void LLSidepanelItemInfo::refresh()
 			"LabelItemName",
 			"LabelItemDesc",
 			"LabelCreatorName",
-			"LabelOwnerName",
-			"CheckOwnerModify",
-			"CheckOwnerCopy",
-			"CheckOwnerTransfer",
-			"CheckShareWithGroup",
-			"CheckEveryoneCopy",
-			"CheckNextOwnerModify",
-			"CheckNextOwnerCopy",
-			"CheckNextOwnerTransfer",
-			"CheckPurchase",
-			"Edit Cost"
+			"LabelOwnerName"
 		};
 
 		for(size_t t=0; t<LL_ARRAY_SIZE(no_item_names); ++t)
 		{
 			getChildView(no_item_names[t])->setEnabled(false);
 		}
-		
+
+		setPropertiesFieldsEnabled(false);
+
 		const std::string hide_names[]={
 			"BaseMaskDebug",
 			"OwnerMaskDebug",
@@ -297,6 +327,11 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
 	llassert(item);
 	if (!item) return;
 
+    if (mUpdatePendingId != -1)
+    {
+        return;
+    }
+
 	// do not enable the UI for incomplete items.
 	BOOL is_complete = item->isFinished();
 	const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(item->getInventoryType());
@@ -726,6 +761,26 @@ void LLSidepanelItemInfo::stopObjectInventoryObserver()
 	mObjectInventoryObserver = NULL;
 }
 
+void LLSidepanelItemInfo::setPropertiesFieldsEnabled(bool enabled)
+{
+    const std::string fields[] = {
+        "CheckOwnerModify",
+        "CheckOwnerCopy",
+        "CheckOwnerTransfer",
+        "CheckShareWithGroup",
+        "CheckEveryoneCopy",
+        "CheckNextOwnerModify",
+        "CheckNextOwnerCopy",
+        "CheckNextOwnerTransfer",
+        "CheckPurchase",
+        "Edit Cost"
+    };
+    for (size_t t = 0; t<LL_ARRAY_SIZE(fields); ++t)
+    {
+        getChildView(fields[t])->setEnabled(false);
+    }
+}
+
 void LLSidepanelItemInfo::onClickCreator()
 {
 	LLViewerInventoryItem* item = findItem();
@@ -793,10 +848,18 @@ void LLSidepanelItemInfo::onCommitDescription()
 	}
 }
 
-// static
-void LLSidepanelItemInfo::onCommitPermissions()
+void LLSidepanelItemInfo::onCommitPermissions(LLUICtrl* ctrl)
+{
+    if (ctrl)
+    {
+        // will be enabled by response from server
+        ctrl->setEnabled(false);
+    }
+    updatePermissions();
+}
+
+void LLSidepanelItemInfo::updatePermissions()
 {
-	//LL_INFOS() << "LLSidepanelItemInfo::onCommitPermissions()" << LL_ENDL;
 	LLViewerInventoryItem* item = findItem();
 	if(!item) return;
 
@@ -884,19 +947,17 @@ void LLSidepanelItemInfo::onCommitPermissions()
 }
 
 // static
-void LLSidepanelItemInfo::onCommitSaleInfo()
+void LLSidepanelItemInfo::onCommitSaleInfo(LLUICtrl* ctrl)
 {
+    if (ctrl)
+    {
+        // will be enabled by response from server
+        ctrl->setEnabled(false);
+    }
 	//LL_INFOS() << "LLSidepanelItemInfo::onCommitSaleInfo()" << LL_ENDL;
 	updateSaleInfo();
 }
 
-// static
-void LLSidepanelItemInfo::onCommitSaleType()
-{
-	//LL_INFOS() << "LLSidepanelItemInfo::onCommitSaleType()" << LL_ENDL;
-	updateSaleInfo();
-}
-
 void LLSidepanelItemInfo::updateSaleInfo()
 {
 	LLViewerInventoryItem* item = findItem();
@@ -977,7 +1038,12 @@ void LLSidepanelItemInfo::onCommitChanges(LLPointer<LLViewerInventoryItem> item)
     if (mObjectID.isNull())
     {
         // This is in the agent's inventory.
-        item->updateServer(FALSE);
+        // Mark update as pending and wait only for most recent one in case user requested for couple
+        // Once update arrives or any of ids change drop pending id.
+        mUpdatePendingId++;
+        LLPointer<LLInventoryCallback> callback = new PropertiesChangedCallback(getHandle(), mItemID, mUpdatePendingId);
+        update_inventory_item(item.get(), callback);
+        //item->updateServer(FALSE);
         gInventory.updateItem(item);
         gInventory.notifyObservers();
     }
@@ -1002,6 +1068,7 @@ void LLSidepanelItemInfo::onCommitChanges(LLPointer<LLViewerInventoryItem> item)
                 // prevents flashing in content tab and some duplicated request.
                 object->dirtyInventory();
             }
+            setPropertiesFieldsEnabled(false);
         }
     }
 }
@@ -1030,7 +1097,6 @@ void LLSidepanelItemInfo::save()
 {
 	onCommitName();
 	onCommitDescription();
-	onCommitPermissions();
-	onCommitSaleInfo();
-	onCommitSaleType();
+	updatePermissions();
+	updateSaleInfo();
 }
diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h
index 74cf7afe3530707e6c3fc9d5ad0b7dbfacac168f..5f29254182f9dfd5934f8efc232e1494494ae187 100644
--- a/indra/newview/llsidepaneliteminfo.h
+++ b/indra/newview/llsidepaneliteminfo.h
@@ -57,6 +57,9 @@ class LLSidepanelItemInfo : public LLSidepanelInventorySubpanel
 	const LLUUID& getObjectID() const;
 	const LLUUID& getItemID() const;
 
+	// if received update and item id (from callback) matches internal ones, update UI
+	void onUpdateCallback(const LLUUID& item_id, S32 received_update_id);
+
 protected:
 	/*virtual*/ void refresh();
 	/*virtual*/ void save();
@@ -71,12 +74,16 @@ class LLSidepanelItemInfo : public LLSidepanelInventorySubpanel
 
 	void startObjectInventoryObserver();
 	void stopObjectInventoryObserver();
+	void setPropertiesFieldsEnabled(bool enabled);
 
 	LLUUID mItemID; 	// inventory UUID for the inventory item.
 	LLUUID mObjectID; 	// in-world task UUID, or null if in agent inventory.
 	LLItemPropertiesObserver* mPropertiesObserver; // for syncing changes to item
 	LLObjectInventoryObserver* mObjectInventoryObserver; // for syncing changes to items inside an object
-	
+
+	// We can send multiple properties updates simultaneously, make sure only last response counts and there won't be a race condition.
+	S32 mUpdatePendingId;
+
 	//
 	// UI Elements
 	// 
@@ -85,9 +92,9 @@ class LLSidepanelItemInfo : public LLSidepanelInventorySubpanel
 	void 						onClickOwner();
 	void 						onCommitName();
 	void 						onCommitDescription();
-	void 						onCommitPermissions();
-	void 						onCommitSaleInfo();
-	void 						onCommitSaleType();
+	void 						onCommitPermissions(LLUICtrl* ctrl);
+	void 						updatePermissions();
+	void 						onCommitSaleInfo(LLUICtrl* ctrl);
 	void 						updateSaleInfo();
 	void 						onCommitChanges(LLPointer<LLViewerInventoryItem> item);
 };
diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp
index f03c7abc4d193bbf1d82df09f5b5836355c8b556..7fa06f51e30e51d5a84e23e6cb26d189390c2fcb 100644
--- a/indra/newview/llsidepaneltaskinfo.cpp
+++ b/indra/newview/llsidepaneltaskinfo.cpp
@@ -174,9 +174,6 @@ BOOL LLSidepanelTaskInfo::postBuild()
 
 void LLSidepanelTaskInfo::disableAll()
 {
-	mDAPermModify->setEnabled(FALSE);
-	mDAPermModify->setValue(LLStringUtil::null);
-
 	mDACreatorName->setValue(LLStringUtil::null);
 	mDACreatorName->setEnabled(FALSE);
 
@@ -184,18 +181,42 @@ void LLSidepanelTaskInfo::disableAll()
 	mDAOwnerName->setValue(LLStringUtil::null);
 	mDAOwnerName->setEnabled(FALSE);
 
-	mDAButtonSetGroup->setEnabled(FALSE);
-
 	mDAObjectName->setValue(LLStringUtil::null);
 	mDAObjectName->setEnabled(FALSE);
 	mDAName->setEnabled(FALSE);
 	mDADescription->setEnabled(FALSE);
 	mDAObjectDescription->setValue(LLStringUtil::null);
 	mDAObjectDescription->setEnabled(FALSE);
-		
+
+	mDAPathfindingAttributes->setEnabled(FALSE);
+	mDAPathfindingAttributes->setValue(LLStringUtil::null);
+
+	mDAButtonSetGroup->setEnabled(FALSE);
+	mDAButtonDeed->setEnabled(FALSE);
+
+	mDAPermModify->setEnabled(FALSE);
+	mDAPermModify->setValue(LLStringUtil::null);
+	mDAEditCost->setValue(LLStringUtil::null);
+	mDAComboSaleType->setValue(LLSaleInfo::FS_COPY);
+
+	disablePermissions();
+
+	mDAB->setVisible(FALSE);
+	mDAO->setVisible(FALSE);
+	mDAG->setVisible(FALSE);
+	mDAE->setVisible(FALSE);
+	mDAN->setVisible(FALSE);
+	mDAF->setVisible(FALSE);
+
+	mOpenBtn->setEnabled(FALSE);
+	mPayBtn->setEnabled(FALSE);
+	mBuyBtn->setEnabled(FALSE);
+}
+
+void LLSidepanelTaskInfo::disablePermissions()
+{
 	mDACheckboxShareWithGroup->setValue(FALSE);
 	mDACheckboxShareWithGroup->setEnabled(FALSE);
-	mDAButtonDeed->setEnabled(FALSE);
 
 	mDACheckboxAllowEveryoneMove->setValue(FALSE);
 	mDACheckboxAllowEveryoneMove->setEnabled(FALSE);
@@ -217,33 +238,17 @@ void LLSidepanelTaskInfo::disableAll()
 	//checkbox include in search
 	mDASearchCheck->setValue(FALSE);
 	mDASearchCheck->setEnabled(FALSE);
-		
-	mDAComboSaleType->setValue(LLSaleInfo::FS_COPY);
+
 	mDAComboSaleType->setEnabled(FALSE);
-	
-	mDAEditCost->setValue(LLStringUtil::null);
+
 	mDAEditCost->setEnabled(FALSE);
-		
+
 	mDALabelClickAction->setEnabled(FALSE);
 	if (mDAComboClickAction)
 	{
 		mDAComboClickAction->setEnabled(FALSE);
 		mDAComboClickAction->clear();
 	}
-
-	mDAPathfindingAttributes->setEnabled(FALSE);
-	mDAPathfindingAttributes->setValue(LLStringUtil::null);
-
-	mDAB->setVisible(FALSE);
-	mDAO->setVisible(FALSE);
-	mDAG->setVisible(FALSE);
-	mDAE->setVisible(FALSE);
-	mDAN->setVisible(FALSE);
-	mDAF->setVisible(FALSE);
-	
-	mOpenBtn->setEnabled(FALSE);
-	mPayBtn->setEnabled(FALSE);
-	mBuyBtn->setEnabled(FALSE);
 }
 
 void LLSidepanelTaskInfo::refresh()
@@ -972,6 +977,12 @@ void LLSidepanelTaskInfo::onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32
 	BOOL new_state = check->get();
 	
 	LLSelectMgr::getInstance()->selectionSetObjectPermissions(field, new_state, perm);
+
+    LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data;
+    if (self)
+    {
+        self->disablePermissions();
+    }
 }
 
 // static
diff --git a/indra/newview/llsidepaneltaskinfo.h b/indra/newview/llsidepaneltaskinfo.h
index cbfb07874bc28c1e04fe9500a38e6f0796de5a8d..dc259cb22df6d1ff7aba41588c22e16b491364c9 100644
--- a/indra/newview/llsidepaneltaskinfo.h
+++ b/indra/newview/llsidepaneltaskinfo.h
@@ -95,6 +95,7 @@ class LLSidepanelTaskInfo : public LLSidepanelInventorySubpanel
 
 	static void	doClickAction(U8 click_action);
 	void disableAll();
+	void disablePermissions();
 
 private:
 	LLNameBox*		mLabelGroupName;		// group name
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index f5fea9decef5f9593eee9eef255b1064fe60f40c..43dc676a6352da8a466fa5b7ab6f6345d99be13d 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -65,6 +65,7 @@ F32 SHINE_WIDTH = 0.6f;
 F32 SHINE_OPACITY = 0.3f;
 F32 FALL_TIME = 0.6f;
 S32 BORDER_WIDTH = 6;
+S32 TOP_PANEL_HEIGHT = 30;
 
 const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
 
@@ -295,8 +296,8 @@ void LLSnapshotLivePreview::draw()
 		F32 uv_width = isImageScaled() ? 1.f : llmin((F32)getWidth() / (F32)getCurrentImage()->getWidth(), 1.f);
 		F32 uv_height = isImageScaled() ? 1.f : llmin((F32)getHeight() / (F32)getCurrentImage()->getHeight(), 1.f);
 		gGL.pushMatrix();
-		{
-			gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f);
+		{	
+			gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom + TOP_PANEL_HEIGHT, 0.f);
 			gGL.begin(LLRender::QUADS);
 			{
 				gGL.texCoord2f(uv_width, uv_height);
@@ -348,14 +349,15 @@ void LLSnapshotLivePreview::draw()
 			F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);
 
 			// draw "shine" effect
-			LLLocalClipRect clip(getLocalRect());
+			LLRect local_rect(0, getRect().getHeight() + TOP_PANEL_HEIGHT, getRect().getWidth(), 0);
+			LLLocalClipRect clip(local_rect);
 			{
 				// draw diagonal stripe with gradient that passes over screen
 				S32 x1 = gViewerWindow->getWindowWidthScaled() * ll_round((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f)));
 				S32 x2 = x1 + ll_round(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
 				S32 x3 = x2 + ll_round(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
 				S32 y1 = 0;
-				S32 y2 = gViewerWindow->getWindowHeightScaled();
+				S32 y2 = gViewerWindow->getWindowHeightScaled() + TOP_PANEL_HEIGHT;
 
 				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 				gGL.begin(LLRender::QUADS);
@@ -385,36 +387,6 @@ void LLSnapshotLivePreview::draw()
 		}
 	}
 
-	// draw framing rectangle
-	{
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		gGL.color4f(1.f, 1.f, 1.f, 1.f);
-		const LLRect& outline_rect = getImageRect();
-		gGL.begin(LLRender::QUADS);
-		{
-			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
-			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
-
-			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
-			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
-			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
-
-			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
-			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
-			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
-
-			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
-			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
-			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
-		}
-		gGL.end();
-	}
-
 	// draw old image dropping away
 	if (mFallAnimTimer.getStarted())
 	{
@@ -588,6 +560,7 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
         if(!gViewerWindow->thumbnailSnapshot(raw,
                                          mThumbnailWidth, mThumbnailHeight,
                                          mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"),
+                                         gSavedSettings.getBOOL("RenderHUDInSnapshot"),
                                          FALSE,
                                          mSnapshotBufferType) )
         {
@@ -746,6 +719,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
                 previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
                 previewp->getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE,
                 previewp->mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"),
+                gSavedSettings.getBOOL("RenderHUDInSnapshot"),
                 FALSE,
                 previewp->mSnapshotBufferType,
                 previewp->getMaxImageSize()))
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 1dc1e65fe5a253d4d13e63065ed828d82fe48c69..7e6f3ef7bc83148c36b1cad724b27bf92ccb0510 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -996,7 +996,7 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
 	}	
 	
 	LLSpatialGroup* group = drawablep->getSpatialGroup();
-	llassert(group != NULL);
+	//llassert(group != NULL);
 
 	if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING))
 	{
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index c8c39ae00f57d6c464ed1a176a35a37a391e6c8b..008dfe2a4508c4ec7f91e66ee9b763f9f8ce2356 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -106,7 +106,6 @@
 //#include "llfirstuse.h"
 #include "llfloaterhud.h"
 #include "llfloaterland.h"
-#include "llfloaterpreference.h"
 #include "llfloatertopobjects.h"
 #include "llfloaterworldmap.h"
 #include "llgesturemgr.h"
@@ -158,6 +157,7 @@
 #include "llviewermessage.h"
 #include "llviewernetwork.h"
 #include "llviewerobjectlist.h"
+#include "llviewerparcelaskplay.h"
 #include "llviewerparcelmedia.h"
 #include "llviewerparcelmgr.h"
 #include "llviewerregion.h"
@@ -236,7 +236,8 @@ LLSLURL LLStartUp::sStartSLURL;
 
 static LLPointer<LLCredential> gUserCredential;
 static std::string gDisplayName;
-static BOOL gRememberPassword = TRUE;     
+static bool gRememberPassword = true;
+static bool gRememberUser = true;
 
 static U64 gFirstSimHandle = 0;
 static LLHost gFirstSim;
@@ -350,13 +351,6 @@ bool idle_startup()
 	gIdleCallbacks.callFunctions();
 	gViewerWindow->updateUI();
 
-	// There is a crash on updateClass, this is an attempt to get more information
-	if (LLMortician::graveyardCount())
-	{
-		std::stringstream log_stream;
-		LLMortician::logClass(log_stream);
-		LL_INFOS() << log_stream.str() << LL_ENDL;
-	}
 	LLMortician::updateClass();
 
 	const std::string delims (" ");
@@ -701,19 +695,23 @@ bool idle_startup()
 		else if (gSavedSettings.getBOOL("AutoLogin"))  
 		{
 			// Log into last account
-			gRememberPassword = TRUE;
-			gSavedSettings.setBOOL("RememberPassword", TRUE);                                                      
+			gRememberPassword = true;
+			gRememberUser = true;
+			gSavedSettings.setBOOL("RememberPassword", TRUE);
+			gSavedSettings.setBOOL("RememberUser", TRUE);
 			show_connect_box = false;    			
 		}
 		else if (gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
 		{
 			// Console provided login&password
 			gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
+			gRememberUser = gSavedSettings.getBOOL("RememberUser");
 			show_connect_box = false;
 		}
 		else 
 		{
 			gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
+			gRememberUser = gSavedSettings.getBOOL("RememberUser");
 			show_connect_box = TRUE;
 		}
 
@@ -781,10 +779,7 @@ bool idle_startup()
 			// Show the login dialog
 			login_show();
 			// connect dialog is already shown, so fill in the names
-			if (gUserCredential.notNull() && !LLPanelLogin::isCredentialSet())
-			{
-				LLPanelLogin::setFields( gUserCredential, gRememberPassword);
-			}
+			LLPanelLogin::populateFields( gUserCredential, gRememberUser, gRememberPassword);
 			LLPanelLogin::giveFocus();
 
 			// MAINT-3231 Show first run dialog only for Desura viewer
@@ -873,7 +868,7 @@ bool idle_startup()
 		{
 			// TODO if not use viewer auth
 			// Load all the name information out of the login view
-			LLPanelLogin::getFields(gUserCredential, gRememberPassword); 
+			LLPanelLogin::getFields(gUserCredential, gRememberUser, gRememberPassword);
 			// end TODO
 	 
 			// HACK: Try to make not jump on login
@@ -885,14 +880,21 @@ bool idle_startup()
 		// STATE_LOGIN_SHOW state if we've gone backwards
 		mLoginStatePastUI = true;
 
-		// save the credentials                                                                                        
-		std::string userid = "unknown";                                                                                
-		if(gUserCredential.notNull())                                                                                  
-		{  
-			userid = gUserCredential->userID();                                                                    
-			gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword);  
-		}
-		gSavedSettings.setBOOL("RememberPassword", gRememberPassword);                                                 
+		// save the credentials
+		std::string userid = "unknown";
+        if (gUserCredential.notNull())
+        {
+            userid = gUserCredential->userID();
+            if (gRememberUser)
+            {
+                gSecAPIHandler->addToCredentialMap("login_list", gUserCredential, gRememberPassword);
+                // Legacy viewers use this method to store user credentials, newer viewers
+                // reuse it to be compatible and to remember last session
+                gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword);
+            }
+        }
+		gSavedSettings.setBOOL("RememberPassword", gRememberPassword);
+		gSavedSettings.setBOOL("RememberUser", gRememberUser);
 		LL_INFOS("AppInit") << "Attempting login as: " << userid << LL_ENDL;                                           
 		gDebugInfo["LoginName"] = userid;                                                                              
          
@@ -1423,6 +1425,10 @@ bool idle_startup()
 		// create a container's instance for start a controlling conversation windows
 		// by the voice's events
 		LLFloaterIMContainer::getInstance();
+		if (gSavedSettings.getS32("ParcelMediaAutoPlayEnable") == 2)
+		{
+			LLViewerParcelAskPlay::getInstance()->loadSettings();
+		}
 
 		// *Note: this is where gWorldMap used to be initialized.
 
@@ -1632,7 +1638,14 @@ bool idle_startup()
 		if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT)
 		{
 			LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
-			LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+			if (gRememberPassword)
+			{
+				LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+			}
+			else
+			{
+				LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status);
+			}
 			reset_login();
 		}
 		return FALSE;
@@ -2367,7 +2380,14 @@ void use_circuit_callback(void**, S32 result)
 		{
 			// Make sure user knows something bad happened. JC
 			LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
-			LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+			if (gRememberPassword)
+			{
+				LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+			}
+			else
+			{
+				LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status);
+			}
 			reset_login();
 		}
 		else
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index 9eda33d3d20f22dac2309ffed79e6b1648deb87b..b8c227334da1ab21818d0fde9477abf3ead9c359 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -243,16 +243,24 @@ BOOL LLStatusBar::postBuild()
 	mPanelNearByMedia->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
 	mPanelNearByMedia->setVisible(FALSE);
 
+	updateBalancePanelPosition();
+
 	// Hook up and init for filtering
 	mFilterEdit = getChild<LLSearchEditor>( "search_menu_edit" );
 	mSearchPanel = getChild<LLPanel>( "menu_search_panel" );
 
-	mSearchPanel->setVisible(gSavedSettings.getBOOL("MenuSearch"));
+	BOOL search_panel_visible = gSavedSettings.getBOOL("MenuSearch");
+	mSearchPanel->setVisible(search_panel_visible);
 	mFilterEdit->setKeystrokeCallback(boost::bind(&LLStatusBar::onUpdateFilterTerm, this));
 	mFilterEdit->setCommitCallback(boost::bind(&LLStatusBar::onUpdateFilterTerm, this));
 	collectSearchableItems();
 	gSavedSettings.getControl("MenuSearch")->getCommitSignal()->connect(boost::bind(&LLStatusBar::updateMenuSearchVisibility, this, _2));
 
+	if (search_panel_visible)
+	{
+		updateMenuSearchPosition();
+	}
+
 	return TRUE;
 }
 
@@ -363,17 +371,7 @@ void LLStatusBar::setBalance(S32 balance)
 	std::string label_str = getString("buycurrencylabel", string_args);
 	mBoxBalance->setValue(label_str);
 
-	// Resize the L$ balance background to be wide enough for your balance plus the buy button
-	{
-		const S32 HPAD = 24;
-		LLRect balance_rect = mBoxBalance->getTextBoundingRect();
-		LLRect buy_rect = getChildView("buyL")->getRect();
-		LLRect shop_rect = getChildView("goShop")->getRect();
-		LLView* balance_bg_view = getChildView("balance_bg");
-		LLRect balance_bg_rect = balance_bg_view->getRect();
-		balance_bg_rect.mLeft = balance_bg_rect.mRight - (buy_rect.getWidth() + shop_rect.getWidth() + balance_rect.getWidth() + HPAD);
-		balance_bg_view->setShape(balance_bg_rect);
-	}
+	updateBalancePanelPosition();
 
 	// If the search panel is shown, move this according to the new balance width. Parcel text will reshape itself in setParcelInfoText
 	if (mSearchPanel && mSearchPanel->getVisible())
@@ -661,6 +659,19 @@ void LLStatusBar::updateMenuSearchPosition()
 	mSearchPanel->setShape( searchRect );
 }
 
+void LLStatusBar::updateBalancePanelPosition()
+{
+    // Resize the L$ balance background to be wide enough for your balance plus the buy button
+    const S32 HPAD = 24;
+    LLRect balance_rect = mBoxBalance->getTextBoundingRect();
+    LLRect buy_rect = getChildView("buyL")->getRect();
+    LLRect shop_rect = getChildView("goShop")->getRect();
+    LLView* balance_bg_view = getChildView("balance_bg");
+    LLRect balance_bg_rect = balance_bg_view->getRect();
+    balance_bg_rect.mLeft = balance_bg_rect.mRight - (buy_rect.getWidth() + shop_rect.getWidth() + balance_rect.getWidth() + HPAD);
+    balance_bg_view->setShape(balance_bg_rect);
+}
+
 
 // Implements secondlife:///app/balance/request to request a L$ balance
 // update via UDP message system. JC
diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h
index 403d590acacd2acef38f27b8281256448dc0ef78..cad877f7991ed7eb42730c0a9b859c8b2e148305 100644
--- a/indra/newview/llstatusbar.h
+++ b/indra/newview/llstatusbar.h
@@ -114,7 +114,8 @@ class LLStatusBar
 	std::unique_ptr< ll::statusbar::SearchData > mSearchData;
 	void collectSearchableItems();
 	void updateMenuSearchVisibility( const LLSD& data );
-	void updateMenuSearchPosition();
+	void updateMenuSearchPosition(); // depends onto balance position
+	void updateBalancePanelPosition();
 
 private:
 	LLTextBox	*mTextTime;
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index e5af47ab6cb69111f161585c53e9700b2bd1bed7..f3bb5741914dc6260a3a520e64832d75c9c03291 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -53,6 +53,7 @@ const F32 TEXTURE_CACHE_PURGE_AMOUNT = .20f; // % amount to reduce the cache by
 const F32 TEXTURE_CACHE_LRU_SIZE = .10f; // % amount for LRU list (low overhead to regenerate)
 const S32 TEXTURE_FAST_CACHE_ENTRY_OVERHEAD = sizeof(S32) * 4; //w, h, c, level
 const S32 TEXTURE_FAST_CACHE_ENTRY_SIZE = 16 * 16 * 4 + TEXTURE_FAST_CACHE_ENTRY_OVERHEAD;
+const F32 TEXTURE_LAZY_PURGE_TIME_LIMIT = .004f; // 4ms. Would be better to autoadjust, but there is a major cache rework in progress.
 
 class LLTextureCacheWorker : public LLWorkerClass
 {
@@ -1669,6 +1670,91 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
 	LL_INFOS() << "The entire texture cache is cleared." << LL_ENDL ;
 }
 
+void LLTextureCache::purgeTexturesLazy(F32 time_limit_sec)
+{
+	if (mReadOnly)
+	{
+		return;
+	}
+
+	if (!mThreaded)
+	{
+		LLAppViewer::instance()->pauseMainloopTimeout();
+	}
+
+	// time_limit doesn't account for lock time
+	LLMutexLock lock(&mHeaderMutex);
+
+	if (mPurgeEntryList.empty())
+	{
+		// Read the entries list and form list of textures to purge
+		std::vector<Entry> entries;
+		U32 num_entries = openAndReadEntries(entries);
+		if (!num_entries)
+		{
+			return; // nothing to purge
+		}
+
+		// Use mTexturesSizeMap to collect UUIDs of textures with bodies
+		typedef std::set<std::pair<U32, S32> > time_idx_set_t;
+		std::set<std::pair<U32, S32> > time_idx_set;
+		for (size_map_t::iterator iter1 = mTexturesSizeMap.begin();
+			iter1 != mTexturesSizeMap.end(); ++iter1)
+		{
+			if (iter1->second > 0)
+			{
+				id_map_t::iterator iter2 = mHeaderIDMap.find(iter1->first);
+				if (iter2 != mHeaderIDMap.end())
+				{
+					S32 idx = iter2->second;
+					time_idx_set.insert(std::make_pair(entries[idx].mTime, idx));
+				}
+				else
+				{
+					LL_ERRS("TextureCache") << "mTexturesSizeMap / mHeaderIDMap corrupted." << LL_ENDL;
+				}
+			}
+		}
+
+		S64 cache_size = mTexturesSizeTotal;
+		S64 purged_cache_size = (sCacheMaxTexturesSize * (S64)((1.f - TEXTURE_CACHE_PURGE_AMOUNT) * 100)) / 100;
+		for (time_idx_set_t::iterator iter = time_idx_set.begin();
+			iter != time_idx_set.end(); ++iter)
+		{
+			S32 idx = iter->second;
+			if (cache_size >= purged_cache_size)
+			{
+				cache_size -= entries[idx].mBodySize;
+				mPurgeEntryList.push_back(std::pair<S32, Entry>(idx, entries[idx]));
+			}
+			else
+			{
+				break;
+			}
+		}
+		LL_DEBUGS("TextureCache") << "Formed Purge list of " << mPurgeEntryList.size() << " entries" << LL_ENDL;
+	}
+	else
+	{
+		// Remove collected entried
+		LLTimer timer;
+		while (!mPurgeEntryList.empty() && timer.getElapsedTimeF32() < time_limit_sec)
+		{
+			S32 idx = mPurgeEntryList.back().first;
+			Entry entry = mPurgeEntryList.back().second;
+			mPurgeEntryList.pop_back();
+			// make sure record is still valid
+			id_map_t::iterator iter_header = mHeaderIDMap.find(entry.mID);
+			if (iter_header != mHeaderIDMap.end() && iter_header->second == idx)
+			{
+				std::string tex_filename = getTextureFileName(entry.mID);
+				removeEntry(idx, entry, tex_filename);
+				writeEntryToHeaderImmediately(idx, entry);
+			}
+		}
+	}
+}
+
 void LLTextureCache::purgeTextures(bool validate)
 {
 	if (mReadOnly)
@@ -1928,11 +2014,10 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio
 	}
 	if (mDoPurge)
 	{
-		// NOTE: This may cause an occasional hiccup,
-		//  but it really needs to be done on the control thread
-		//  (i.e. here)		
-		purgeTextures(false);
-		mDoPurge = FALSE;
+		// NOTE: Needs to be done on the control thread
+		//  (i.e. here)
+		purgeTexturesLazy(TEXTURE_LAZY_PURGE_TIME_LIMIT);
+		mDoPurge = !mPurgeEntryList.empty();
 	}
 	LLMutexLock lock(&mWorkersMutex);
 	LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index 81ea7aeee2d98057c70f25b486bfc45b95af1d5e..da59290930d34f3f7c2cae53eb9ddbd67c359ac7 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -155,6 +155,7 @@ class LLTextureCache : public LLWorkerThread
 	void readHeaderCache();
 	void clearCorruptedCache();
 	void purgeAllTextures(bool purge_directories);
+	void purgeTexturesLazy(F32 time_limit_sec);
 	void purgeTextures(bool validate);
 	LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset);
 	void closeHeaderEntriesFile();
@@ -225,6 +226,8 @@ class LLTextureCache : public LLWorkerThread
 
 	typedef std::map<S32, Entry> idx_entry_map_t;
 	idx_entry_map_t mUpdatedEntryMap;
+	typedef std::vector<std::pair<S32, Entry> > idx_entry_vector_t;
+	idx_entry_vector_t mPurgeEntryList;
 
 	// Statics
 	static F32 sHeaderCacheVersion;
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index e2bb904eff0ffdd003fad4596ee8e94cfde648ec..fd1c5373aed83999dc36ffd12b396fdee47e5163 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -73,9 +73,6 @@
 
 #include "llavatarappearancedefines.h"
 
-static const F32 CONTEXT_CONE_IN_ALPHA = 0.0f;
-static const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
-static const F32 CONTEXT_FADE_TIME = 0.08f;
 
 static const S32 LOCAL_TRACKING_ID_COLUMN = 1;
 
@@ -442,59 +439,8 @@ BOOL LLFloaterTexturePicker::postBuild()
 // virtual
 void LLFloaterTexturePicker::draw()
 {
-	if (mOwner)
-	{
-		// draw cone of context pointing back to texture swatch	
-		LLRect owner_rect;
-		mOwner->localRectToOtherView(mOwner->getLocalRect(), &owner_rect, this);
-		LLRect local_rect = getLocalRect();
-		if (gFocusMgr.childHasKeyboardFocus(this) && mOwner->isInVisibleChain() && mContextConeOpacity > 0.001f)
-		{
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			LLGLEnable(GL_CULL_FACE);
-			gGL.begin(LLRender::QUADS);
-			{
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
-				gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
-				gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
-
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-				gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
-				gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
-
-
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-				gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
-				gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
-			}
-			gGL.end();
-		}
-	}
-
-	if (gFocusMgr.childHasMouseCapture(getDragHandle()))
-	{
-		mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME));
-	}
-	else
-	{
-		mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME));
-	}
+    static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
+    drawConeToOwner(mContextConeOpacity, max_opacity, mOwner);
 
 	updateImageStats();
 
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index 941cb410fcab88f227754ed9eccad010a8659af1..f882fd31ee9439196bde7231e95c39b22b83cfa5 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -34,7 +34,6 @@
 #include "llfontgl.h"
 #include "lltextbox.h"
 #include "llbutton.h"
-#include "llcheckboxctrl.h"
 #include "llkeyboard.h"
 #include "llfocusmgr.h"
 #include "lliconctrl.h"
@@ -62,9 +61,8 @@ static const S32 HPAD = 25;
 static const S32 BTN_HPAD = 8;
 
 LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal)
-	  : LLToastPanel(notification),
+	  : LLCheckBoxToastPanel(notification),
 		mDefaultOption( 0 ),
-		mCheck(NULL),
 		mCaution(notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH),
 		mLabel(notification->getName()),
 		mLineEditor(NULL)
@@ -347,20 +345,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
 		button_left += button_width + BTN_HPAD;
 	}
 
-	std::string ignore_label;
-
-	if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE)
-	{
-		setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label);
-	}
-	if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY)
-	{
-		setCheckBox(LLNotifications::instance().getGlobalString("skipnexttimesessiononly"), ignore_label);
-	}
-	else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
-	{
-		setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label);
-	}
+	setCheckBoxes(HPAD, VPAD);
 
 	// *TODO: check necessity of this code
 	//gFloaterView->adjustToFitScreen(this, FALSE);
@@ -380,46 +365,6 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
 			LLTransientFloaterMgr::GLOBAL, this);
 }
 
-bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std::string& check_control )
-{
-	mCheck = LLUICtrlFactory::getInstance()->createFromFile<LLCheckBoxCtrl>("alert_check_box.xml", this, LLPanel::child_registry_t::instance());
-
-	if(!mCheck)
-	{
-		return false;
-	}
-
-	const LLFontGL* font =  mCheck->getFont();
-	const S32 LINE_HEIGHT = font->getLineHeight();
-
-	std::vector<std::string> lines;
-	boost::split(lines, check_title, boost::is_any_of("\n"));
-	
-	// Extend dialog for "check next time"
-	S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * HPAD;
-	S32 check_width = S32(font->getWidth(lines[0]) + 0.99f) + 16; // use width of the first line
-	max_msg_width = llmax(max_msg_width, check_width);
-	S32 dialog_width = max_msg_width + 2 * HPAD;
-
-	S32 dialog_height = LLToastPanel::getRect().getHeight();
-	dialog_height += LINE_HEIGHT * lines.size();
-	dialog_height += LINE_HEIGHT / 2;
-
-	LLToastPanel::reshape( dialog_width, dialog_height, FALSE );
-
-	S32 msg_x = (LLToastPanel::getRect().getWidth() - max_msg_width) / 2;
-
-	// set check_box's attributes
-	LLRect check_rect;
-	mCheck->setRect(check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, max_msg_width, LINE_HEIGHT*lines.size()));
-	mCheck->setLabel(check_title);
-	mCheck->setCommitCallback(boost::bind(&LLToastAlertPanel::onClickIgnore, this, _1));
-	
-	LLToastPanel::addChild(mCheck);
-
-	return true;
-}
-
 void LLToastAlertPanel::setVisible( BOOL visible )
 {
 	// only make the "ding" sound if it's newly visible
@@ -569,16 +514,3 @@ void LLToastAlertPanel::onButtonPressed( const LLSD& data, S32 button )
 
 	mNotification->respond(response); // new notification reponse
 }
-
-void LLToastAlertPanel::onClickIgnore(LLUICtrl* ctrl)
-{
-	// checkbox sometimes means "hide and do the default" and
-	// other times means "warn me again".  Yuck. JC
-	BOOL check = ctrl->getValue().asBoolean();
-	if (mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
-	{
-		// question was "show again" so invert value to get "ignore"
-		check = !check;
-	}
-	mNotification->setIgnored(check);
-}
diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h
index 15bf11d42c83ecb622b67f7be6932d29bffa935c..9b4e054bf13656618d40d188e50e386bc2e92ffb 100644
--- a/indra/newview/lltoastalertpanel.h
+++ b/indra/newview/lltoastalertpanel.h
@@ -46,7 +46,7 @@ class LLLineEditor;
  */
 
 class LLToastAlertPanel
-	: public LLToastPanel
+	: public LLCheckBoxToastPanel
 {
 	LOG_CLASS(LLToastAlertPanel);
 public:
@@ -61,13 +61,11 @@ class LLToastAlertPanel
 	virtual void	draw();
 	virtual void	setVisible( BOOL visible );
 
-	bool 			setCheckBox( const std::string&, const std::string& );	
 	void			setCaution(BOOL val = TRUE) { mCaution = val; }
 	// If mUnique==TRUE only one copy of this message should exist
 	void			setUnique(BOOL val = TRUE) { mUnique = val; }
 	void			setEditTextArgs(const LLSD& edit_args);
 	
-	void onClickIgnore(LLUICtrl* ctrl);
 	void onButtonPressed(const LLSD& data, S32 button);
 	
 private:
@@ -91,7 +89,6 @@ class LLToastAlertPanel
 	std::vector<ButtonData> mButtonData;
 
 	S32				mDefaultOption;
-	LLCheckBoxCtrl* mCheck;
 	BOOL			mCaution;
 	BOOL			mUnique;
 	LLUIString		mLabel;
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index a2116817a245c69bbb31000b5d5e249773d14339..bccf88128de5e436d1db2de28579ab2d1e54f22a 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -33,6 +33,7 @@
 
 // library includes
 #include "lldbstrings.h"
+#include "llcheckboxctrl.h"
 #include "lllslconstants.h"
 #include "llnotifications.h"
 #include "lluiconstants.h"
@@ -55,7 +56,7 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;
 LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal;
 
 LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) 
-:	LLToastPanel(notification),
+:	LLCheckBoxToastPanel(notification),
 	LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>(notification->getID())
 {
 	init(rect, show_images);
@@ -162,6 +163,11 @@ void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair
 		{
 			left = (max_width - btn_rect.getWidth()) / 2;
 		}
+		else if (left == 0 && buttons.size() == 2)
+		{
+			// Note: this and "size() == 1" shouldn't be inside the cycle, might be good idea to refactor whole placing process
+			left = (max_width - (btn_rect.getWidth() * 2) - h_pad) / 2;
+		}
 		else if (left + btn_rect.getWidth() > max_width)// whether there is still some place for button+h_pad in the mControlPanel
 		{
 			// looks like we need to add button to the next row
@@ -409,7 +415,20 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
 	//.xml file intially makes info panel only follow left/right/top. This is so that when control buttons are added the info panel 
 	//can shift upward making room for the buttons inside mControlPanel. After the buttons are added, the info panel can then be set to follow 'all'.
 	mInfoPanel->setFollowsAll();
-	snapToMessageHeight(mTextBox, LLToastPanel::MAX_TEXT_LENGTH);
+
+    // Add checkbox (one of couple types) if nessesary.
+    setCheckBoxes(HPAD * 2, 0, mInfoPanel);
+    if (mCheck)
+    {
+        mCheck->setFollows(FOLLOWS_BOTTOM | FOLLOWS_LEFT);
+    }
+    // Snap to message, then to checkbox if present
+    snapToMessageHeight(mTextBox, LLToastPanel::MAX_TEXT_LENGTH);
+    if (mCheck)
+    {
+        S32 new_panel_height = mCheck->getRect().getHeight() + getRect().getHeight() + VPAD;
+        reshape(getRect().getWidth(), new_panel_height);
+    }
 
 	// reshape the panel to its previous size
 	if (current_rect.notEmpty())
diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h
index e4a75acfda09ec9cf7294a474b2a8c96af6b4e02..a5a637c6fac9e4de3fa9bb27f159c9b600a28623 100644
--- a/indra/newview/lltoastnotifypanel.h
+++ b/indra/newview/lltoastnotifypanel.h
@@ -47,7 +47,7 @@ class LLNotificationForm;
  * @deprecated this class will be removed after all toast panel types are
  *  implemented in separate classes.
  */
-class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>
+class LLToastNotifyPanel: public LLCheckBoxToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>
 {
 public:
 	/**
diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp
index 7c624d5b50566518267ef5dd91aa9acf78b615e4..100d5ee71359327311d51073058502fc5ad60373 100644
--- a/indra/newview/lltoastpanel.cpp
+++ b/indra/newview/lltoastpanel.cpp
@@ -27,6 +27,7 @@
 #include "llviewerprecompiledheaders.h"
 
 #include "lldbstrings.h"
+#include "llcheckboxctrl.h"
 #include "llpanelgenerictip.h"
 #include "llpanelonlinestatus.h"
 #include "llnotifications.h"
@@ -34,6 +35,8 @@
 #include "lltoastpanel.h"
 #include "lltoastscriptquestion.h"
 
+#include <boost/algorithm/string.hpp>
+
 //static
 const S32 LLToastPanel::MIN_PANEL_HEIGHT = 40; // VPAD(4)*2 + ICON_HEIGHT(32)
 // 'magic numbers', consider initializing (512+20) part from xml/notifications
@@ -145,3 +148,108 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification(
 
 	return res;
 }
+
+LLCheckBoxToastPanel::LLCheckBoxToastPanel(const LLNotificationPtr& p_ntf)
+: LLToastPanel(p_ntf),
+mCheck(NULL)
+{
+
+}
+
+void LLCheckBoxToastPanel::setCheckBoxes(const S32 &h_pad, const S32 &v_pad, LLView *parent_view)
+{
+    std::string ignore_label;
+    LLNotificationFormPtr form = mNotification->getForm();
+
+    if (form->getIgnoreType() == LLNotificationForm::IGNORE_CHECKBOX_ONLY)
+    {
+        // Normally text is only used to describe notification in preferences, 
+        // but this one is not displayed in preferences and works on case by case
+        // basis.
+        // Display text if present, display 'always chose' if not.
+        std::string ignore_message = form->getIgnoreMessage();
+        if (ignore_message.empty())
+        {
+            ignore_message = LLNotifications::instance().getGlobalString("alwayschoose");
+        }
+        setCheckBox(ignore_message, ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+    }
+    else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE)
+    {
+        setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+    }
+    if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY)
+    {
+        setCheckBox(LLNotifications::instance().getGlobalString("skipnexttimesessiononly"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+    }
+    else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
+    {
+        setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+    }
+}
+
+bool LLCheckBoxToastPanel::setCheckBox(const std::string& check_title,
+                                       const std::string& check_control,
+                                       const commit_signal_t::slot_type& cb,
+                                       const S32 &h_pad,
+                                       const S32 &v_pad,
+                                       LLView *parent_view)
+{
+    mCheck = LLUICtrlFactory::getInstance()->createFromFile<LLCheckBoxCtrl>("alert_check_box.xml", this, LLPanel::child_registry_t::instance());
+
+    if (!mCheck)
+    {
+        return false;
+    }
+
+    const LLFontGL* font = mCheck->getFont();
+    const S32 LINE_HEIGHT = font->getLineHeight();
+
+    std::vector<std::string> lines;
+    boost::split(lines, check_title, boost::is_any_of("\n"));
+
+    // Extend dialog for "check next time"
+    S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * h_pad;
+    S32 check_width = S32(font->getWidth(lines[0]) + 0.99f) + 16; // use width of the first line
+    max_msg_width = llmax(max_msg_width, check_width);
+    S32 dialog_width = max_msg_width + 2 * h_pad;
+
+    S32 dialog_height = LLToastPanel::getRect().getHeight();
+    dialog_height += LINE_HEIGHT * lines.size();
+    dialog_height += LINE_HEIGHT / 2;
+
+    LLToastPanel::reshape(dialog_width, dialog_height, FALSE);
+
+    S32 msg_x = (LLToastPanel::getRect().getWidth() - max_msg_width) / 2;
+
+    // set check_box's attributes
+    LLRect check_rect;
+    // if we are part of the toast, we need to leave space for buttons
+    S32 msg_y = v_pad + (parent_view ? 0 : (BTN_HEIGHT + LINE_HEIGHT / 2));
+    mCheck->setRect(check_rect.setOriginAndSize(msg_x, msg_y, max_msg_width, LINE_HEIGHT*lines.size()));
+    mCheck->setLabel(check_title);
+    mCheck->setCommitCallback(cb);
+
+    if (parent_view)
+    {
+        // assume that width and height autoadjusts to toast
+        parent_view->addChild(mCheck);
+    }
+    else
+    {
+        LLToastPanel::addChild(mCheck);
+    }
+
+    return true;
+}
+
+void LLCheckBoxToastPanel::onCommitCheckbox(LLUICtrl* ctrl)
+{
+    BOOL check = ctrl->getValue().asBoolean();
+    if (mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
+    {
+        // question was "show again" so invert value to get "ignore"
+        check = !check;
+    }
+    mNotification->setIgnored(check);
+}
diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h
index 6a9b72a5ae56e915417c784991659d80aaac037e..f4c758ade9ef344c3be4d7155ea30fe22277d329 100644
--- a/indra/newview/lltoastpanel.h
+++ b/indra/newview/lltoastpanel.h
@@ -64,4 +64,23 @@ class LLToastPanel : public LLPanel {
 	S32 computeSnappedToMessageHeight(LLTextBase* message, S32 maxLineCount);
 };
 
+class LLCheckBoxCtrl;
+
+// Wrapper with support for 'don't ask again' checkbox
+class LLCheckBoxToastPanel : public LLToastPanel
+{
+public:
+	LLCheckBoxToastPanel(const LLNotificationPtr& p_ntf);
+	virtual ~LLCheckBoxToastPanel() {};
+
+	// set checkboxes acording to defaults from form
+	void			setCheckBoxes(const S32 &h_pad, const S32 &v_pad, LLView *parent_view = NULL);
+	// set single checkbox
+	bool			setCheckBox(const std::string&, const std::string&, const commit_signal_t::slot_type& cb, const S32 &h_pad, const S32 &v_pad, LLView *parent_view = NULL);
+protected:
+	void onCommitCheckbox(LLUICtrl* ctrl);
+
+	LLCheckBoxCtrl* mCheck;
+};
+
 #endif /* LL_TOASTPANEL_H */
diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp
index b5d78f36548ebeb880dee7a62b8dc6bc249b7ef8..5235914c34884c0392c6d78d135e59cbdf706dfd 100644
--- a/indra/newview/lltool.cpp
+++ b/indra/newview/lltool.cpp
@@ -60,7 +60,7 @@ LLTool::~LLTool()
 	}
 }
 
-BOOL LLTool::handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
+BOOL LLTool::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
 {
 	BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
 	
@@ -83,9 +83,9 @@ BOOL LLTool::handleMouseDown(S32 x, S32 y, MASK mask)
 		LL_INFOS() << "LLTool left mouse down" << LL_ENDL;
 	}
 	// by default, didn't handle it
+	// AGENT_CONTROL_LBUTTON_DOWN is handled by scanMouse() and scanKey()
 	// LL_INFOS() << "LLTool::handleMouseDown" << LL_ENDL;
-	gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
-	return TRUE;
+	return FALSE;
 }
 
 BOOL LLTool::handleMouseUp(S32 x, S32 y, MASK mask)
@@ -95,8 +95,8 @@ BOOL LLTool::handleMouseUp(S32 x, S32 y, MASK mask)
 		LL_INFOS() << "LLTool left mouse up" << LL_ENDL;
 	}
 	// by default, didn't handle it
+	// AGENT_CONTROL_LBUTTON_UP is handled by scanMouse() and scanKey()
 	// LL_INFOS() << "LLTool::handleMouseUp" << LL_ENDL;
-	gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
 	return TRUE;
 }
 
@@ -115,6 +115,12 @@ BOOL LLTool::handleScrollWheel(S32 x, S32 y, S32 clicks)
 	return FALSE;
 }
 
+BOOL LLTool::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+    // by default, didn't handle it
+    return FALSE;
+}
+
 BOOL LLTool::handleDoubleClick(S32 x,S32 y,MASK mask)
 {
 	// LL_INFOS() << "LLTool::handleDoubleClick" << LL_ENDL;
diff --git a/indra/newview/lltool.h b/indra/newview/lltool.h
index c5bad9d53272635821f71587dfe9764290faeebb..41a38804cea4baa16b23435b05edf47dd0f03e51 100644
--- a/indra/newview/lltool.h
+++ b/indra/newview/lltool.h
@@ -49,7 +49,7 @@ class LLTool
 	virtual BOOL isView() const { return FALSE; }
 
 	// Virtual functions inherited from LLMouseHandler
-	virtual BOOL	handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
+	virtual BOOL	handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
 	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleMiddleMouseDown(S32 x, S32 y, MASK mask);
@@ -57,6 +57,7 @@ class LLTool
 
 	virtual BOOL	handleHover(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleScrollWheel(S32 x, S32 y, S32 clicks);
+	virtual BOOL	handleScrollHWheel(S32 x, S32 y, S32 clicks);
 	virtual BOOL	handleDoubleClick(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleRightMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleRightMouseUp(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index f66211ef3462e77525e20680cb19bc616f112489..7d77a8983f7de8b9ec32d22fa838230922ddebf2 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -1728,6 +1728,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
 	const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
 	if(gInventory.isObjectDescendentOf(item->getUUID(), outbox_id))
 	{
+		// Legacy
 		return ACCEPT_NO;
 	}
 
@@ -2154,6 +2155,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
 		const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
 		if(gInventory.isObjectDescendentOf(category->getUUID(), outbox_id))
 		{
+			// Legacy
 			return ACCEPT_NO;
 		}
 
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index 3831f7d67dae7ab81943e0bde176d5617853d0bc..a4806ceaf64df5834687b2bbbe401f9778b62d86 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -721,9 +721,14 @@ void LLToolGrabBase::handleHoverActive(S32 x, S32 y, MASK mask)
 			!objectp->isHUDAttachment() && 
 			objectp->getRoot() == gAgentAvatarp->getRoot())
 		{
-			// force focus to point in space where we were looking previously
-			gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
-			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+			// we are essentially editing object position
+			if (!gSavedSettings.getBOOL("EditCameraMovement"))
+			{
+				// force focus to point in space where we were looking previously
+				// Example of use: follow cam scripts shouldn't affect you when movng objects arouns
+				gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
+				gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+			}
 		}
 		else
 		{
diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp
index f6eb290bc34660297224b132b9b6189440e1e294..3fcf193deca2f4688744f41cd14b7798f43e1b39 100644
--- a/indra/newview/lltoolmgr.cpp
+++ b/indra/newview/lltoolmgr.cpp
@@ -355,7 +355,7 @@ bool LLToolMgr::inBuildMode()
 
 bool LLToolMgr::canAccessMarketplace()
 {
-	return (LLMarketplaceData::instance().getSLMStatus() != MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT) || gSavedSettings.getBOOL("InventoryOutboxDisplayBoth");
+	return (LLMarketplaceData::instance().getSLMStatus() != MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT);
 }
 
 void LLToolMgr::toggleMarketplace(const LLSD& sdname)
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 54df5198c8c95a18d5e5e453a6c65486c6bfa98f..dd429d4ccfcc32a1e65b7a43d15be249118fddbe 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -83,7 +83,6 @@ LLToolPie::LLToolPie()
 	mMouseOutsideSlop( false ),
 	mMouseSteerX(-1),
 	mMouseSteerY(-1),
-	mBlockClickToWalk(false),
 	mClickAction(0),
 	mClickActionBuyEnabled( gSavedSettings.getBOOL("ClickActionBuyEnabled") ),
 	mClickActionPayEnabled( gSavedSettings.getBOOL("ClickActionPayEnabled") ),
@@ -91,7 +90,7 @@ LLToolPie::LLToolPie()
 {
 }
 
-BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down)
+BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
 {
 	BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
 	
@@ -172,10 +171,8 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
 	mPick.mKeyMask = mask;
 
 	mMouseButtonDown = true;
-	
-	handleLeftClickPick();
 
-	return TRUE;
+    return handleLeftClickPick();
 }
 
 // Spawn context menus on right mouse down so you can drag over and select
@@ -208,6 +205,11 @@ BOOL LLToolPie::handleScrollWheel(S32 x, S32 y, S32 clicks)
 	return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
 }
 
+BOOL LLToolPie::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+    return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
+}
+
 // True if you selected an object.
 BOOL LLToolPie::handleLeftClickPick()
 {
@@ -369,8 +371,6 @@ BOOL LLToolPie::handleLeftClickPick()
 	// put focus back "in world"
 	if (gFocusMgr.getKeyboardFocus())
 	{
-		// don't click to walk on attempt to give focus to world
-		mBlockClickToWalk = true;
 		gFocusMgr.setKeyboardFocus(NULL);
 	}
 
@@ -414,7 +414,7 @@ BOOL LLToolPie::handleLeftClickPick()
 		}
 		object = (LLViewerObject*)object->getParent();
 	}
-	if (object && object == gAgentAvatarp && !gSavedSettings.getBOOL("ClickToWalk"))
+	if (object && object == gAgentAvatarp)
 	{
 		// we left clicked on avatar, switch to focus mode
 		mMouseButtonDown = false;
@@ -431,7 +431,6 @@ BOOL LLToolPie::handleLeftClickPick()
 	//	LLFirstUse::useLeftClickNoHit();
 	/////////
 
-	// Eat the event
 	return LLTool::handleMouseDown(x, y, mask);
 }
 
@@ -538,17 +537,97 @@ void LLToolPie::resetSelection()
 	mClickAction = 0;
 }
 
-void LLToolPie::walkToClickedLocation()
+bool LLToolPie::walkToClickedLocation()
+{
+    if (gAgent.getFlying()							// don't auto-navigate while flying until that works
+        || !gAgentAvatarp
+        || gAgentAvatarp->isSitting())
+    {
+        return false;
+    }
+
+    LLPickInfo saved_pick = mPick;
+    mPick = gViewerWindow->pickImmediate(mHoverPick.mMousePt.mX, mHoverPick.mMousePt.mY,
+        FALSE /* ignore transparent */,
+        FALSE /* ignore rigged */,
+        FALSE /* ignore particles */);
+
+    if (mPick.mPickType == LLPickInfo::PICK_OBJECT)
+    {
+        if (mPick.getObject() && mPick.getObject()->isHUDAttachment())
+        {
+            mPick = saved_pick;
+            return false;
+        }
+    }
+
+    LLViewerObject* avatar_object = mPick.getObject();
+
+    // get pointer to avatar
+    while (avatar_object && !avatar_object->isAvatar())
+    {
+        avatar_object = (LLViewerObject*)avatar_object->getParent();
+    }
+
+    if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
+    {
+        const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
+        // pretend we picked some point a bit in front of avatar
+        mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
+    }
+
+    if ((mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) ||
+        (mPick.mObjectID.notNull() && !mPick.mPosGlobal.isExactlyZero()))
+    {
+        gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
+
+        if (mAutoPilotDestination) { mAutoPilotDestination->markDead(); }
+        mAutoPilotDestination = (LLHUDEffectBlob *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BLOB, FALSE);
+        mAutoPilotDestination->setPositionGlobal(mPick.mPosGlobal);
+        mAutoPilotDestination->setPixelSize(5);
+        mAutoPilotDestination->setColor(LLColor4U(170, 210, 190));
+        mAutoPilotDestination->setDuration(3.f);
+
+        LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
+        gAgent.startAutoPilotGlobal(pos, std::string(), NULL, NULL, NULL, 0.f, 0.03f, FALSE);
+        LLFirstUse::notMoving(false);
+        showVisualContextMenuEffect();
+        return true;
+    }
+    else
+    {
+        LL_DEBUGS() << "walk target was "
+            << (mPick.mPosGlobal.isExactlyZero() ? "zero" : "not zero")
+            << ", pick type was " << (mPick.mPickType == LLPickInfo::PICK_LAND ? "land" : "not land")
+            << ", pick object was " << mPick.mObjectID
+            << LL_ENDL;
+        mPick = saved_pick;
+        return false;
+    }
+    return true;
+}
+
+bool LLToolPie::teleportToClickedLocation()
 {
-	if(mAutoPilotDestination) { mAutoPilotDestination->markDead(); }
-	mAutoPilotDestination = (LLHUDEffectBlob *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BLOB, FALSE);
-	mAutoPilotDestination->setPositionGlobal(mPick.mPosGlobal);
-	mAutoPilotDestination->setPixelSize(5);
-	mAutoPilotDestination->setColor(LLColor4U(170, 210, 190));
-	mAutoPilotDestination->setDuration(3.f);
-
-	LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
-	gAgent.startAutoPilotGlobal(pos, std::string(), NULL, NULL, NULL, 0.f, 0.03f, FALSE);
+    LLViewerObject* objp = mHoverPick.getObject();
+    LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL;
+
+    bool is_in_world = mHoverPick.mObjectID.notNull() && objp && !objp->isHUDAttachment();
+    bool is_land = mHoverPick.mPickType == LLPickInfo::PICK_LAND;
+    bool pos_non_zero = !mHoverPick.mPosGlobal.isExactlyZero();
+    bool has_touch_handler = (objp && objp->flagHandleTouch()) || (parentp && parentp->flagHandleTouch());
+    bool has_click_action = final_click_action(objp);
+
+    if (pos_non_zero && (is_land || (is_in_world && !has_touch_handler && !has_click_action)))
+    {
+        LLVector3d pos = mHoverPick.mPosGlobal;
+        pos.mdV[VZ] += gAgentAvatarp->getPelvisToFoot();
+        gAgent.teleportViaLocationLookAt(pos);
+        mPick = mHoverPick;
+        showVisualContextMenuEffect();
+        return true;
+    }
+    return false;
 }
 
 // When we get object properties after left-clicking on an object
@@ -624,8 +703,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
 		LL_DEBUGS("UserInput") << "hover handled by LLToolPie (inactive)" << LL_ENDL;
 	}
 	else if (!mMouseOutsideSlop 
-		&& mMouseButtonDown 
-		&& gSavedSettings.getBOOL("ClickToWalk"))
+		&& mMouseButtonDown)
 	{
 		S32 delta_x = x - mMouseDownX;
 		S32 delta_y = y - mMouseDownY;
@@ -710,70 +788,10 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
         mDoubleClickTimer.reset();
     }
     LLViewerObject* obj = mPick.getObject();
-	U8 click_action = final_click_action(obj);
 
-	// let media have first pass at click
-	if (handleMediaMouseUp() || LLViewerMediaFocus::getInstance()->getFocus())
-	{
-		mBlockClickToWalk = true;
-	}
 	stopCameraSteering();
 	mMouseButtonDown = false;
 
-	if (click_action == CLICK_ACTION_NONE				// not doing 1-click action
-		&& gSavedSettings.getBOOL("ClickToWalk")		// click to walk enabled
-		&& !gAgent.getFlying()							// don't auto-navigate while flying until that works
-		&& gAgentAvatarp
-		&& !gAgentAvatarp->isSitting()
-		&& !mBlockClickToWalk							// another behavior hasn't cancelled click to walk
-        )
-	{
-        // We may be doing click to walk, but we don't want to use a target on
-        // a transparent object because the user thought they were clicking on
-        // whatever they were seeing through it, so recompute what was clicked on
-        // ignoring transparent objects
-        LLPickInfo savedPick = mPick;
-        mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY,
-                                             FALSE /* ignore transparent */,
-                                             FALSE /* ignore rigged */,
-                                             FALSE /* ignore particles */);
-
-        if (!mPick.mPosGlobal.isExactlyZero()			// valid coordinates for pick
-            && (mPick.mPickType == LLPickInfo::PICK_LAND	// we clicked on land
-                || mPick.mObjectID.notNull()))				// or on an object
-        {
-            // handle special cases of steering picks
-            LLViewerObject* avatar_object = mPick.getObject();
-
-            // get pointer to avatar
-            while (avatar_object && !avatar_object->isAvatar())
-            {
-                avatar_object = (LLViewerObject*)avatar_object->getParent();
-            }
-
-            if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
-            {
-                const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
-                // pretend we picked some point a bit in front of avatar
-                mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
-            }
-            gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
-            walkToClickedLocation();
-            LLFirstUse::notMoving(false);
-
-            return TRUE;
-        }
-        else
-        {
-            LL_DEBUGS("maint5901") << "walk target was "
-                                   << (mPick.mPosGlobal.isExactlyZero() ? "zero" : "not zero")
-                                   << ", pick type was " << (mPick.mPickType == LLPickInfo::PICK_LAND ? "land" : "not land")
-                                   << ", pick object was " << mPick.mObjectID
-                                   << LL_ENDL;
-            // we didn't click to walk, so restore the original target
-            mPick = savedPick;
-        }
-	}
 	gViewerWindow->setCursor(UI_CURSOR_ARROW);
 	if (hasMouseCapture())
 	{
@@ -783,7 +801,6 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
 	LLToolMgr::getInstance()->clearTransientTool();
 	gAgentCamera.setLookAt(LOOKAT_TARGET_CONVERSATION, obj); // maybe look at object/person clicked on
 
-	mBlockClickToWalk = false;
 	return LLTool::handleMouseUp(x, y, mask);
 }
 
@@ -809,102 +826,21 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
 		return TRUE;
 	}
     
-    	if (!mDoubleClickTimer.getStarted() || (mDoubleClickTimer.getElapsedTimeF32() > 0.3f))
+	if (!mDoubleClickTimer.getStarted() || (mDoubleClickTimer.getElapsedTimeF32() > 0.3f))
 	{
 		mDoubleClickTimer.stop();
 		return FALSE;
 	}
 	mDoubleClickTimer.stop();
 
-	if (gSavedSettings.getBOOL("DoubleClickAutoPilot"))
-	{
-        // We may be doing double click to walk, but we don't want to use a target on
-        // a transparent object because the user thought they were clicking on
-        // whatever they were seeing through it, so recompute what was clicked on
-        // ignoring transparent objects
-        LLPickInfo savedPick = mPick;
-        mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY,
-                                             FALSE /* ignore transparent */,
-                                             FALSE /* ignore rigged */,
-                                             FALSE /* ignore particles */);
-
-        if(mPick.mPickType == LLPickInfo::PICK_OBJECT)
-        {
-            if (mPick.getObject() && mPick.getObject()->isHUDAttachment())
-            {
-                mPick = savedPick;
-                return FALSE;
-            }
-        }
-
-		if ((mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) ||
-			(mPick.mObjectID.notNull()  && !mPick.mPosGlobal.isExactlyZero()))
-		{
-			walkToClickedLocation();
-			return TRUE;
-		}
-        else
-        {
-            // restore the original pick for any other purpose
-            mPick = savedPick;
-        }
-	}
-	else if (gSavedSettings.getBOOL("DoubleClickTeleport"))
-	{
-		LLViewerObject* objp = mPick.getObject();
-		LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL;
-
-		bool is_in_world = mPick.mObjectID.notNull() && objp && !objp->isHUDAttachment();
-		bool is_land = mPick.mPickType == LLPickInfo::PICK_LAND;
-		bool pos_non_zero = !mPick.mPosGlobal.isExactlyZero();
-		bool has_touch_handler = (objp && objp->flagHandleTouch()) || (parentp && parentp->flagHandleTouch());
-		bool has_click_action = final_click_action(objp);
-
-		if (pos_non_zero && (is_land || (is_in_world && !has_touch_handler && !has_click_action)))
-		{
-			LLVector3d pos = mPick.mPosGlobal;
-			pos.mdV[VZ] += gAgentAvatarp->getPelvisToFoot();
-			gAgent.teleportViaLocationLookAt(pos);
-			return TRUE;
-		}
-	}
-
 	return FALSE;
 }
 
 static bool needs_tooltip(LLSelectNode* nodep)
 {
-	if (!nodep) 
+	if (!nodep || !nodep->mValid) 
 		return false;
-
-	LLViewerObject* object = nodep->getObject();
-	LLViewerObject *parent = (LLViewerObject *)object->getParent();
-	if (object->flagHandleTouch()
-		|| (parent && parent->flagHandleTouch())
-		|| object->flagTakesMoney()
-		|| (parent && parent->flagTakesMoney())
-		|| object->flagAllowInventoryAdd()
-		)
-	{
-		return true;
-	}
-
-	U8 click_action = final_click_action(object);
-	if (click_action != 0)
-	{
-		return true;
-	}
-
-	if (nodep->mValid)
-	{
-		bool anyone_copy = anyone_copy_selection(nodep);
-		bool for_sale = for_sale_selection(nodep);
-		if (anyone_copy || for_sale)
-		{
-			return true;
-		}
-	}
-	return false;
+	return true;
 }
 
 
@@ -1428,7 +1364,6 @@ void LLToolPie::VisitHomePage(const LLPickInfo& info)
 void LLToolPie::handleSelect()
 {
 	// tool is reselected when app gets focus, etc.
-	mBlockClickToWalk = true;	
 }
 
 void LLToolPie::handleDeselect()
@@ -1489,7 +1424,7 @@ void LLToolPie::stopCameraSteering()
 
 bool LLToolPie::inCameraSteerMode()
 {
-	return mMouseButtonDown && mMouseOutsideSlop && gSavedSettings.getBOOL("ClickToWalk");
+	return mMouseButtonDown && mMouseOutsideSlop;
 }
 
 // true if x,y outside small box around start_x,start_y
@@ -1940,7 +1875,6 @@ void LLToolPie::startCameraSteering()
 {
 	LLFirstUse::notMoving(false);
 	mMouseOutsideSlop = true;
-	mBlockClickToWalk = true;
 
 	if (gAgentCamera.getFocusOnAvatar())
 	{
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index 95d155a474a4ea1005df415b3784524794bfb906..ac6751aac0fad8deec86a6bdb4e1272f1f770dec 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -42,7 +42,7 @@ class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
 public:
 
 	// Virtual functions inherited from LLMouseHandler
-	virtual BOOL		handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
+	virtual BOOL		handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
 	virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL		handleRightMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask);
@@ -50,6 +50,7 @@ class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
 	virtual BOOL		handleHover(S32 x, S32 y, MASK mask);
 	virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask);
 	virtual BOOL		handleScrollWheel(S32 x, S32 y, S32 clicks);
+	virtual BOOL		handleScrollHWheel(S32 x, S32 y, S32 clicks);
 	virtual BOOL		handleToolTip(S32 x, S32 y, MASK mask);
 
 	virtual void		render();
@@ -66,8 +67,8 @@ class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
 	LLViewerObject*		getClickActionObject() { return mClickActionObject; }
 	LLObjectSelection*	getLeftClickSelection() { return (LLObjectSelection*)mLeftClickSelection; }
 	void 				resetSelection();
-	void				walkToClickedLocation();
-	void				blockClickToWalk() { mBlockClickToWalk = true; }
+	bool				walkToClickedLocation();
+	bool				teleportToClickedLocation();
 	void				stopClickToWalk();
 	
 	static void			selectionPropertiesReceived();
@@ -109,7 +110,6 @@ class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
 	LLPointer<LLHUDEffectBlob>	mAutoPilotDestination;
 	LLPointer<LLHUDEffectBlob>	mMouseSteerGrabPoint;
 	bool				mClockwise;			
-	bool				mBlockClickToWalk;
 	LLUUID				mMediaMouseCaptureID;
 	LLPickInfo			mPick;
 	LLPickInfo			mHoverPick;
diff --git a/indra/newview/lluploadfloaterobservers.h b/indra/newview/lluploadfloaterobservers.h
index 15c3dad38e6ba2e843308f40f358a282f2001463..77e950a1c9ed83bcf69f73069b25b0945758651a 100644
--- a/indra/newview/lluploadfloaterobservers.h
+++ b/indra/newview/lluploadfloaterobservers.h
@@ -53,7 +53,7 @@ class LLWholeModelFeeObserver
 	virtual ~LLWholeModelFeeObserver() {}
 
 	virtual void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) = 0;
-	virtual void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason) = 0;
+	virtual void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason, const LLSD& result) = 0;
 
 	LLHandle<LLWholeModelFeeObserver> getWholeModelFeeObserverHandle() const { return mWholeModelFeeObserverHandle; }
 
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index d8526e63caeed25370cb7cdcc339a74a2927d8ed..6df849674f26b56349b38b5ce5d4553ce43a1363 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1087,7 +1087,7 @@ void render_hud_attachments()
 	// clamp target zoom level to reasonable values
 	gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f);
 	// smoothly interpolate current zoom level
-	gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLSmoothInterpolation::getInterpolant(0.03f));
+	gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.getAgentHUDTargetZoom(), LLSmoothInterpolation::getInterpolant(0.03f));
 
 	if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
 	{
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index f475ab7d6630248e13fda8a6be7e8d6adc46f678..846a8e62a15393499b5fff1755805ffef731d813 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -69,6 +69,7 @@
 #include "llfloaterevent.h"
 #include "llfloaterflickr.h"
 #include "llfloaterfonttest.h"
+#include "llfloaterforgetuser.h"
 #include "llfloatergesture.h"
 #include "llfloatergodtools.h"
 #include "llfloatergridstatus.h"
@@ -235,6 +236,7 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("experience_search", "floater_experience_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiencePicker>);
 
 	LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFontTest>);
+	LLFloaterReg::add("forget_username", "floater_forget_user.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterForgetUser>);
 
 	LLFloaterReg::add("gestures", "floater_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGesture>);
 	LLFloaterReg::add("god_tools", "floater_god_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGodTools>);
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0718a27696a4ce1a4511f210d233d1e7d1c9b651
--- /dev/null
+++ b/indra/newview/llviewerinput.cpp
@@ -0,0 +1,1525 @@
+/** 
+ * @file llviewerinput.cpp
+ * @brief LLViewerInput class implementation
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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 "llviewerprecompiledheaders.h"
+
+#include "llviewerinput.h"
+
+#include "llappviewer.h"
+#include "llfloaterreg.h"
+#include "llmath.h"
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llfloaterimnearbychat.h"
+#include "llfocusmgr.h"
+#include "llkeybind.h" // LLKeyData
+#include "llmorphview.h"
+#include "llmoveview.h"
+#include "lltoolfocus.h"
+#include "lltoolpie.h"
+#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+#include "llvoavatarself.h"
+#include "llfloatercamera.h"
+#include "llinitparam.h"
+
+//
+// Constants
+//
+
+const F32 FLY_TIME = 0.5f;
+const F32 FLY_FRAMES = 4;
+
+const F32 NUDGE_TIME = 0.25f;  // in seconds
+const S32 NUDGE_FRAMES = 2;
+const F32 ORBIT_NUDGE_RATE = 0.05f;  // fraction of normal speed
+
+const LLKeyData agent_control_lbutton(CLICK_LEFT, KEY_NONE, MASK_NONE, true);
+
+struct LLKeyboardActionRegistry 
+:	public LLRegistrySingleton<std::string, boost::function<bool (EKeystate keystate)>, LLKeyboardActionRegistry>
+{
+	LLSINGLETON_EMPTY_CTOR(LLKeyboardActionRegistry);
+};
+
+LLViewerInput gViewerInput;
+
+bool agent_jump( EKeystate s )
+{
+	static BOOL first_fly_attempt(TRUE);
+	if (KEYSTATE_UP == s)
+	{
+		first_fly_attempt = TRUE;
+		return true;
+	}
+	F32 time = gKeyboard->getCurKeyElapsedTime();
+	S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
+
+	if( time < FLY_TIME 
+		|| frame_count <= FLY_FRAMES 
+		|| gAgent.upGrabbed()
+		|| !gSavedSettings.getBOOL("AutomaticFly"))
+	{
+		gAgent.moveUp(1);
+	}
+	else
+	{
+		gAgent.setFlying(TRUE, first_fly_attempt);
+		first_fly_attempt = FALSE;
+		gAgent.moveUp(1);
+	}
+	return true;
+}
+
+bool agent_push_down( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgent.moveUp(-1);
+	return true;
+}
+
+static void agent_check_temporary_run(LLAgent::EDoubleTapRunMode mode)
+{
+	if (gAgent.mDoubleTapRunMode == mode &&
+		gAgent.getRunning() &&
+		!gAgent.getAlwaysRun())
+	{
+		// Turn off temporary running.
+		gAgent.clearRunning();
+		gAgent.sendWalkRun(gAgent.getRunning());
+	}
+}
+
+static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode mode)
+{
+	if (KEYSTATE_UP == s)
+	{
+		// Note: in case shift is already released, slide left/right run
+		// will be released in agent_turn_left()/agent_turn_right()
+		agent_check_temporary_run(mode);
+	}
+	else if (gSavedSettings.getBOOL("AllowTapTapHoldRun") &&
+		 KEYSTATE_DOWN == s &&
+		 !gAgent.getRunning())
+	{
+		if (gAgent.mDoubleTapRunMode == mode &&
+		    gAgent.mDoubleTapRunTimer.getElapsedTimeF32() < NUDGE_TIME)
+		{
+			// Same walk-key was pushed again quickly; this is a
+			// double-tap so engage temporary running.
+			gAgent.setRunning();
+			gAgent.sendWalkRun(gAgent.getRunning());
+		}
+
+		// Pressing any walk-key resets the double-tap timer
+		gAgent.mDoubleTapRunTimer.reset();
+		gAgent.mDoubleTapRunMode = mode;
+	}
+}
+
+static void agent_push_forwardbackward( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
+{
+	agent_handle_doubletap_run(s, mode);
+	if (KEYSTATE_UP == s) return;
+
+	F32 time = gKeyboard->getCurKeyElapsedTime();
+	S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
+
+	if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
+	{
+		gAgent.moveAtNudge(direction);
+	}
+	else
+	{
+		gAgent.moveAt(direction);
+	}
+}
+
+bool camera_move_forward( EKeystate s );
+
+bool agent_push_forward( EKeystate s )
+{
+	if(gAgent.isMovementLocked()) return true;
+
+	//in free camera control mode we need to intercept keyboard events for avatar movements
+	if (LLFloaterCamera::inFreeCameraMode())
+	{
+		camera_move_forward(s);
+	}
+	else
+	{
+		agent_push_forwardbackward(s, 1, LLAgent::DOUBLETAP_FORWARD);
+	}
+	return true;
+}
+
+bool camera_move_backward( EKeystate s );
+
+bool agent_push_backward( EKeystate s )
+{
+	if(gAgent.isMovementLocked()) return true;
+
+	//in free camera control mode we need to intercept keyboard events for avatar movements
+	if (LLFloaterCamera::inFreeCameraMode())
+	{
+		camera_move_backward(s);
+	}
+	else if (!gAgent.backwardGrabbed() && gAgentAvatarp->isSitting() && gSavedSettings.getBOOL("LeaveMouselook"))
+	{
+		gAgentCamera.changeCameraToThirdPerson();
+	}
+	else
+	{
+		agent_push_forwardbackward(s, -1, LLAgent::DOUBLETAP_BACKWARD);
+	}
+	return true;
+}
+
+static void agent_slide_leftright( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
+{
+	agent_handle_doubletap_run(s, mode);
+	if( KEYSTATE_UP == s ) return;
+	F32 time = gKeyboard->getCurKeyElapsedTime();
+	S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
+
+	if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
+	{
+		gAgent.moveLeftNudge(direction);
+	}
+	else
+	{
+		gAgent.moveLeft(direction);
+	}
+}
+
+
+bool agent_slide_left( EKeystate s )
+{
+	if(gAgent.isMovementLocked()) return true;
+	agent_slide_leftright(s, 1, LLAgent::DOUBLETAP_SLIDELEFT);
+	return true;
+}
+
+
+bool agent_slide_right( EKeystate s )
+{
+	if(gAgent.isMovementLocked()) return true;
+	agent_slide_leftright(s, -1, LLAgent::DOUBLETAP_SLIDERIGHT);
+	return true;
+}
+
+bool camera_spin_around_cw( EKeystate s );
+
+bool agent_turn_left(EKeystate s)
+{
+	//in free camera control mode we need to intercept keyboard events for avatar movements
+	if (LLFloaterCamera::inFreeCameraMode())
+	{
+		camera_spin_around_cw(s);
+		return true;
+	}
+
+	if(gAgent.isMovementLocked()) return false;
+
+	if (LLToolCamera::getInstance()->mouseSteerMode())
+	{
+		agent_slide_left(s);
+	}
+	else
+	{
+		if (KEYSTATE_UP == s)
+		{
+			// Check temporary running. In case user released 'left' key with shift already released.
+			agent_check_temporary_run(LLAgent::DOUBLETAP_SLIDELEFT);
+			return true;
+		}
+		F32 time = gKeyboard->getCurKeyElapsedTime();
+		gAgent.moveYaw( LLFloaterMove::getYawRate( time ) );
+	}
+	return true;
+}
+
+bool camera_spin_around_ccw( EKeystate s );
+
+bool agent_turn_right( EKeystate s )
+{
+	//in free camera control mode we need to intercept keyboard events for avatar movements
+	if (LLFloaterCamera::inFreeCameraMode())
+	{
+		camera_spin_around_ccw(s);
+		return true;
+	}
+
+	if(gAgent.isMovementLocked()) return false;
+
+	if (LLToolCamera::getInstance()->mouseSteerMode())
+	{
+		agent_slide_right(s);
+	}
+	else
+	{
+		if (KEYSTATE_UP == s)
+		{
+			// Check temporary running. In case user released 'right' key with shift already released.
+			agent_check_temporary_run(LLAgent::DOUBLETAP_SLIDERIGHT);
+			return true;
+		}
+		F32 time = gKeyboard->getCurKeyElapsedTime();
+		gAgent.moveYaw( -LLFloaterMove::getYawRate( time ) );
+	}
+	return true;
+}
+
+bool agent_look_up( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgent.movePitch(-1);
+	//gAgent.rotate(-2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
+	return true;
+}
+
+
+bool agent_look_down( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgent.movePitch(1);
+	//gAgent.rotate(2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
+	return true;
+}
+
+bool agent_toggle_fly( EKeystate s )
+{
+	// Only catch the edge
+	if (KEYSTATE_DOWN == s )
+	{
+		LLAgent::toggleFlying();
+	}
+	return true;
+}
+
+F32 get_orbit_rate()
+{
+	F32 time = gKeyboard->getCurKeyElapsedTime();
+	if( time < NUDGE_TIME )
+	{
+		F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME;
+		//LL_INFOS() << rate << LL_ENDL;
+		return rate;
+	}
+	else
+	{
+		return 1;
+	}
+}
+
+bool camera_spin_around_ccw( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
+	return true;
+}
+
+
+bool camera_spin_around_cw( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setOrbitRightKey( get_orbit_rate() );
+	return true;
+}
+
+bool camera_spin_around_ccw_sitting( EKeystate s )
+{
+	if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDERIGHT ) return true;
+	if (gAgent.rotateGrabbed() || gAgentCamera.sitCameraEnabled() || gAgent.getRunning())
+	{
+		//send keystrokes, but do not change camera
+		agent_turn_right(s);
+	}
+	else
+	{
+		//change camera but do not send keystrokes
+		gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
+	}
+	return true;
+}
+
+
+bool camera_spin_around_cw_sitting( EKeystate s )
+{
+	if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDELEFT ) return true;
+	if (gAgent.rotateGrabbed() || gAgentCamera.sitCameraEnabled() || gAgent.getRunning())
+	{
+		//send keystrokes, but do not change camera
+		agent_turn_left(s);
+	}
+	else
+	{
+		//change camera but do not send keystrokes
+		gAgentCamera.setOrbitRightKey( get_orbit_rate() );
+	}
+	return true;
+}
+
+
+bool camera_spin_over( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setOrbitUpKey( get_orbit_rate() );
+	return true;
+}
+
+
+bool camera_spin_under( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setOrbitDownKey( get_orbit_rate() );
+	return true;
+}
+
+bool camera_spin_over_sitting( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	if (gAgent.upGrabbed() || gAgentCamera.sitCameraEnabled())
+	{
+		//send keystrokes, but do not change camera
+		agent_jump(s);
+	}
+	else
+	{
+		//change camera but do not send keystrokes
+		gAgentCamera.setOrbitUpKey( get_orbit_rate() );
+	}
+	return true;
+}
+
+
+bool camera_spin_under_sitting( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	if (gAgent.downGrabbed() || gAgentCamera.sitCameraEnabled())
+	{
+		//send keystrokes, but do not change camera
+		agent_push_down(s);
+	}
+	else
+	{
+		//change camera but do not send keystrokes
+		gAgentCamera.setOrbitDownKey( get_orbit_rate() );
+	}
+	return true;
+}
+
+bool camera_move_forward( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setOrbitInKey( get_orbit_rate() );
+	return true;
+}
+
+
+bool camera_move_backward( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setOrbitOutKey( get_orbit_rate() );
+	return true;
+}
+
+bool camera_move_forward_sitting( EKeystate s )
+{
+	if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_FORWARD ) return true;
+	if (gAgent.forwardGrabbed() || gAgentCamera.sitCameraEnabled() || (gAgent.getRunning() && !gAgent.getAlwaysRun()))
+	{
+		agent_push_forward(s);
+	}
+	else
+	{
+		gAgentCamera.setOrbitInKey( get_orbit_rate() );
+	}
+	return true;
+}
+
+bool camera_move_backward_sitting( EKeystate s )
+{
+	if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_BACKWARD ) return true;
+
+	if (gAgent.backwardGrabbed() || gAgentCamera.sitCameraEnabled() || (gAgent.getRunning() && !gAgent.getAlwaysRun()))
+	{
+		agent_push_backward(s);
+	}
+	else
+	{
+		gAgentCamera.setOrbitOutKey( get_orbit_rate() );
+	}
+	return true;
+}
+
+bool camera_pan_up( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setPanUpKey( get_orbit_rate() );
+	return true;
+}
+
+bool camera_pan_down( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setPanDownKey( get_orbit_rate() );
+	return true;
+}
+
+bool camera_pan_left( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setPanLeftKey( get_orbit_rate() );
+	return true;
+}
+
+bool camera_pan_right( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setPanRightKey( get_orbit_rate() );
+	return true;
+}
+
+bool camera_pan_in( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setPanInKey( get_orbit_rate() );
+	return true;
+}
+
+bool camera_pan_out( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setPanOutKey( get_orbit_rate() );
+	return true;
+}
+
+bool camera_move_forward_fast( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setOrbitInKey(2.5f);
+	return true;
+}
+
+bool camera_move_backward_fast( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gAgentCamera.unlockView();
+	gAgentCamera.setOrbitOutKey(2.5f);
+	return true;
+}
+
+
+bool edit_avatar_spin_ccw( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gMorphView->setCameraDrivenByKeys( TRUE );
+	gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
+	//gMorphView->orbitLeft( get_orbit_rate() );
+	return true;
+}
+
+
+bool edit_avatar_spin_cw( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gMorphView->setCameraDrivenByKeys( TRUE );
+	gAgentCamera.setOrbitRightKey( get_orbit_rate() );
+	//gMorphView->orbitRight( get_orbit_rate() );
+	return true;
+}
+
+bool edit_avatar_spin_over( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gMorphView->setCameraDrivenByKeys( TRUE );
+	gAgentCamera.setOrbitUpKey( get_orbit_rate() );
+	//gMorphView->orbitUp( get_orbit_rate() );
+	return true;
+}
+
+
+bool edit_avatar_spin_under( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gMorphView->setCameraDrivenByKeys( TRUE );
+	gAgentCamera.setOrbitDownKey( get_orbit_rate() );
+	//gMorphView->orbitDown( get_orbit_rate() );
+	return true;
+}
+
+bool edit_avatar_move_forward( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gMorphView->setCameraDrivenByKeys( TRUE );
+	gAgentCamera.setOrbitInKey( get_orbit_rate() );
+	//gMorphView->orbitIn();
+	return true;
+}
+
+
+bool edit_avatar_move_backward( EKeystate s )
+{
+	if( KEYSTATE_UP == s  ) return true;
+	gMorphView->setCameraDrivenByKeys( TRUE );
+	gAgentCamera.setOrbitOutKey( get_orbit_rate() );
+	//gMorphView->orbitOut();
+	return true;
+}
+
+bool stop_moving( EKeystate s )
+{
+	if( KEYSTATE_DOWN != s  ) return true;
+	// stop agent
+	gAgent.setControlFlags(AGENT_CONTROL_STOP);
+
+	// cancel autopilot
+	gAgent.stopAutoPilot();
+	return true;
+}
+
+bool start_chat( EKeystate s )
+{
+    if (LLAppViewer::instance()->quitRequested())
+    {
+        return true; // can't talk, gotta go, kthxbye!
+    }
+    if (KEYSTATE_DOWN != s) return true;
+
+	// start chat
+	LLFloaterIMNearbyChat::startChat(NULL);
+	return true;
+}
+
+bool start_gesture( EKeystate s )
+{
+	LLUICtrl* focus_ctrlp = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+	if (KEYSTATE_UP == s &&
+		! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))
+	{
+ 		if ((LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->getCurrentChat().empty())
+ 		{
+ 			// No existing chat in chat editor, insert '/'
+ 			LLFloaterIMNearbyChat::startChat("/");
+ 		}
+ 		else
+ 		{
+ 			// Don't overwrite existing text in chat editor
+ 			LLFloaterIMNearbyChat::startChat(NULL);
+ 		}
+	}
+	return true;
+}
+
+bool run_forward(EKeystate s)
+{
+    if (KEYSTATE_UP != s)
+    {
+        if (gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_FORWARD)
+        {
+            gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_FORWARD;
+        }
+        if (!gAgent.getRunning())
+        {
+            gAgent.setRunning();
+            gAgent.sendWalkRun(true);
+        }
+    }
+    else if(KEYSTATE_UP == s)
+    {
+        if (gAgent.mDoubleTapRunMode == LLAgent::DOUBLETAP_FORWARD)
+            gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_NONE;
+        gAgent.clearRunning();
+        gAgent.sendWalkRun(false);
+    }
+    agent_push_forward(s);
+    return true;
+}
+
+bool run_backward(EKeystate s)
+{
+    if (KEYSTATE_UP != s)
+    {
+        if (gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_BACKWARD)
+        {
+            gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_BACKWARD;
+        }
+        if (!gAgent.getRunning())
+        {
+            gAgent.setRunning();
+            gAgent.sendWalkRun(true);
+        }
+    }
+    else if (KEYSTATE_UP == s)
+    {
+        if (gAgent.mDoubleTapRunMode == LLAgent::DOUBLETAP_BACKWARD)
+            gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_NONE;
+        gAgent.clearRunning();
+        gAgent.sendWalkRun(false);
+    }
+    agent_push_backward(s);
+    return true;
+}
+
+bool run_left(EKeystate s)
+{
+    if (KEYSTATE_UP != s)
+    {
+        if (gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDELEFT)
+        {
+            gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_SLIDELEFT;
+        }
+        if (!gAgent.getRunning())
+        {
+            gAgent.setRunning();
+            gAgent.sendWalkRun(true);
+        }
+    }
+    else if (KEYSTATE_UP == s)
+    {
+        if (gAgent.mDoubleTapRunMode == LLAgent::DOUBLETAP_SLIDELEFT)
+            gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_NONE;
+        gAgent.clearRunning();
+        gAgent.sendWalkRun(false);
+    }
+    agent_slide_left(s);
+    return true;
+}
+
+bool run_right(EKeystate s)
+{
+    if (KEYSTATE_UP != s)
+    {
+        if (gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDERIGHT)
+        {
+            gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_SLIDERIGHT;
+        }
+        if (!gAgent.getRunning())
+        {
+            gAgent.setRunning();
+            gAgent.sendWalkRun(true);
+        }
+    }
+    else if (KEYSTATE_UP == s)
+    {
+        if (gAgent.mDoubleTapRunMode == LLAgent::DOUBLETAP_SLIDERIGHT)
+            gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_NONE;
+        gAgent.clearRunning();
+        gAgent.sendWalkRun(false);
+    }
+    agent_slide_right(s);
+    return true;
+}
+
+bool toggle_run(EKeystate s)
+{
+    if (KEYSTATE_DOWN != s) return true;
+    bool run = gAgent.getAlwaysRun();
+    if (run)
+    {
+        gAgent.clearAlwaysRun();
+        gAgent.clearRunning();
+    }
+    else
+    {
+        gAgent.setAlwaysRun();
+        gAgent.setRunning();
+    }
+    gAgent.sendWalkRun(!run);
+	return true;
+}
+
+bool toggle_sit(EKeystate s)
+{
+    if (KEYSTATE_DOWN != s) return true;
+    if (gAgent.isSitting())
+    {
+        gAgent.standUp();
+    }
+    else
+    {
+        gAgent.sitDown();
+    }
+	return true;
+}
+
+bool toggle_pause_media(EKeystate s) // analogue of play/pause button in top bar
+{
+    if (KEYSTATE_DOWN != s) return true;
+    bool pause = LLViewerMedia::isAnyMediaPlaying();
+    LLViewerMedia::setAllMediaPaused(pause);
+    return true;
+}
+
+bool toggle_enable_media(EKeystate s)
+{
+    if (KEYSTATE_DOWN != s) return true;
+    bool pause = LLViewerMedia::isAnyMediaPlaying() || LLViewerMedia::isAnyMediaShowing();
+    LLViewerMedia::setAllMediaEnabled(!pause);
+    return true;
+}
+
+bool walk_to(EKeystate s)
+{
+    if (KEYSTATE_DOWN != s) return true;
+    return LLToolPie::getInstance()->walkToClickedLocation();
+}
+
+bool teleport_to(EKeystate s)
+{
+    if (KEYSTATE_DOWN != s) return true;
+    return LLToolPie::getInstance()->teleportToClickedLocation();
+}
+
+bool toggle_voice(EKeystate s)
+{
+    if (KEYSTATE_DOWN != s) return true;
+    if (!LLAgent::isActionAllowed("speak")) return false;
+    LLVoiceClient::getInstance()->toggleUserPTTState();
+    return true;
+}
+
+bool voice_follow_key(EKeystate s)
+{
+    if (KEYSTATE_DOWN == s)
+    {
+        if (!LLAgent::isActionAllowed("speak")) return false;
+        LLVoiceClient::getInstance()->setUserPTTState(true);
+        return true;
+    }
+    else if (KEYSTATE_UP == s && LLVoiceClient::getInstance()->getUserPTTState())
+    {
+        LLVoiceClient::getInstance()->setUserPTTState(false);
+        return true;
+    }
+    return false;
+}
+
+bool agen_control_lbutton_handle(EKeystate s)
+{
+    switch (s)
+    {
+    case KEYSTATE_DOWN:
+        gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
+        break;
+    case KEYSTATE_UP:
+        gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
+        break;
+    default:
+        break;
+    }
+    return true;
+}
+
+#define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, ACTION);
+REGISTER_KEYBOARD_ACTION("jump", agent_jump);
+REGISTER_KEYBOARD_ACTION("push_down", agent_push_down);
+REGISTER_KEYBOARD_ACTION("push_forward", agent_push_forward);
+REGISTER_KEYBOARD_ACTION("push_backward", agent_push_backward);
+REGISTER_KEYBOARD_ACTION("look_up", agent_look_up);
+REGISTER_KEYBOARD_ACTION("look_down", agent_look_down);
+REGISTER_KEYBOARD_ACTION("toggle_fly", agent_toggle_fly);
+REGISTER_KEYBOARD_ACTION("turn_left", agent_turn_left);
+REGISTER_KEYBOARD_ACTION("turn_right", agent_turn_right);
+REGISTER_KEYBOARD_ACTION("slide_left", agent_slide_left);
+REGISTER_KEYBOARD_ACTION("slide_right", agent_slide_right);
+REGISTER_KEYBOARD_ACTION("spin_around_ccw", camera_spin_around_ccw);
+REGISTER_KEYBOARD_ACTION("spin_around_cw", camera_spin_around_cw);
+REGISTER_KEYBOARD_ACTION("spin_around_ccw_sitting", camera_spin_around_ccw_sitting);
+REGISTER_KEYBOARD_ACTION("spin_around_cw_sitting", camera_spin_around_cw_sitting);
+REGISTER_KEYBOARD_ACTION("spin_over", camera_spin_over);
+REGISTER_KEYBOARD_ACTION("spin_under", camera_spin_under);
+REGISTER_KEYBOARD_ACTION("spin_over_sitting", camera_spin_over_sitting);
+REGISTER_KEYBOARD_ACTION("spin_under_sitting", camera_spin_under_sitting);
+REGISTER_KEYBOARD_ACTION("move_forward", camera_move_forward);
+REGISTER_KEYBOARD_ACTION("move_backward", camera_move_backward);
+REGISTER_KEYBOARD_ACTION("move_forward_sitting", camera_move_forward_sitting);
+REGISTER_KEYBOARD_ACTION("move_backward_sitting", camera_move_backward_sitting);
+REGISTER_KEYBOARD_ACTION("pan_up", camera_pan_up);
+REGISTER_KEYBOARD_ACTION("pan_down", camera_pan_down);
+REGISTER_KEYBOARD_ACTION("pan_left", camera_pan_left);
+REGISTER_KEYBOARD_ACTION("pan_right", camera_pan_right);
+REGISTER_KEYBOARD_ACTION("pan_in", camera_pan_in);
+REGISTER_KEYBOARD_ACTION("pan_out", camera_pan_out);
+REGISTER_KEYBOARD_ACTION("move_forward_fast", camera_move_forward_fast);
+REGISTER_KEYBOARD_ACTION("move_backward_fast", camera_move_backward_fast);
+REGISTER_KEYBOARD_ACTION("edit_avatar_spin_ccw", edit_avatar_spin_ccw);
+REGISTER_KEYBOARD_ACTION("edit_avatar_spin_cw", edit_avatar_spin_cw);
+REGISTER_KEYBOARD_ACTION("edit_avatar_spin_over", edit_avatar_spin_over);
+REGISTER_KEYBOARD_ACTION("edit_avatar_spin_under", edit_avatar_spin_under);
+REGISTER_KEYBOARD_ACTION("edit_avatar_move_forward", edit_avatar_move_forward);
+REGISTER_KEYBOARD_ACTION("edit_avatar_move_backward", edit_avatar_move_backward);
+REGISTER_KEYBOARD_ACTION("stop_moving", stop_moving);
+REGISTER_KEYBOARD_ACTION("start_chat", start_chat);
+REGISTER_KEYBOARD_ACTION("start_gesture", start_gesture);
+REGISTER_KEYBOARD_ACTION("run_forward", run_forward);
+REGISTER_KEYBOARD_ACTION("run_backward", run_backward);
+REGISTER_KEYBOARD_ACTION("run_left", run_left);
+REGISTER_KEYBOARD_ACTION("run_right", run_right);
+REGISTER_KEYBOARD_ACTION("toggle_run", toggle_run);
+REGISTER_KEYBOARD_ACTION("toggle_sit", toggle_sit);
+REGISTER_KEYBOARD_ACTION("toggle_pause_media", toggle_pause_media);
+REGISTER_KEYBOARD_ACTION("toggle_enable_media", toggle_enable_media);
+REGISTER_KEYBOARD_ACTION("teleport_to", teleport_to);
+REGISTER_KEYBOARD_ACTION("walk_to", walk_to);
+REGISTER_KEYBOARD_ACTION("toggle_voice", toggle_voice);
+REGISTER_KEYBOARD_ACTION("voice_follow_key", voice_follow_key);
+#undef REGISTER_KEYBOARD_ACTION
+
+LLViewerInput::LLViewerInput()
+{
+    resetBindings();
+
+	for (S32 i = 0; i < KEY_COUNT; i++)
+	{
+		mKeyHandledByUI[i] = FALSE;
+    }
+    for (S32 i = 0; i < CLICK_COUNT; i++)
+    {
+        mMouseLevel[i] = MOUSE_STATE_SILENT;
+    }
+	// we want the UI to never see these keys so that they can always control the avatar/camera
+	for(KEY k = KEY_PAD_UP; k <= KEY_PAD_DIVIDE; k++) 
+	{
+		mKeysSkippedByUI.insert(k);	
+	}
+}
+
+// static
+BOOL LLViewerInput::modeFromString(const std::string& string, S32 *mode)
+{
+	if (string == "FIRST_PERSON")
+	{
+		*mode = MODE_FIRST_PERSON;
+		return TRUE;
+	}
+	else if (string == "THIRD_PERSON")
+	{
+		*mode = MODE_THIRD_PERSON;
+		return TRUE;
+	}
+	else if (string == "EDIT_AVATAR")
+	{
+		*mode = MODE_EDIT_AVATAR;
+		return TRUE;
+	}
+	else if (string == "SITTING")
+	{
+		*mode = MODE_SITTING;
+		return TRUE;
+	}
+	else
+	{
+		*mode = MODE_THIRD_PERSON;
+		return FALSE;
+	}
+}
+
+// static
+BOOL LLViewerInput::mouseFromString(const std::string& string, EMouseClickType *mode)
+{
+    if (string == "LMB")
+    {
+        *mode = CLICK_LEFT;
+        return TRUE;
+    }
+    else if (string == "Double LMB")
+    {
+        *mode = CLICK_DOUBLELEFT;
+        return TRUE;
+    }
+    else if (string == "MMB")
+    {
+        *mode = CLICK_MIDDLE;
+        return TRUE;
+    }
+    else if (string == "MB4")
+    {
+        *mode = CLICK_BUTTON4;
+        return TRUE;
+    }
+    else if (string == "MB5")
+    {
+        *mode = CLICK_BUTTON5;
+        return TRUE;
+    }
+    else
+    {
+        *mode = CLICK_NONE;
+        return FALSE;
+    }
+}
+
+BOOL LLViewerInput::handleKey(KEY translated_key, MASK translated_mask, BOOL repeated)
+{
+	// check for re-map
+	EKeyboardMode mode = gViewerInput.getMode();
+	U32 keyidx = (translated_mask<<16) | translated_key;
+	key_remap_t::iterator iter = mRemapKeys[mode].find(keyidx);
+	if (iter != mRemapKeys[mode].end())
+	{
+		translated_key = (iter->second) & 0xff;
+		translated_mask = (iter->second)>>16;
+	}
+
+	// No repeats of F-keys
+	BOOL repeatable_key = (translated_key < KEY_F1 || translated_key > KEY_F12);
+	if (!repeatable_key && repeated)
+	{
+		return FALSE;
+	}
+
+	LL_DEBUGS("UserInput") << "keydown -" << translated_key << "-" << LL_ENDL;
+	// skip skipped keys
+	if(mKeysSkippedByUI.find(translated_key) != mKeysSkippedByUI.end()) 
+	{
+		mKeyHandledByUI[translated_key] = FALSE;
+		LL_INFOS("KeyboardHandling") << "Key wasn't handled by UI!" << LL_ENDL;
+	}
+	else
+	{
+		// it is sufficient to set this value once per call to handlekey
+		// without clearing it, as it is only used in the subsequent call to scanKey
+		mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask); 
+		// mKeyHandledByUI is not what you think ... this indicates whether the UI has handled this keypress yet (any keypress)
+		// NOT whether some UI shortcut wishes to handle the keypress
+	  
+	}
+	return mKeyHandledByUI[translated_key];
+}
+
+BOOL LLViewerInput::handleKeyUp(KEY translated_key, MASK translated_mask)
+{
+	return gViewerWindow->handleKeyUp(translated_key, translated_mask);
+}
+
+BOOL LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name)
+{
+	S32 index;
+	typedef boost::function<bool(EKeystate)> function_t;
+	function_t function = NULL;
+	std::string name;
+
+	// Allow remapping of F2-F12
+	if (function_name[0] == 'F')
+	{
+		int c1 = function_name[1] - '0';
+		int c2 = function_name[2] ? function_name[2] - '0' : -1;
+		if (c1 >= 0 && c1 <= 9 && c2 >= -1 && c2 <= 9)
+		{
+			int idx = c1;
+			if (c2 >= 0)
+				idx = idx*10 + c2;
+			if (idx >=2 && idx <= 12)
+			{
+				U32 keyidx = ((mask<<16)|key);
+				(mRemapKeys[mode])[keyidx] = ((0<<16)|(KEY_F1+(idx-1)));
+				return TRUE;
+			}
+		}
+	}
+
+	// Not remapped, look for a function
+	
+	function_t* result = LLKeyboardActionRegistry::getValue(function_name);
+	if (result)
+	{
+		function = *result;
+	}
+
+	if (!function)
+	{
+		LL_ERRS() << "Can't bind key to function " << function_name << ", no function with this name found" << LL_ENDL;
+		return FALSE;
+	}
+
+	// check for duplicate first and overwrite
+    S32 size = mKeyBindings[mode].size();
+    for (index = 0; index < size; index++)
+    {
+        if (key == mKeyBindings[mode][index].mKey && mask == mKeyBindings[mode][index].mMask)
+            break;
+    }
+
+	if (mode >= MODE_COUNT)
+	{
+		LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL;
+		return FALSE;
+	}
+
+    LLKeyboardBinding bind;
+    bind.mKey = key;
+    bind.mMask = mask;
+    bind.mFunction = function;
+
+    mKeyBindings[mode].push_back(bind);
+
+	return TRUE;
+}
+
+BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const std::string& function_name)
+{
+    S32 index;
+    typedef boost::function<bool(EKeystate)> function_t;
+    function_t function = NULL;
+
+    function_t* result = LLKeyboardActionRegistry::getValue(function_name);
+    if (result)
+    {
+        function = *result;
+    }
+
+    if (!function)
+    {
+        LL_ERRS() << "Can't bind key to function " << function_name << ", no function with this name found" << LL_ENDL;
+        return FALSE;
+    }
+
+    // check for duplicate first and overwrite
+    S32 size = mMouseBindings[mode].size();
+    for (index = 0; index < size; index++)
+    {
+        if (mouse == mMouseBindings[mode][index].mMouse && mask == mMouseBindings[mode][index].mMask)
+            break;
+    }
+
+    if (mode >= MODE_COUNT)
+    {
+        LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL;
+        return FALSE;
+    }
+
+    LLMouseBinding bind;
+    bind.mMouse = mouse;
+    bind.mMask = mask;
+    bind.mFunction = function;
+
+    mMouseBindings[mode].push_back(bind);
+
+    return TRUE;
+}
+
+LLViewerInput::KeyBinding::KeyBinding()
+:	key("key"),
+	mouse("mouse"),
+	mask("mask"),
+	command("command")
+{}
+
+LLViewerInput::KeyMode::KeyMode()
+:	bindings("binding")
+{}
+
+LLViewerInput::Keys::Keys()
+:	first_person("first_person"),
+	third_person("third_person"),
+	sitting("sitting"),
+	edit_avatar("edit_avatar")
+{}
+
+void LLViewerInput::resetBindings()
+{
+    for (S32 i = 0; i < MODE_COUNT; i++)
+    {
+        mKeyBindings[i].clear();
+        mMouseBindings[i].clear();
+    }
+}
+
+S32 LLViewerInput::loadBindingsXML(const std::string& filename)
+{
+    resetBindings();
+
+	S32 binding_count = 0;
+	Keys keys;
+	LLSimpleXUIParser parser;
+
+	if (parser.readXUI(filename, keys) 
+		&& keys.validateBlock())
+	{
+		binding_count += loadBindingMode(keys.first_person, MODE_FIRST_PERSON);
+		binding_count += loadBindingMode(keys.third_person, MODE_THIRD_PERSON);
+		binding_count += loadBindingMode(keys.sitting, MODE_SITTING);
+		binding_count += loadBindingMode(keys.edit_avatar, MODE_EDIT_AVATAR);
+	}
+	return binding_count;
+}
+
+S32 count_masks(const MASK &mask)
+{
+    S32 res = 0;
+    if (mask & MASK_CONTROL)
+    {
+        res++;
+    }
+    if (mask & MASK_SHIFT)
+    {
+        res++;
+    }
+    if (mask & MASK_ALT)
+    {
+        res++;
+    }
+    return res;
+}
+
+bool compare_key_by_mask(LLKeyboardBinding i1, LLKeyboardBinding i2)
+{
+    return (count_masks(i1.mMask) > count_masks(i2.mMask));
+}
+
+bool compare_mouse_by_mask(LLMouseBinding i1, LLMouseBinding i2)
+{
+    return (count_masks(i1.mMask) > count_masks(i2.mMask));
+}
+
+S32 LLViewerInput::loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mode)
+{
+	S32 binding_count = 0;
+	for (LLInitParam::ParamIterator<KeyBinding>::const_iterator it = keymode.bindings.begin(), 
+			end_it = keymode.bindings.end();
+		it != end_it;
+		++it)
+	{
+        bool processed = false;
+        std::string key_str = it->key.getValue();
+        if (!key_str.empty() && key_str != "NONE")
+        {
+            KEY key;
+            LLKeyboard::keyFromString(key_str, &key);
+            if (key != KEY_NONE)
+            {
+                MASK mask;
+                LLKeyboard::maskFromString(it->mask, &mask);
+                bindKey(mode, key, mask, it->command);
+                processed = true;
+            }
+            else
+            {
+                LL_WARNS_ONCE() << "There might be issues in keybindings' file" << LL_ENDL;
+            }
+        }
+        if (!processed && it->mouse.isProvided() && !it->mouse.getValue().empty())
+        {
+            EMouseClickType mouse;
+            mouseFromString(it->mouse.getValue(), &mouse);
+            if (mouse != CLICK_NONE)
+            {
+                MASK mask;
+                LLKeyboard::maskFromString(it->mask, &mask);
+                bindMouse(mode, mouse, mask, it->command);
+                processed = true;
+            }
+            else
+            {
+                LL_WARNS_ONCE() << "There might be issues in keybindings' file" << LL_ENDL;
+            }
+        }
+        if (processed)
+        {
+            // total
+            binding_count++;
+        }
+    }
+
+    // sort lists by mask (so that Shift+W is executed before W, if both are assigned, but if Shift+W is not assigned W should be executed)
+    std::sort(mKeyBindings[mode].begin(), mKeyBindings[mode].end(), compare_key_by_mask);
+    std::sort(mMouseBindings[mode].begin(), mMouseBindings[mode].end(), compare_mouse_by_mask);
+
+	return binding_count;
+}
+
+EKeyboardMode LLViewerInput::getMode() const
+{
+	if ( gAgentCamera.cameraMouselook() )
+	{
+		return MODE_FIRST_PERSON;
+	}
+	else if ( gMorphView && gMorphView->getVisible())
+	{
+		return MODE_EDIT_AVATAR;
+	}
+	else if (isAgentAvatarValid() && gAgentAvatarp->isSitting())
+	{
+		return MODE_SITTING;
+	}
+	else
+	{
+		return MODE_THIRD_PERSON;
+	}
+}
+
+bool LLViewerInput::scanKey(const std::vector<LLKeyboardBinding> &binding,
+                               S32 binding_count,
+                               KEY key,
+                               MASK mask,
+                               BOOL key_down,
+                               BOOL key_up,
+                               BOOL key_level,
+                               bool repeat) const
+{
+	for (S32 i = 0; i < binding_count; i++)
+	{
+		if (binding[i].mKey == key)
+		{
+			if ((binding[i].mMask & mask) == binding[i].mMask)
+			{
+				bool res = false;
+				if (key_down && !repeat)
+				{
+					// ...key went down this frame, call function
+					res = binding[i].mFunction( KEYSTATE_DOWN );
+					return true;
+				}
+				else if (key_up)
+				{
+					// ...key went down this frame, call function
+					res = binding[i].mFunction( KEYSTATE_UP );
+				}
+				else if (key_level)
+				{
+					// ...key held down from previous frame
+					// Not windows, just call the function.
+					res = binding[i].mFunction( KEYSTATE_LEVEL );
+				}//if
+				// Key+Mask combinations are supposed to be unique, so we won't find anything else
+				return res;
+			}//if
+		}//if
+	}//for
+	return false;
+}
+
+// Called from scanKeyboard.
+bool LLViewerInput::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) const
+{
+	if (LLApp::isExiting())
+	{
+		return false;
+	}
+
+	S32 mode = getMode();
+	// Consider keyboard scanning as NOT mouse event. JC
+	MASK mask = gKeyboard->currentMask(FALSE);
+
+	if (mKeyHandledByUI[key])
+	{
+		return false;
+	}
+
+	// don't process key down on repeated keys
+	BOOL repeat = gKeyboard->getKeyRepeated(key);
+
+    bool res = scanKey(mKeyBindings[mode], mKeyBindings[mode].size(), key, mask, key_down, key_up, key_level, repeat);
+
+    if (!res && agent_control_lbutton.canHandle(CLICK_NONE, key, mask))
+    {
+        if (key_down && !repeat)
+        {
+            res = agen_control_lbutton_handle(KEYSTATE_DOWN);
+        }
+        if (key_up)
+        {
+            res = agen_control_lbutton_handle(KEYSTATE_UP);
+        }
+    }
+    return res;
+}
+
+BOOL LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down)
+{
+    BOOL handled = gViewerWindow->handleAnyMouseClick(window_impl, pos, mask, clicktype, down);
+
+    if (clicktype != CLICK_NONE)
+    {
+        // Special case
+        // If UI doesn't handle double click, LMB click is issued, so supres LMB 'down' when doubleclick is set
+        // handle !down as if we are handling doubleclick
+
+        bool double_click_sp = (clicktype == CLICK_LEFT
+            && (mMouseLevel[CLICK_DOUBLELEFT] != MOUSE_STATE_SILENT)
+            && mMouseLevel[CLICK_LEFT] == MOUSE_STATE_SILENT);
+        if (double_click_sp && !down)
+        {
+            // Process doubleclick instead
+            clicktype = CLICK_DOUBLELEFT;
+        }
+
+
+        if (double_click_sp && down)
+        {
+            // Consume click.
+            // Due to handling, double click that is not handled will be immediately followed by LMB click
+        }
+        // If UI handled 'down', it should handle 'up' as well
+        // If we handle 'down' not by UI, then we should handle 'up'/'level' regardless of UI
+        else if (handled)
+        {
+            // UI handled new 'down' so iterupt whatever state we were in.
+            if (mMouseLevel[clicktype] != MOUSE_STATE_SILENT)
+            {
+                if (mMouseLevel[clicktype] == MOUSE_STATE_DOWN)
+                {
+                    mMouseLevel[clicktype] = MOUSE_STATE_CLICK;
+                }
+                else
+                {
+                    mMouseLevel[clicktype] = MOUSE_STATE_UP;
+                }
+            }
+        }
+        else if (down)
+        {
+            if (mMouseLevel[clicktype] == MOUSE_STATE_DOWN)
+            {
+                // this is repeated hit (mouse does not repeat event until release)
+                // for now treat rapid clicking like mouse being held
+                mMouseLevel[clicktype] = MOUSE_STATE_LEVEL;
+            }
+            else
+            {
+                mMouseLevel[clicktype] = MOUSE_STATE_DOWN;
+            }
+        }
+        else if (mMouseLevel[clicktype] != MOUSE_STATE_SILENT)
+        {
+            // Released mouse key
+            if (mMouseLevel[clicktype] == MOUSE_STATE_DOWN)
+            {
+                mMouseLevel[clicktype] = MOUSE_STATE_CLICK;
+            }
+            else 
+            {
+                mMouseLevel[clicktype] = MOUSE_STATE_UP;
+            }
+        }
+    }
+
+    return handled;
+}
+
+bool LLViewerInput::scanMouse(const std::vector<LLMouseBinding> &binding, S32 binding_count, EMouseClickType mouse, MASK mask, EMouseState state) const
+{
+    for (S32 i = 0; i < binding_count; i++)
+    {
+        if (binding[i].mMouse == mouse && (binding[i].mMask & mask) == binding[i].mMask)
+        {
+            bool res = false;
+            switch (state)
+            {
+            case MOUSE_STATE_DOWN:
+                res = binding[i].mFunction(KEYSTATE_DOWN);
+                break;
+            case MOUSE_STATE_CLICK:
+                // Button went down and up in scope of single frame
+                // might not work best with some functions,
+                // but some function need specific states specifically
+                res = binding[i].mFunction(KEYSTATE_DOWN);
+                res |= binding[i].mFunction(KEYSTATE_UP);
+                break;
+            case MOUSE_STATE_LEVEL:
+                res = binding[i].mFunction(KEYSTATE_LEVEL);
+                break;
+            case MOUSE_STATE_UP:
+                res = binding[i].mFunction(KEYSTATE_UP);
+                break;
+            default:
+                break;
+            }
+            // Key+Mask combinations are supposed to be unique, no need to continue
+            return res;
+        }
+    }
+    return false;
+}
+
+// todo: this recods key, scanMouse() triggers functions with EKeystate
+bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const
+{
+    bool res = false;
+    S32 mode = getMode();
+    MASK mask = gKeyboard->currentMask(TRUE);
+    res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state);
+    // no user defined actions found or those actions can't handle the key/button, handle control if nessesary
+    if (!res && agent_control_lbutton.canHandle(click, KEY_NONE, mask))
+    {
+        switch (state)
+        {
+        case MOUSE_STATE_DOWN:
+            agen_control_lbutton_handle(KEYSTATE_DOWN);
+            res = true;
+            break;
+        case MOUSE_STATE_CLICK:
+            // might not work best with some functions,
+            // but some function need specific states too specifically
+            agen_control_lbutton_handle(KEYSTATE_DOWN);
+            agen_control_lbutton_handle(KEYSTATE_UP);
+            res = true;
+            break;
+        case MOUSE_STATE_UP:
+            agen_control_lbutton_handle(KEYSTATE_UP);
+            res = true;
+            break;
+        default:
+            break;
+        }
+    }
+    return res;
+}
+
+void LLViewerInput::scanMouse()
+{
+    for (S32 i = 0; i < CLICK_COUNT; i++)
+    {
+        if (mMouseLevel[i] != MOUSE_STATE_SILENT)
+        {
+            scanMouse((EMouseClickType)i, mMouseLevel[i]);
+            if (mMouseLevel[i] == MOUSE_STATE_DOWN)
+            {
+                // mouse doesn't support 'continued' state, so after handling, switch to LEVEL
+                mMouseLevel[i] = MOUSE_STATE_LEVEL;
+            }
+            else if (mMouseLevel[i] == MOUSE_STATE_UP || mMouseLevel[i] == MOUSE_STATE_CLICK)
+            {
+                mMouseLevel[i] = MOUSE_STATE_SILENT;
+            }
+        }
+    }
+}
diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h
new file mode 100644
index 0000000000000000000000000000000000000000..1fe55bd585f247b2c82d652d25e109dd8096485f
--- /dev/null
+++ b/indra/newview/llviewerinput.h
@@ -0,0 +1,177 @@
+/** 
+ * @file llviewerinput.h
+ * @brief LLViewerInput class header file
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+#ifndef LL_LLVIEWERINPUT_H
+#define LL_LLVIEWERINPUT_H
+
+#include "llkeyboard.h" // For EKeystate
+#include "llinitparam.h"
+
+const S32 MAX_KEY_BINDINGS = 128; // was 60
+
+class LLNamedFunction
+{
+public:
+	LLNamedFunction() : mFunction(NULL) { };
+	~LLNamedFunction() { };
+
+	std::string	mName;
+	LLKeyFunc	mFunction;
+};
+
+class LLKeyboardBinding
+{
+public:
+    KEY				mKey;
+    MASK			mMask;
+
+    LLKeyFunc		mFunction;
+};
+
+class LLMouseBinding
+{
+public:
+    EMouseClickType	mMouse;
+    MASK			mMask;
+
+    LLKeyFunc		mFunction;
+};
+
+
+typedef enum e_keyboard_mode
+{
+	MODE_FIRST_PERSON,
+	MODE_THIRD_PERSON,
+	MODE_EDIT_AVATAR,
+	MODE_SITTING,
+	MODE_COUNT
+} EKeyboardMode;
+
+class LLWindow;
+
+void bind_keyboard_functions();
+
+class LLViewerInput
+{
+public:
+	struct KeyBinding : public LLInitParam::Block<KeyBinding>
+	{
+		Mandatory<std::string>	key,
+								mask,
+								command;
+		Optional<std::string>	mouse; // Note, not mandatory for the sake of backward campatibility with keys.xml
+
+		KeyBinding();
+	};
+
+	struct KeyMode : public LLInitParam::Block<KeyMode>
+	{
+		Multiple<KeyBinding>		bindings;
+
+		KeyMode();
+	};
+
+	struct Keys : public LLInitParam::Block<Keys>
+	{
+		Optional<KeyMode>	first_person,
+							third_person,
+							sitting,
+							edit_avatar;
+
+		Keys();
+	};
+
+	LLViewerInput();
+
+	BOOL			handleKey(KEY key, MASK mask, BOOL repeated);
+	BOOL			handleKeyUp(KEY key, MASK mask);
+
+	S32				loadBindingsXML(const std::string& filename);										// returns number bound, 0 on error
+	EKeyboardMode	getMode() const;
+
+	static BOOL		modeFromString(const std::string& string, S32 *mode);			// False on failure
+	static BOOL		mouseFromString(const std::string& string, EMouseClickType *mode);// False on failure
+
+    bool            scanKey(KEY key,
+                            BOOL key_down,
+                            BOOL key_up,
+                            BOOL key_level) const;
+
+    // handleMouse() records state, scanMouse() goes through states, scanMouse(click) processes individual saved states after UI is done with them
+    BOOL            handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
+    void            scanMouse();
+
+private:
+    bool            scanKey(const std::vector<LLKeyboardBinding> &binding,
+                            S32 binding_count,
+                            KEY key,
+                            MASK mask,
+                            BOOL key_down,
+                            BOOL key_up,
+                            BOOL key_level,
+                            bool repeat) const;
+
+    enum EMouseState
+    {
+        MOUSE_STATE_DOWN, // key down this frame
+        MOUSE_STATE_CLICK, // key went up and down in scope of same frame
+        MOUSE_STATE_LEVEL, // clicked again fast, or never released
+        MOUSE_STATE_UP, // went up this frame
+        MOUSE_STATE_SILENT // notified about 'up', do not notify again
+    };
+    bool			scanMouse(EMouseClickType click, EMouseState state) const;
+    bool            scanMouse(const std::vector<LLMouseBinding> &binding,
+                          S32 binding_count,
+                          EMouseClickType mouse,
+                          MASK mask,
+                          EMouseState state) const;
+
+    S32				loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mode);
+    BOOL			bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name);
+    BOOL			bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const std::string& function_name);
+    void			resetBindings();
+
+	// Hold all the ugly stuff torn out to make LLKeyboard non-viewer-specific here
+
+    // TODO: at some point it is better to remake this, especially keyaboard part
+    // would be much better to send to functions actual state of the button than
+    // to send what we think function wants based on collection of bools (mKeyRepeated, mKeyLevel, mKeyDown)
+    std::vector<LLKeyboardBinding>	mKeyBindings[MODE_COUNT];
+    std::vector<LLMouseBinding>		mMouseBindings[MODE_COUNT];
+
+	typedef std::map<U32, U32> key_remap_t;
+	key_remap_t		mRemapKeys[MODE_COUNT];
+	std::set<KEY>	mKeysSkippedByUI;
+	BOOL			mKeyHandledByUI[KEY_COUNT];		// key processed successfully by UI
+
+    // This is indentical to what llkeyboard does (mKeyRepeated, mKeyLevel, mKeyDown e t c),
+    // just instead of remembering individually as bools,  we record state as enum
+    EMouseState		mMouseLevel[CLICK_COUNT];	// records of key state
+};
+
+extern LLViewerInput gViewerInput;
+
+#endif // LL_LLVIEWERINPUT_H
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 9d7da115ac8b4afd9b74112b5983facf13602b41..6ff02ffe66b3999b13c011993e35e31f2376b5ee 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1745,7 +1745,7 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge,
 {
 	std::string type_name = userdata.asString();
 	
-	if (("inbox" == type_name) || ("outbox" == type_name) || ("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
+	if (("inbox" == type_name) || ("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
 	{
 		LLFolderType::EType preferred_type = LLFolderType::lookup(type_name);
 
diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp
deleted file mode 100644
index e930eb20d3cf185affae53bb182d622dc0a0b2d3..0000000000000000000000000000000000000000
--- a/indra/newview/llviewerkeyboard.cpp
+++ /dev/null
@@ -1,1032 +0,0 @@
-/** 
- * @file llviewerkeyboard.cpp
- * @brief LLViewerKeyboard class implementation
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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 "llviewerprecompiledheaders.h"
-
-#include "llappviewer.h"
-#include "llfloaterreg.h"
-#include "llviewerkeyboard.h"
-#include "llmath.h"
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "llfloaterimnearbychat.h"
-#include "llviewercontrol.h"
-#include "llfocusmgr.h"
-#include "llmorphview.h"
-#include "llmoveview.h"
-#include "lltoolfocus.h"
-#include "llviewerwindow.h"
-#include "llvoavatarself.h"
-#include "llfloatercamera.h"
-#include "llinitparam.h"
-
-//
-// Constants
-//
-
-const F32 FLY_TIME = 0.5f;
-const F32 FLY_FRAMES = 4;
-
-const F32 NUDGE_TIME = 0.25f;  // in seconds
-const S32 NUDGE_FRAMES = 2;
-const F32 ORBIT_NUDGE_RATE = 0.05f;  // fraction of normal speed
-
-struct LLKeyboardActionRegistry 
-:	public LLRegistrySingleton<std::string, boost::function<void (EKeystate keystate)>, LLKeyboardActionRegistry>
-{
-	LLSINGLETON_EMPTY_CTOR(LLKeyboardActionRegistry);
-};
-
-LLViewerKeyboard gViewerKeyboard;
-
-void agent_jump( EKeystate s )
-{
-	static BOOL first_fly_attempt(TRUE);
-	if (KEYSTATE_UP == s)
-	{
-		first_fly_attempt = TRUE;
-		return;
-	}
-	F32 time = gKeyboard->getCurKeyElapsedTime();
-	S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
-
-	if( time < FLY_TIME 
-		|| frame_count <= FLY_FRAMES 
-		|| gAgent.upGrabbed()
-		|| !gSavedSettings.getBOOL("AutomaticFly"))
-	{
-		gAgent.moveUp(1);
-	}
-	else
-	{
-		gAgent.setFlying(TRUE, first_fly_attempt);
-		first_fly_attempt = FALSE;
-		gAgent.moveUp(1);
-	}
-}
-
-void agent_push_down( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgent.moveUp(-1);
-}
-
-static void agent_check_temporary_run(LLAgent::EDoubleTapRunMode mode)
-{
-	if (gAgent.mDoubleTapRunMode == mode &&
-		gAgent.getRunning() &&
-		!gAgent.getAlwaysRun())
-	{
-		// Turn off temporary running.
-		gAgent.clearRunning();
-		gAgent.sendWalkRun(gAgent.getRunning());
-	}
-}
-
-static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode mode)
-{
-	if (KEYSTATE_UP == s)
-	{
-		// Note: in case shift is already released, slide left/right run
-		// will be released in agent_turn_left()/agent_turn_right()
-		agent_check_temporary_run(mode);
-	}
-	else if (gSavedSettings.getBOOL("AllowTapTapHoldRun") &&
-		 KEYSTATE_DOWN == s &&
-		 !gAgent.getRunning())
-	{
-		if (gAgent.mDoubleTapRunMode == mode &&
-		    gAgent.mDoubleTapRunTimer.getElapsedTimeF32() < NUDGE_TIME)
-		{
-			// Same walk-key was pushed again quickly; this is a
-			// double-tap so engage temporary running.
-			gAgent.setRunning();
-			gAgent.sendWalkRun(gAgent.getRunning());
-		}
-
-		// Pressing any walk-key resets the double-tap timer
-		gAgent.mDoubleTapRunTimer.reset();
-		gAgent.mDoubleTapRunMode = mode;
-	}
-}
-
-static void agent_push_forwardbackward( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
-{
-	agent_handle_doubletap_run(s, mode);
-	if (KEYSTATE_UP == s) return;
-
-	F32 time = gKeyboard->getCurKeyElapsedTime();
-	S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
-
-	if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
-	{
-		gAgent.moveAtNudge(direction);
-	}
-	else
-	{
-		gAgent.moveAt(direction);
-	}
-}
-
-void camera_move_forward( EKeystate s );
-
-void agent_push_forward( EKeystate s )
-{
-	if(gAgent.isMovementLocked()) return;
-
-	//in free camera control mode we need to intercept keyboard events for avatar movements
-	if (LLFloaterCamera::inFreeCameraMode())
-	{
-		camera_move_forward(s);
-	}
-	else
-	{
-		agent_push_forwardbackward(s, 1, LLAgent::DOUBLETAP_FORWARD);
-	}
-}
-
-void camera_move_backward( EKeystate s );
-
-void agent_push_backward( EKeystate s )
-{
-	if(gAgent.isMovementLocked()) return;
-
-	//in free camera control mode we need to intercept keyboard events for avatar movements
-	if (LLFloaterCamera::inFreeCameraMode())
-	{
-		camera_move_backward(s);
-	}
-	else if (!gAgent.backwardGrabbed() && gAgentAvatarp->isSitting() && gSavedSettings.getBOOL("LeaveMouselook"))
-	{
-		gAgentCamera.changeCameraToThirdPerson();
-	}
-	else
-	{
-		agent_push_forwardbackward(s, -1, LLAgent::DOUBLETAP_BACKWARD);
-	}
-}
-
-static void agent_slide_leftright( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
-{
-	agent_handle_doubletap_run(s, mode);
-	if( KEYSTATE_UP == s ) return;
-	F32 time = gKeyboard->getCurKeyElapsedTime();
-	S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
-
-	if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
-	{
-		gAgent.moveLeftNudge(direction);
-	}
-	else
-	{
-		gAgent.moveLeft(direction);
-	}
-}
-
-
-void agent_slide_left( EKeystate s )
-{
-	if(gAgent.isMovementLocked()) return;
-	agent_slide_leftright(s, 1, LLAgent::DOUBLETAP_SLIDELEFT);
-}
-
-
-void agent_slide_right( EKeystate s )
-{
-	if(gAgent.isMovementLocked()) return;
-	agent_slide_leftright(s, -1, LLAgent::DOUBLETAP_SLIDERIGHT);
-}
-
-void camera_spin_around_cw( EKeystate s );
-
-void agent_turn_left( EKeystate s )
-{
-	//in free camera control mode we need to intercept keyboard events for avatar movements
-	if (LLFloaterCamera::inFreeCameraMode())
-	{
-		camera_spin_around_cw(s);
-		return;
-	}
-
-	if(gAgent.isMovementLocked()) return;
-
-	if (LLToolCamera::getInstance()->mouseSteerMode())
-	{
-		agent_slide_left(s);
-	}
-	else
-	{
-		if (KEYSTATE_UP == s)
-		{
-			// Check temporary running. In case user released 'left' key with shift already released.
-			agent_check_temporary_run(LLAgent::DOUBLETAP_SLIDELEFT);
-			return;
-		}
-		F32 time = gKeyboard->getCurKeyElapsedTime();
-		gAgent.moveYaw( LLFloaterMove::getYawRate( time ) );
-	}
-}
-
-void camera_spin_around_ccw( EKeystate s );
-
-void agent_turn_right( EKeystate s )
-{
-	//in free camera control mode we need to intercept keyboard events for avatar movements
-	if (LLFloaterCamera::inFreeCameraMode())
-	{
-		camera_spin_around_ccw(s);
-		return;
-	}
-
-	if(gAgent.isMovementLocked()) return;
-
-	if (LLToolCamera::getInstance()->mouseSteerMode())
-	{
-		agent_slide_right(s);
-	}
-	else
-	{
-		if (KEYSTATE_UP == s)
-		{
-			// Check temporary running. In case user released 'right' key with shift already released.
-			agent_check_temporary_run(LLAgent::DOUBLETAP_SLIDERIGHT);
-			return;
-		}
-		F32 time = gKeyboard->getCurKeyElapsedTime();
-		gAgent.moveYaw( -LLFloaterMove::getYawRate( time ) );
-	}
-}
-
-void agent_look_up( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgent.movePitch(-1);
-	//gAgent.rotate(-2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
-}
-
-
-void agent_look_down( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgent.movePitch(1);
-	//gAgent.rotate(2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
-}
-
-void agent_toggle_fly( EKeystate s )
-{
-	// Only catch the edge
-	if (KEYSTATE_DOWN == s )
-	{
-		LLAgent::toggleFlying();
-	}
-}
-
-F32 get_orbit_rate()
-{
-	F32 time = gKeyboard->getCurKeyElapsedTime();
-	if( time < NUDGE_TIME )
-	{
-		F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME;
-		//LL_INFOS() << rate << LL_ENDL;
-		return rate;
-	}
-	else
-	{
-		return 1;
-	}
-}
-
-void camera_spin_around_ccw( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
-}
-
-
-void camera_spin_around_cw( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setOrbitRightKey( get_orbit_rate() );
-}
-
-void camera_spin_around_ccw_sitting( EKeystate s )
-{
-	if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDERIGHT ) return;
-	if (gAgent.rotateGrabbed() || gAgentCamera.sitCameraEnabled() || gAgent.getRunning())
-	{
-		//send keystrokes, but do not change camera
-		agent_turn_right(s);
-	}
-	else
-	{
-		//change camera but do not send keystrokes
-		gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
-	}
-}
-
-
-void camera_spin_around_cw_sitting( EKeystate s )
-{
-	if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDELEFT ) return;
-	if (gAgent.rotateGrabbed() || gAgentCamera.sitCameraEnabled() || gAgent.getRunning())
-	{
-		//send keystrokes, but do not change camera
-		agent_turn_left(s);
-	}
-	else
-	{
-		//change camera but do not send keystrokes
-		gAgentCamera.setOrbitRightKey( get_orbit_rate() );
-	}
-}
-
-
-void camera_spin_over( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setOrbitUpKey( get_orbit_rate() );
-}
-
-
-void camera_spin_under( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setOrbitDownKey( get_orbit_rate() );
-}
-
-void camera_spin_over_sitting( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	if (gAgent.upGrabbed() || gAgentCamera.sitCameraEnabled())
-	{
-		//send keystrokes, but do not change camera
-		agent_jump(s);
-	}
-	else
-	{
-		//change camera but do not send keystrokes
-		gAgentCamera.setOrbitUpKey( get_orbit_rate() );
-	}
-}
-
-
-void camera_spin_under_sitting( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	if (gAgent.downGrabbed() || gAgentCamera.sitCameraEnabled())
-	{
-		//send keystrokes, but do not change camera
-		agent_push_down(s);
-	}
-	else
-	{
-		//change camera but do not send keystrokes
-		gAgentCamera.setOrbitDownKey( get_orbit_rate() );
-	}
-}
-
-void camera_move_forward( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setOrbitInKey( get_orbit_rate() );
-}
-
-
-void camera_move_backward( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setOrbitOutKey( get_orbit_rate() );
-}
-
-void camera_move_forward_sitting( EKeystate s )
-{
-	if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_FORWARD ) return;
-	if (gAgent.forwardGrabbed() || gAgentCamera.sitCameraEnabled() || (gAgent.getRunning() && !gAgent.getAlwaysRun()))
-	{
-		agent_push_forward(s);
-	}
-	else
-	{
-		gAgentCamera.setOrbitInKey( get_orbit_rate() );
-	}
-}
-
-
-void camera_move_backward_sitting( EKeystate s )
-{
-	if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_BACKWARD ) return;
-
-	if (gAgent.backwardGrabbed() || gAgentCamera.sitCameraEnabled() || (gAgent.getRunning() && !gAgent.getAlwaysRun()))
-	{
-		agent_push_backward(s);
-	}
-	else
-	{
-		gAgentCamera.setOrbitOutKey( get_orbit_rate() );
-	}
-}
-
-void camera_pan_up( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setPanUpKey( get_orbit_rate() );
-}
-
-void camera_pan_down( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setPanDownKey( get_orbit_rate() );
-}
-
-void camera_pan_left( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setPanLeftKey( get_orbit_rate() );
-}
-
-void camera_pan_right( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setPanRightKey( get_orbit_rate() );
-}
-
-void camera_pan_in( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setPanInKey( get_orbit_rate() );
-}
-
-void camera_pan_out( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setPanOutKey( get_orbit_rate() );
-}
-
-void camera_move_forward_fast( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setOrbitInKey(2.5f);
-}
-
-void camera_move_backward_fast( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gAgentCamera.unlockView();
-	gAgentCamera.setOrbitOutKey(2.5f);
-}
-
-
-void edit_avatar_spin_ccw( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gMorphView->setCameraDrivenByKeys( TRUE );
-	gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
-	//gMorphView->orbitLeft( get_orbit_rate() );
-}
-
-
-void edit_avatar_spin_cw( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gMorphView->setCameraDrivenByKeys( TRUE );
-	gAgentCamera.setOrbitRightKey( get_orbit_rate() );
-	//gMorphView->orbitRight( get_orbit_rate() );
-}
-
-void edit_avatar_spin_over( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gMorphView->setCameraDrivenByKeys( TRUE );
-	gAgentCamera.setOrbitUpKey( get_orbit_rate() );
-	//gMorphView->orbitUp( get_orbit_rate() );
-}
-
-
-void edit_avatar_spin_under( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gMorphView->setCameraDrivenByKeys( TRUE );
-	gAgentCamera.setOrbitDownKey( get_orbit_rate() );
-	//gMorphView->orbitDown( get_orbit_rate() );
-}
-
-void edit_avatar_move_forward( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gMorphView->setCameraDrivenByKeys( TRUE );
-	gAgentCamera.setOrbitInKey( get_orbit_rate() );
-	//gMorphView->orbitIn();
-}
-
-
-void edit_avatar_move_backward( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	gMorphView->setCameraDrivenByKeys( TRUE );
-	gAgentCamera.setOrbitOutKey( get_orbit_rate() );
-	//gMorphView->orbitOut();
-}
-
-void stop_moving( EKeystate s )
-{
-	if( KEYSTATE_UP == s  ) return;
-	// stop agent
-	gAgent.setControlFlags(AGENT_CONTROL_STOP);
-
-	// cancel autopilot
-	gAgent.stopAutoPilot();
-}
-
-void start_chat( EKeystate s )
-{
-    if (LLAppViewer::instance()->quitRequested())
-    {
-        return; // can't talk, gotta go, kthxbye!
-    }
-    
-	// start chat
-	LLFloaterIMNearbyChat::startChat(NULL);
-}
-
-void start_gesture( EKeystate s )
-{
-	LLUICtrl* focus_ctrlp = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
-	if (KEYSTATE_UP == s &&
-		! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))
-	{
- 		if ((LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->getCurrentChat().empty())
- 		{
- 			// No existing chat in chat editor, insert '/'
- 			LLFloaterIMNearbyChat::startChat("/");
- 		}
- 		else
- 		{
- 			// Don't overwrite existing text in chat editor
- 			LLFloaterIMNearbyChat::startChat(NULL);
- 		}
-	}
-}
-
-#define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, ACTION);
-REGISTER_KEYBOARD_ACTION("jump", agent_jump);
-REGISTER_KEYBOARD_ACTION("push_down", agent_push_down);
-REGISTER_KEYBOARD_ACTION("push_forward", agent_push_forward);
-REGISTER_KEYBOARD_ACTION("push_backward", agent_push_backward);
-REGISTER_KEYBOARD_ACTION("look_up", agent_look_up);
-REGISTER_KEYBOARD_ACTION("look_down", agent_look_down);
-REGISTER_KEYBOARD_ACTION("toggle_fly", agent_toggle_fly);
-REGISTER_KEYBOARD_ACTION("turn_left", agent_turn_left);
-REGISTER_KEYBOARD_ACTION("turn_right", agent_turn_right);
-REGISTER_KEYBOARD_ACTION("slide_left", agent_slide_left);
-REGISTER_KEYBOARD_ACTION("slide_right", agent_slide_right);
-REGISTER_KEYBOARD_ACTION("spin_around_ccw", camera_spin_around_ccw);
-REGISTER_KEYBOARD_ACTION("spin_around_cw", camera_spin_around_cw);
-REGISTER_KEYBOARD_ACTION("spin_around_ccw_sitting", camera_spin_around_ccw_sitting);
-REGISTER_KEYBOARD_ACTION("spin_around_cw_sitting", camera_spin_around_cw_sitting);
-REGISTER_KEYBOARD_ACTION("spin_over", camera_spin_over);
-REGISTER_KEYBOARD_ACTION("spin_under", camera_spin_under);
-REGISTER_KEYBOARD_ACTION("spin_over_sitting", camera_spin_over_sitting);
-REGISTER_KEYBOARD_ACTION("spin_under_sitting", camera_spin_under_sitting);
-REGISTER_KEYBOARD_ACTION("move_forward", camera_move_forward);
-REGISTER_KEYBOARD_ACTION("move_backward", camera_move_backward);
-REGISTER_KEYBOARD_ACTION("move_forward_sitting", camera_move_forward_sitting);
-REGISTER_KEYBOARD_ACTION("move_backward_sitting", camera_move_backward_sitting);
-REGISTER_KEYBOARD_ACTION("pan_up", camera_pan_up);
-REGISTER_KEYBOARD_ACTION("pan_down", camera_pan_down);
-REGISTER_KEYBOARD_ACTION("pan_left", camera_pan_left);
-REGISTER_KEYBOARD_ACTION("pan_right", camera_pan_right);
-REGISTER_KEYBOARD_ACTION("pan_in", camera_pan_in);
-REGISTER_KEYBOARD_ACTION("pan_out", camera_pan_out);
-REGISTER_KEYBOARD_ACTION("move_forward_fast", camera_move_forward_fast);
-REGISTER_KEYBOARD_ACTION("move_backward_fast", camera_move_backward_fast);
-REGISTER_KEYBOARD_ACTION("edit_avatar_spin_ccw", edit_avatar_spin_ccw);
-REGISTER_KEYBOARD_ACTION("edit_avatar_spin_cw", edit_avatar_spin_cw);
-REGISTER_KEYBOARD_ACTION("edit_avatar_spin_over", edit_avatar_spin_over);
-REGISTER_KEYBOARD_ACTION("edit_avatar_spin_under", edit_avatar_spin_under);
-REGISTER_KEYBOARD_ACTION("edit_avatar_move_forward", edit_avatar_move_forward);
-REGISTER_KEYBOARD_ACTION("edit_avatar_move_backward", edit_avatar_move_backward);
-REGISTER_KEYBOARD_ACTION("stop_moving", stop_moving);
-REGISTER_KEYBOARD_ACTION("start_chat", start_chat);
-REGISTER_KEYBOARD_ACTION("start_gesture", start_gesture);
-#undef REGISTER_KEYBOARD_ACTION
-
-LLViewerKeyboard::LLViewerKeyboard()
-{
-	for (S32 i = 0; i < MODE_COUNT; i++)
-	{
-		mBindingCount[i] = 0;
-	}
-
-	for (S32 i = 0; i < KEY_COUNT; i++)
-	{
-		mKeyHandledByUI[i] = FALSE;
-	}
-	// we want the UI to never see these keys so that they can always control the avatar/camera
-	for(KEY k = KEY_PAD_UP; k <= KEY_PAD_DIVIDE; k++) 
-	{
-		mKeysSkippedByUI.insert(k);	
-	}
-}
-
-BOOL LLViewerKeyboard::modeFromString(const std::string& string, S32 *mode)
-{
-	if (string == "FIRST_PERSON")
-	{
-		*mode = MODE_FIRST_PERSON;
-		return TRUE;
-	}
-	else if (string == "THIRD_PERSON")
-	{
-		*mode = MODE_THIRD_PERSON;
-		return TRUE;
-	}
-	else if (string == "EDIT")
-	{
-		*mode = MODE_EDIT;
-		return TRUE;
-	}
-	else if (string == "EDIT_AVATAR")
-	{
-		*mode = MODE_EDIT_AVATAR;
-		return TRUE;
-	}
-	else if (string == "SITTING")
-	{
-		*mode = MODE_SITTING;
-		return TRUE;
-	}
-	else
-	{
-		*mode = MODE_THIRD_PERSON;
-		return FALSE;
-	}
-}
-
-BOOL LLViewerKeyboard::handleKey(KEY translated_key,  MASK translated_mask, BOOL repeated)
-{
-	// check for re-map
-	EKeyboardMode mode = gViewerKeyboard.getMode();
-	U32 keyidx = (translated_mask<<16) | translated_key;
-	key_remap_t::iterator iter = mRemapKeys[mode].find(keyidx);
-	if (iter != mRemapKeys[mode].end())
-	{
-		translated_key = (iter->second) & 0xff;
-		translated_mask = (iter->second)>>16;
-	}
-
-	// No repeats of F-keys
-	BOOL repeatable_key = (translated_key < KEY_F1 || translated_key > KEY_F12);
-	if (!repeatable_key && repeated)
-	{
-		return FALSE;
-	}
-
-	LL_DEBUGS("UserInput") << "keydown -" << translated_key << "-" << LL_ENDL;
-	// skip skipped keys
-	if(mKeysSkippedByUI.find(translated_key) != mKeysSkippedByUI.end()) 
-	{
-		mKeyHandledByUI[translated_key] = FALSE;
-		LL_INFOS("KeyboardHandling") << "Key wasn't handled by UI!" << LL_ENDL;
-	}
-	else
-	{
-		// it is sufficient to set this value once per call to handlekey
-		// without clearing it, as it is only used in the subsequent call to scanKey
-		mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask); 
-		// mKeyHandledByUI is not what you think ... this indicates whether the UI has handled this keypress yet (any keypress)
-		// NOT whether some UI shortcut wishes to handle the keypress
-	  
-	}
-	return mKeyHandledByUI[translated_key];
-}
-
-BOOL LLViewerKeyboard::handleKeyUp(KEY translated_key, MASK translated_mask)
-{
-	return gViewerWindow->handleKeyUp(translated_key, translated_mask);
-}
-
-BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name)
-{
-	S32 index;
-	typedef boost::function<void(EKeystate)> function_t;
-	function_t function = NULL;
-	std::string name;
-
-	// Allow remapping of F2-F12
-	if (function_name[0] == 'F')
-	{
-		int c1 = function_name[1] - '0';
-		int c2 = function_name[2] ? function_name[2] - '0' : -1;
-		if (c1 >= 0 && c1 <= 9 && c2 >= -1 && c2 <= 9)
-		{
-			int idx = c1;
-			if (c2 >= 0)
-				idx = idx*10 + c2;
-			if (idx >=2 && idx <= 12)
-			{
-				U32 keyidx = ((mask<<16)|key);
-				(mRemapKeys[mode])[keyidx] = ((0<<16)|(KEY_F1+(idx-1)));
-				return TRUE;
-			}
-		}
-	}
-
-	// Not remapped, look for a function
-	
-	function_t* result = LLKeyboardActionRegistry::getValue(function_name);
-	if (result)
-	{
-		function = *result;
-	}
-
-	if (!function)
-	{
-		LL_ERRS() << "Can't bind key to function " << function_name << ", no function with this name found" << LL_ENDL;
-		return FALSE;
-	}
-
-	// check for duplicate first and overwrite
-	for (index = 0; index < mBindingCount[mode]; index++)
-	{
-		if (key == mBindings[mode][index].mKey && mask == mBindings[mode][index].mMask)
-			break;
-	}
-
-	if (index >= MAX_KEY_BINDINGS)
-	{
-		LL_ERRS() << "LLKeyboard::bindKey() - too many keys for mode " << mode << LL_ENDL;
-		return FALSE;
-	}
-
-	if (mode >= MODE_COUNT)
-	{
-		LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL;
-		return FALSE;
-	}
-
-	mBindings[mode][index].mKey = key;
-	mBindings[mode][index].mMask = mask;
-	mBindings[mode][index].mFunction = function;
-
-	if (index == mBindingCount[mode])
-		mBindingCount[mode]++;
-
-	return TRUE;
-}
-
-LLViewerKeyboard::KeyBinding::KeyBinding()
-:	key("key"),
-	mask("mask"),
-	command("command")
-{}
-
-LLViewerKeyboard::KeyMode::KeyMode(EKeyboardMode _mode)
-:	bindings("binding"),
-	mode(_mode)
-{}
-
-LLViewerKeyboard::Keys::Keys()
-:	first_person("first_person", KeyMode(MODE_FIRST_PERSON)),
-	third_person("third_person", KeyMode(MODE_THIRD_PERSON)),
-	edit("edit", KeyMode(MODE_EDIT)),
-	sitting("sitting", KeyMode(MODE_SITTING)),
-	edit_avatar("edit_avatar", KeyMode(MODE_EDIT_AVATAR))
-{}
-
-S32 LLViewerKeyboard::loadBindingsXML(const std::string& filename)
-{
-	S32 binding_count = 0;
-	Keys keys;
-	LLSimpleXUIParser parser;
-
-	if (parser.readXUI(filename, keys) 
-		&& keys.validateBlock())
-	{
-		binding_count += loadBindingMode(keys.first_person);
-		binding_count += loadBindingMode(keys.third_person);
-		binding_count += loadBindingMode(keys.edit);
-		binding_count += loadBindingMode(keys.sitting);
-		binding_count += loadBindingMode(keys.edit_avatar);
-	}
-	return binding_count;
-}
-
-S32 LLViewerKeyboard::loadBindingMode(const LLViewerKeyboard::KeyMode& keymode)
-{
-	S32 binding_count = 0;
-	for (LLInitParam::ParamIterator<KeyBinding>::const_iterator it = keymode.bindings.begin(), 
-			end_it = keymode.bindings.end();
-		it != end_it;
-		++it)
-	{
-		KEY key;
-		MASK mask;
-		LLKeyboard::keyFromString(it->key, &key);
-		LLKeyboard::maskFromString(it->mask, &mask);
-		bindKey(keymode.mode, key, mask, it->command);
-		binding_count++;
-	}
-
-	return binding_count;
-}
-
-S32 LLViewerKeyboard::loadBindings(const std::string& filename)
-{
-	LLFILE *fp;
-	const S32 BUFFER_SIZE = 2048;
-	char buffer[BUFFER_SIZE];	/* Flawfinder: ignore */
-	// *NOTE: This buffer size is hard coded into scanf() below.
-	char mode_string[MAX_STRING] = "";	/* Flawfinder: ignore */
-	char key_string[MAX_STRING] = "";	/* Flawfinder: ignore */
-	char mask_string[MAX_STRING] = "";	/* Flawfinder: ignore */
-	char function_string[MAX_STRING] = "";	/* Flawfinder: ignore */
-	S32 mode = MODE_THIRD_PERSON;
-	KEY key = 0;
-	MASK mask = 0;
-	S32 tokens_read;
-	S32 binding_count = 0;
-	S32 line_count = 0;
-
-	if(filename.empty())
-	{
-		LL_ERRS() << " No filename specified" << LL_ENDL;
-		return 0;
-	}
-
-	fp = LLFile::fopen(filename, "r");
-
-	if (!fp)
-	{
-		return 0;
-	}
-
-
-	while (!feof(fp))
-	{
-		line_count++;
-		if (!fgets(buffer, BUFFER_SIZE, fp))
-			break;
-
-		// skip over comments, blank lines
-		if (buffer[0] == '#' || buffer[0] == '\n') continue;
-
-		// grab the binding strings
-		tokens_read = sscanf(	/* Flawfinder: ignore */
-			buffer,
-			"%254s %254s %254s %254s",
-			mode_string,
-			key_string,
-			mask_string,
-			function_string);
-
-		if (tokens_read == EOF)
-		{
-			LL_INFOS() << "Unexpected end-of-file at line " << line_count << " of key binding file " << filename << LL_ENDL;
-			fclose(fp);
-			return 0;
-		}
-		else if (tokens_read < 4)
-		{
-			LL_INFOS() << "Can't read line " << line_count << " of key binding file " << filename << LL_ENDL;
-			continue;
-		}
-
-		// convert mode
-		if (!modeFromString(mode_string, &mode))
-		{
-			LL_INFOS() << "Unknown mode on line " << line_count << " of key binding file " << filename << LL_ENDL;
-			LL_INFOS() << "Mode must be one of FIRST_PERSON, THIRD_PERSON, EDIT, EDIT_AVATAR" << LL_ENDL;
-			continue;
-		}
-
-		// convert key
-		if (!LLKeyboard::keyFromString(key_string, &key))
-		{
-			LL_INFOS() << "Can't interpret key on line " << line_count << " of key binding file " << filename << LL_ENDL;
-			continue;
-		}
-
-		// convert mask
-		if (!LLKeyboard::maskFromString(mask_string, &mask))
-		{
-			LL_INFOS() << "Can't interpret mask on line " << line_count << " of key binding file " << filename << LL_ENDL;
-			continue;
-		}
-
-		// bind key
-		if (bindKey(mode, key, mask, function_string))
-		{
-			binding_count++;
-		}
-	}
-
-	fclose(fp);
-
-	return binding_count;
-}
-
-
-EKeyboardMode LLViewerKeyboard::getMode()
-{
-	if ( gAgentCamera.cameraMouselook() )
-	{
-		return MODE_FIRST_PERSON;
-	}
-	else if ( gMorphView && gMorphView->getVisible())
-	{
-		return MODE_EDIT_AVATAR;
-	}
-	else if (isAgentAvatarValid() && gAgentAvatarp->isSitting())
-	{
-		return MODE_SITTING;
-	}
-	else
-	{
-		return MODE_THIRD_PERSON;
-	}
-}
-
-
-// Called from scanKeyboard.
-void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
-{
-	S32 mode = getMode();
-	// Consider keyboard scanning as NOT mouse event. JC
-	MASK mask = gKeyboard->currentMask(FALSE);
-
-	LLKeyBinding* binding = mBindings[mode];
-	S32 binding_count = mBindingCount[mode];
-
-
-	if (mKeyHandledByUI[key])
-	{
-		return;
-	}
-
-	// don't process key down on repeated keys
-	BOOL repeat = gKeyboard->getKeyRepeated(key);
-
-	for (S32 i = 0; i < binding_count; i++)
-	{
-		//for (S32 key = 0; key < KEY_COUNT; key++)
-		if (binding[i].mKey == key)
-		{
-			//if (binding[i].mKey == key && binding[i].mMask == mask)
-			if (binding[i].mMask == mask)
-			{
-				if (key_down && !repeat)
-				{
-					// ...key went down this frame, call function
-					binding[i].mFunction( KEYSTATE_DOWN );
-				}
-				else if (key_up)
-				{
-					// ...key went down this frame, call function
-					binding[i].mFunction( KEYSTATE_UP );
-				}
-				else if (key_level)
-				{
-					// ...key held down from previous frame
-					// Not windows, just call the function.
-					binding[i].mFunction( KEYSTATE_LEVEL );
-				}//if
-			}//if
-		}//for
-	}//for
-}
diff --git a/indra/newview/llviewerkeyboard.h b/indra/newview/llviewerkeyboard.h
deleted file mode 100644
index 110dc89d2895bfb14fe33cd89c8f0233924bf521..0000000000000000000000000000000000000000
--- a/indra/newview/llviewerkeyboard.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/** 
- * @file llviewerkeyboard.h
- * @brief LLViewerKeyboard class header file
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#ifndef LL_LLVIEWERKEYBOARD_H
-#define LL_LLVIEWERKEYBOARD_H
-
-#include "llkeyboard.h" // For EKeystate
-#include "llinitparam.h"
-
-const S32 MAX_NAMED_FUNCTIONS = 100;
-const S32 MAX_KEY_BINDINGS = 128; // was 60
-
-class LLNamedFunction
-{
-public:
-	LLNamedFunction() : mFunction(NULL) { };
-	~LLNamedFunction() { };
-
-	std::string	mName;
-	LLKeyFunc	mFunction;
-};
-
-typedef enum e_keyboard_mode
-{
-	MODE_FIRST_PERSON,
-	MODE_THIRD_PERSON,
-	MODE_EDIT,
-	MODE_EDIT_AVATAR,
-	MODE_SITTING,
-	MODE_COUNT
-} EKeyboardMode;
-
-
-void bind_keyboard_functions();
-
-class LLViewerKeyboard
-{
-public:
-	struct KeyBinding : public LLInitParam::Block<KeyBinding>
-	{
-		Mandatory<std::string>	key,
-								mask,
-								command;
-
-		KeyBinding();
-	};
-
-	struct KeyMode : public LLInitParam::Block<KeyMode>
-	{
-		Multiple<KeyBinding>		bindings;
-		EKeyboardMode				mode;
-		KeyMode(EKeyboardMode mode);
-	};
-
-	struct Keys : public LLInitParam::Block<Keys>
-	{
-		Optional<KeyMode>	first_person,
-							third_person,
-							edit,
-							sitting,
-							edit_avatar;
-
-		Keys();
-	};
-
-	LLViewerKeyboard();
-
-	BOOL			handleKey(KEY key, MASK mask, BOOL repeated);
-	BOOL			handleKeyUp(KEY key, MASK mask);
-
-	S32				loadBindings(const std::string& filename);										// returns number bound, 0 on error
-	S32				loadBindingsXML(const std::string& filename);										// returns number bound, 0 on error
-	EKeyboardMode	getMode();
-
-	BOOL			modeFromString(const std::string& string, S32 *mode);			// False on failure
-
-	void			scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);
-
-private:
-	S32				loadBindingMode(const LLViewerKeyboard::KeyMode& keymode);
-	BOOL			bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name);
-
-	// Hold all the ugly stuff torn out to make LLKeyboard non-viewer-specific here
-	S32				mBindingCount[MODE_COUNT];
-	LLKeyBinding	mBindings[MODE_COUNT][MAX_KEY_BINDINGS];
-
-	typedef std::map<U32, U32> key_remap_t;
-	key_remap_t		mRemapKeys[MODE_COUNT];
-	std::set<KEY>	mKeysSkippedByUI;
-	BOOL			mKeyHandledByUI[KEY_COUNT];		// key processed successfully by UI
-};
-
-extern LLViewerKeyboard gViewerKeyboard;
-
-#endif // LL_LLVIEWERKEYBOARD_H
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 6cfc22a4e596d31141c5527f7f6541c04f8ef5d0..700462ad75564a92f4de72d7469ad0f6460fb55e 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -57,6 +57,7 @@
 #include "llviewercontrol.h"
 #include "llviewermenufile.h" // LLFilePickerThread
 #include "llviewernetwork.h"
+#include "llviewerparcelaskplay.h"
 #include "llviewerparcelmedia.h"
 #include "llviewerparcelmgr.h"
 #include "llviewerregion.h"
@@ -1018,12 +1019,14 @@ void LLViewerMedia::setAllMediaPaused(bool val)
         }
     }
 
+    LLParcel *agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
     // Also do Parcel Media and Parcel Audio
     if (!val)
     {
         if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia())
         {
-            LLViewerParcelMedia::getInstance()->play(LLViewerParcelMgr::getInstance()->getAgentParcel());
+            LLViewerParcelMedia::getInstance()->play(agent_parcel);
         }
 
         static LLCachedControl<bool> audio_streaming_music(gSavedSettings, "AudioStreamingMusic", true);
@@ -1051,6 +1054,12 @@ void LLViewerMedia::setAllMediaPaused(bool val)
             LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade();
         }
     }
+
+    // remove play choice for current parcel
+    if (agent_parcel && gAgent.getRegion())
+    {
+        LLViewerParcelAskPlay::getInstance()->resetSetting(gAgent.getRegion()->getRegionID(), agent_parcel->getLocalID());
+    }
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -2285,14 +2294,14 @@ void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button)
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, MASK mask)
+void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, S32 scroll_x, S32 scroll_y, MASK mask)
 {
 	scaleMouse(&x, &y);
 	mLastMouseX = x;
 	mLastMouseY = y;
 	if (mMediaSource)
 	{
-		mMediaSource->scrollEvent(x, y, mask);
+		mMediaSource->scrollEvent(x, y, scroll_x, scroll_y, mask);
 	}
 }
 
@@ -3754,7 +3763,7 @@ void LLViewerMediaImpl::setTextureID(LLUUID id)
 bool LLViewerMediaImpl::isAutoPlayable() const
 {
 	return (mMediaAutoPlay &&
-			gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
+			gSavedSettings.getS32("ParcelMediaAutoPlayEnable") != 0 &&
 			gSavedSettings.getBOOL("MediaTentativeAutoPlay"));
 }
 
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 014f9048f0849559f17007dcb8f923f527495f00..2b604d3a7a9aa06400ed6f9180ae774130d4b6b3 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -79,7 +79,6 @@ class LLViewerMedia: public LLSingleton<LLViewerMedia>
 
 public:
 	// String to get/set media autoplay in gSavedSettings
-	static const char* AUTO_PLAY_MEDIA_SETTING;
 	static const char* SHOW_MEDIA_ON_OTHERS_SETTING;
 	static const char* SHOW_MEDIA_WITHIN_PARCEL_SETTING;
 	static const char* SHOW_MEDIA_OUTSIDE_PARCEL_SETTING;
@@ -235,7 +234,7 @@ class LLViewerMediaImpl
 	void mouseMove(const LLVector2& texture_coords, MASK mask);
     void mouseDoubleClick(const LLVector2& texture_coords, MASK mask);
     void mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button = 0);
-	void scrollWheel(S32 x, S32 y, MASK mask);
+	void scrollWheel(S32 x, S32 y, S32 scroll_x, S32 scroll_y, MASK mask);
 	void mouseCapture();
 	
 	void navigateBack();
@@ -320,6 +319,7 @@ class LLViewerMediaImpl
 	/*virtual*/ BOOL	handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
 	/*virtual*/ BOOL	handleHover(S32 x, S32 y, MASK mask) { return FALSE; };
 	/*virtual*/ BOOL	handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; };
+	/*virtual*/ BOOL	handleScrollHWheel(S32 x, S32 y, S32 clicks) { return FALSE; };
 	/*virtual*/ BOOL	handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; };
 	/*virtual*/ BOOL	handleRightMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
 	/*virtual*/ BOOL	handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE; };
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index f4a64a8e55c41ded10ad734cfd0df3ca5d8833e2..69ab0a71af459ecc9abe6e44ddd16faac300ddb4 100644
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -377,12 +377,7 @@ BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)
 	LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
 	if(media_impl && media_impl->hasMedia())
 	{
-        // the scrollEvent() API's x and y are not the same as handleScrollWheel's x and y.
-        // The latter is the position of the mouse at the time of the event
-        // The former is the 'scroll amount' in x and y, respectively.
-        // All we have for 'scroll amount' here is 'clicks'.
-		// We're also not passed the keyboard modifier mask, but we can get that from gKeyboard.
-		media_impl->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE));
+		media_impl->scrollWheel(x, y, 0, clicks, gKeyboard->currentMask(TRUE));
 		retval = TRUE;
 	}
 	return retval;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index dc82719109b91d3bee6f9c9c89c11c8d97c28ade..a49218858be0e4fc9b1f9867582ef64a11ea4e67 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -401,23 +401,20 @@ void set_merchant_SLM_menu()
 
 void check_merchant_status(bool force)
 {
-    if (!gSavedSettings.getBOOL("InventoryOutboxDisplayBoth"))
+    if (force)
     {
-        if (force)
-        {
-            // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status()
-            LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED);
-        }
-        // Hide SLM related menu item
-        gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(FALSE);
-        
-        // Also disable the toolbar button for Marketplace Listings
-        LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings");
-		gToolBarView->enableCommand(command->id(), false);
-        
-        // Launch an SLM test connection to get the merchant status
-        LLMarketplaceData::instance().initializeSLM(boost::bind(&set_merchant_SLM_menu));
+        // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status()
+        LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED);
     }
+    // Hide SLM related menu item
+    gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(FALSE);
+
+    // Also disable the toolbar button for Marketplace Listings
+    LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings");
+    gToolBarView->enableCommand(command->id(), false);
+
+    // Launch an SLM test connection to get the merchant status
+    LLMarketplaceData::instance().initializeSLM(boost::bind(&set_merchant_SLM_menu));
 }
 
 void init_menus()
@@ -6672,10 +6669,10 @@ class LLObjectAttachToAvatar : public view_listener_t
 
 	static void onNearAttachObject(BOOL success, void *user_data);
 	void confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point);
-
-	struct CallbackData
+	class CallbackData : public LLSelectionCallbackData
 	{
-		CallbackData(LLViewerJointAttachment* point, bool replace) : mAttachmentPoint(point), mReplace(replace) {}
+	public:
+		CallbackData(LLViewerJointAttachment* point, bool replace) : LLSelectionCallbackData(), mAttachmentPoint(point), mReplace(replace) {}
 
 		LLViewerJointAttachment*	mAttachmentPoint;
 		bool						mReplace;
@@ -6716,8 +6713,8 @@ void LLObjectAttachToAvatar::onNearAttachObject(BOOL success, void *user_data)
 			// interpret 0 as "default location"
 			attachment_id = 0;
 		}
-		LLSelectMgr::getInstance()->sendAttach(attachment_id, cb_data->mReplace);
-	}		
+		LLSelectMgr::getInstance()->sendAttach(cb_data->getSelection(), attachment_id, cb_data->mReplace);
+	}
 	LLObjectAttachToAvatar::setObjectSelection(NULL);
 
 	delete cb_data;
@@ -8003,7 +8000,6 @@ BOOL LLViewerMenuHolderGL::hideMenus()
 	
 	if (LLMenuHolderGL::hideMenus())
 	{
-		LLToolPie::instance().blockClickToWalk();
 		handled = TRUE;
 	}
 
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index a9a91b158b1b5b3aa98e431950ea42884957c3a4..687a48e7c183c922bc895e8da97901b09226d292 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -595,10 +595,16 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
 		S32 width = gViewerWindow->getWindowWidthRaw();
 		S32 height = gViewerWindow->getWindowHeightRaw();
 
+		bool render_ui = gSavedSettings.getBOOL("RenderUIInSnapshot");
+		bool render_hud = gSavedSettings.getBOOL("RenderHUDInSnapshot");
+
 		if (gSavedSettings.getBOOL("HighResSnapshot"))
 		{
 			width *= 2;
 			height *= 2;
+			// not compatible wirh UI/HUD
+			render_ui = false;
+			render_hud = false;
 		}
 
 		if (gViewerWindow->rawSnapshot(raw,
@@ -606,7 +612,8 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
 									   height,
 									   TRUE,
 									   FALSE,
-									   gSavedSettings.getBOOL("RenderUIInSnapshot"),
+									   render_ui,
+									   render_hud,
 									   FALSE))
 		{
 			LLPointer<LLImageFormatted> formatted;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index b0ad81614a1c1c2fd5748f4a356616fc6d20a280..12a9757f71422b308269898169a205ef4382c26b 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -374,6 +374,11 @@ void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_
 	LL_INFOS("Messaging") << "give_money(" << uuid << "," << amount << ")"<< LL_ENDL;
 	if(can_afford_transaction(amount))
 	{
+		if (uuid.isNull())
+		{
+			LL_WARNS() << "Failed to send L$ gift to to Null UUID." << LL_ENDL;
+			return;
+		}
 //		gStatusBar->debitBalance(amount);
 		LLMessageSystem* msg = gMessageSystem;
 		msg->newMessageFast(_PREHASH_MoneyTransferRequest);
@@ -1671,8 +1676,20 @@ void LLOfferInfo::fromLLSD(const LLSD& params)
 	*this = params;
 }
 
-void LLOfferInfo::send_auto_receive_response(void)
-{	
+void LLOfferInfo::sendReceiveResponse(bool accept, const LLUUID &destination_folder_id)
+{
+	if(IM_INVENTORY_OFFERED == mIM)
+	{
+		// add buddy to recent people list
+		LLRecentPeople::instance().add(mFromID);
+	}
+
+	if (mTransactionID.isNull())
+	{
+		// Not provided, message won't work
+		return;
+	}
+
 	LLMessageSystem* msg = gMessageSystem;
 	msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
 	msg->nextBlockFast(_PREHASH_AgentData);
@@ -1691,23 +1708,42 @@ void LLOfferInfo::send_auto_receive_response(void)
 	msg->addU32Fast(_PREHASH_ParentEstateID, 0);
 	msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
 	msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
-	
-	// Auto Receive Message. The math for the dialog works, because the accept
+
+	// ACCEPT. The math for the dialog works, because the accept
 	// for inventory_offered, task_inventory_offer or
 	// group_notice_inventory is 1 greater than the offer integer value.
 	// Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED, 
 	// or IM_GROUP_NOTICE_INVENTORY_ACCEPTED
-	msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
-	msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData),
-						   sizeof(mFolderID.mData));
-	// send the message
-	msg->sendReliable(mHost);
-	
-	if(IM_INVENTORY_OFFERED == mIM)
+	// Decline for inventory_offered, task_inventory_offer or
+	// group_notice_inventory is 2 greater than the offer integer value.
+
+	EInstantMessage im = mIM;
+	if (mIM == IM_GROUP_NOTICE_REQUESTED)
 	{
-		// add buddy to recent people list
-		LLRecentPeople::instance().add(mFromID);
+		// Request has no responder dialogs
+		im = IM_GROUP_NOTICE;
+	}
+
+	if (accept)
+	{
+		msg->addU8Fast(_PREHASH_Dialog, (U8)(im + 1));
+		msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(destination_folder_id.mData),
+								sizeof(destination_folder_id.mData));
+	}
+	else
+	{
+		msg->addU8Fast(_PREHASH_Dialog, (U8)(im + 2));
+		msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE);
 	}
+	// send the message
+	msg->sendReliable(mHost);
+
+	// transaction id is usable only once
+	// Note: a bit of a hack, clicking group notice attachment will not close notice
+	// so we reset no longer usable transaction id to know not to send message again
+	// Once capabilities for responses will be implemented LLOfferInfo will have to
+	// remember that it already responded in another way and ignore IOR_DECLINE
+	mTransactionID.setNull();
 }
 
 void LLOfferInfo::handleRespond(const LLSD& notification, const LLSD& response)
@@ -1767,7 +1803,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 	
 	// TODO: when task inventory offers can also be handled the new way, migrate the code that sets these strings here:
 	from_string = chatHistory_string = mFromName;
-	
+
+	// accept goes to proper folder, decline gets accepted to trash, muted gets declined
+	bool accept_to_trash = true;
+
 	LLNotificationFormPtr modified_form(notification_ptr ? new LLNotificationForm(*notification_ptr->getForm()) : new LLNotificationForm());
 
 	switch(button)
@@ -1799,11 +1838,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 			}
 			break;
 		case IM_GROUP_NOTICE:
+		case IM_GROUP_NOTICE_REQUESTED:
 			opener = new LLOpenTaskGroupOffer;
-			send_auto_receive_response();
+			sendReceiveResponse(true, mFolderID);
 			break;
 		case IM_TASK_INVENTORY_OFFERED:
-		case IM_GROUP_NOTICE_REQUESTED:
 			// This is an offer from a task or group.
 			// We don't use a new instance of an opener
 			// We instead use the singular observer gOpenTaskOffer
@@ -1838,6 +1877,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 		{
 			modified_form->setElementEnabled("Mute", false);
 		}
+		accept_to_trash = false; // for notices, but IOR_MUTE normally doesn't happen for notices
 		// MUTE falls through to decline
 	case IOR_DECLINE:
 		{
@@ -1851,21 +1891,32 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 			if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) )  // muting for SL-42269
 			{
 				chat.mMuted = TRUE;
+				accept_to_trash = false; // will send decline message
 			}
 
 			// *NOTE dzaporozhan
 			// Disabled logging to old chat floater to fix crash in group notices - EXT-4149
 			// LLFloaterChat::addChatHistory(chat);
 			
-			LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID);
-			discard_agent_offer->startFetch();
-			if ((catp && gInventory.isCategoryComplete(mObjectID)) || (itemp && itemp->isFinished()))
+			if (mObjectID.notNull()) //make sure we can discard
 			{
-				discard_agent_offer->done();
+				LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID);
+				discard_agent_offer->startFetch();
+				if ((catp && gInventory.isCategoryComplete(mObjectID)) || (itemp && itemp->isFinished()))
+				{
+					discard_agent_offer->done();
+				}
+				else
+				{
+					opener = discard_agent_offer;
+				}
 			}
-			else
+			else if (mIM == IM_GROUP_NOTICE)
 			{
-				opener = discard_agent_offer;
+				// group notice needs to request object to trash so that user will see it later
+				// Note: muted agent offers go to trash, not sure if we should do same for notices
+				LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+				sendReceiveResponse(accept_to_trash, trash);
 			}
 
 			if (modified_form != NULL)
@@ -1878,9 +1929,14 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 		}
 	default:
 		// close button probably
-		// The item has already been fetched and is in your inventory, we simply won't highlight it
+		// In case of agent offers item has already been fetched and is in your inventory, we simply won't highlight it
 		// OR delete it if the notification gets killed, since we don't want that to be a vector for 
 		// losing inventory offers.
+		if (mIM == IM_GROUP_NOTICE)
+		{
+			LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+			sendReceiveResponse(true, trash);
+		}
 		break;
 	}
 
@@ -1925,29 +1981,10 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
 			}
 		}
 	}
-	
-	LLMessageSystem* msg = gMessageSystem;
-	msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-	msg->nextBlockFast(_PREHASH_MessageBlock);
-	msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
-	msg->addUUIDFast(_PREHASH_ToAgentID, mFromID);
-	msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
-	msg->addUUIDFast(_PREHASH_ID, mTransactionID);
-	msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
-	std::string name;
-	LLAgentUI::buildFullname(name);
-	msg->addStringFast(_PREHASH_FromAgentName, name);
-	msg->addStringFast(_PREHASH_Message, ""); 
-	msg->addU32Fast(_PREHASH_ParentEstateID, 0);
-	msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
-	msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
-	LLInventoryObserver* opener = NULL;
-	
+
 	std::string from_string; // Used in the pop-up.
 	std::string chatHistory_string;  // Used in chat history.
+
 	if (mFromObject == TRUE)
 	{
 		if (mFromGroup)
@@ -1991,23 +2028,15 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
 		from_string = chatHistory_string = mFromName;
 	}
 	
-	bool is_do_not_disturb = gAgent.isDoNotDisturb();
-	
+	LLUUID destination;
+	bool accept = true;
+
+	// If user accepted, accept to proper folder, if user discarded, accept to trash.
 	switch(button)
 	{
 		case IOR_ACCEPT:
-			// ACCEPT. The math for the dialog works, because the accept
-			// for inventory_offered, task_inventory_offer or
-			// group_notice_inventory is 1 greater than the offer integer value.
-			// Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED, 
-			// or IM_GROUP_NOTICE_INVENTORY_ACCEPTED
-			msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
-			msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData),
-								   sizeof(mFolderID.mData));
-			// send the message
-			msg->sendReliable(mHost);
-			
-			//don't spam them if they are getting flooded
+			destination = mFolderID;
+			//don't spam user if flooded
 			if (check_offer_throttle(mFromName, true))
 			{
 				log_message = "<nolink>" + chatHistory_string + "</nolink> " + LLTrans::getString("InvOfferGaveYou") + " " + getSanitizedDescription() + LLTrans::getString(".");
@@ -2015,66 +2044,24 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
 				args["MESSAGE"] = log_message;
 				LLNotificationsUtil::add("SystemMessageTip", args);
 			}
-			
-			// we will want to open this item when it comes back.
-			LL_DEBUGS("Messaging") << "Initializing an opener for tid: " << mTransactionID
-			<< LL_ENDL;
-			switch (mIM)
-		{
-			case IM_TASK_INVENTORY_OFFERED:
-			case IM_GROUP_NOTICE:
-			case IM_GROUP_NOTICE_REQUESTED:
-			{
-				// This is an offer from a task or group.
-				// We don't use a new instance of an opener
-				// We instead use the singular observer gOpenTaskOffer
-				// Since it already exists, we don't need to actually do anything
-			}
-				break;
-			default:
-				LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;
-				break;
-		}	// end switch (mIM)
 			break;
-			
 		case IOR_MUTE:
 			// MUTE falls through to decline
+			accept = false;
 		case IOR_DECLINE:
-			// DECLINE. The math for the dialog works, because the decline
-			// for inventory_offered, task_inventory_offer or
-			// group_notice_inventory is 2 greater than the offer integer value.
-			// Generates IM_INVENTORY_DECLINED, IM_TASK_INVENTORY_DECLINED,
-			// or IM_GROUP_NOTICE_INVENTORY_DECLINED
 		default:
 			// close button probably (or any of the fall-throughs from above)
-			msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 2));
-			msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE);
-			// send the message
-			msg->sendReliable(mHost);
-
-			if (gSavedSettings.getBOOL("LogInventoryDecline"))
-			{
-				LLStringUtil::format_map_t log_message_args;
-				log_message_args["DESC"] = mDesc;
-				log_message_args["NAME"] = mFromName;
-				log_message = LLTrans::getString("InvOfferDecline", log_message_args);
-
-				LLSD args;
-				args["MESSAGE"] = log_message;
-				LLNotificationsUtil::add("SystemMessageTip", args);
-			}
-			
-			if (is_do_not_disturb &&	(!mFromGroup && !mFromObject))
+			destination = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+			if (accept && LLMuteList::getInstance()->isMuted(mFromID, mFromName))
 			{
-				send_do_not_disturb_message(msg,mFromID);
+				// Note: muted offers are usually declined automatically,
+				// but user can mute object after receiving message
+				accept = false;
 			}
 			break;
 	}
-	
-	if(opener)
-	{
-		gInventory.addObserver(opener);
-	}
+
+	sendReceiveResponse(accept, destination);
 
 	if(!mPersist)
 	{
@@ -4045,6 +4032,8 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
 	S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationList);
 	S32 num_source_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationSourceList);
 
+	LL_DEBUGS("Messaging", "Motion") << "Processing " << num_blocks << " Animations" << LL_ENDL;
+
 	//clear animation flags
 	avatarp->mSignaledAnimations.clear();
 	
@@ -4057,8 +4046,6 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
 			mesgsys->getUUIDFast(_PREHASH_AnimationList, _PREHASH_AnimID, animation_id, i);
 			mesgsys->getS32Fast(_PREHASH_AnimationList, _PREHASH_AnimSequenceID, anim_sequence_id, i);
 
-			LL_DEBUGS("Messaging") << "Anim sequence ID: " << anim_sequence_id << LL_ENDL;
-
 			avatarp->mSignaledAnimations[animation_id] = anim_sequence_id;
 
 			// *HACK: Disabling flying mode if it has been enabled shortly before the agent
@@ -4097,6 +4084,14 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
 						avatarp->mAnimationSources.insert(LLVOAvatar::AnimationSourceMap::value_type(object_id, animation_id));
 					}
 				}
+				LL_DEBUGS("Messaging", "Motion") << "Anim sequence ID: " << anim_sequence_id
+									<< " Animation id: " << animation_id
+									<< " From block: " << object_id << LL_ENDL;
+			}
+			else
+			{
+				LL_DEBUGS("Messaging", "Motion") << "Anim sequence ID: " << anim_sequence_id
+									<< " Animation id: " << animation_id << LL_ENDL;
 			}
 		}
 	}
@@ -5108,7 +5103,14 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
 			std::string snap_filename = gDirUtilp->getLindenUserDir();
 			snap_filename += gDirUtilp->getDirDelimiter();
 			snap_filename += LLStartUp::getScreenHomeFilename();
-			gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, FALSE, LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
+            gViewerWindow->saveSnapshot(snap_filename,
+                                        gViewerWindow->getWindowWidthRaw(),
+                                        gViewerWindow->getWindowHeightRaw(),
+                                        FALSE, //UI
+                                        gSavedSettings.getBOOL("RenderHUDInSnapshot"),
+                                        FALSE,
+                                        LLSnapshotModel::SNAPSHOT_TYPE_COLOR,
+                                        LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
 		}
 		
 		if (notificationID == "RegionRestartMinutes" ||
@@ -5163,12 +5165,27 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
             }
         }
 
-		// Error Notification can come with and without reason
-		if (notificationID == "JoinGroupError" && llsdBlock.has("reason"))
-		{
-			LLNotificationsUtil::add("JoinGroupErrorReason", llsdBlock);
-			return true;
-		}
+        // Error Notification can come with and without reason
+        if (notificationID == "JoinGroupError")
+        {
+            if (llsdBlock.has("reason"))
+            {
+                LLNotificationsUtil::add("JoinGroupErrorReason", llsdBlock);
+                return true;
+            }
+            if (llsdBlock.has("group_id"))
+            {
+                LLGroupData agent_gdatap;
+                bool is_member = gAgent.getGroupData(llsdBlock["group_id"].asUUID(), agent_gdatap);
+                if (is_member)
+                {
+                    LLSD args;
+                    args["reason"] = LLTrans::getString("AlreadyInGroup");
+                    LLNotificationsUtil::add("JoinGroupErrorReason", args);
+                    return true;
+                }
+            }
+        }
 
 		LLNotificationsUtil::add(notificationID, llsdBlock);
 		return true;
@@ -5191,7 +5208,14 @@ static void process_special_alert_messages(const std::string & message)
 		std::string snap_filename = gDirUtilp->getLindenUserDir();
 		snap_filename += gDirUtilp->getDirDelimiter();
 		snap_filename += LLStartUp::getScreenHomeFilename();
-		gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, FALSE, LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
+		gViewerWindow->saveSnapshot(snap_filename,
+                                    gViewerWindow->getWindowWidthRaw(),
+                                    gViewerWindow->getWindowHeightRaw(),
+                                    FALSE,
+                                    gSavedSettings.getBOOL("RenderHUDInSnapshot"),
+                                    FALSE,
+                                    LLSnapshotModel::SNAPSHOT_TYPE_COLOR,
+                                    LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
 	}
 }
 
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index 2d6636f30ddfc7e60e2f1ba8bbeee163c24513a3..78829a6a568151f7a9c3da0cda5f122ddaa1b5f9 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -254,7 +254,7 @@ class LLOfferInfo : public LLNotificationResponderInterface
 	/*virtual*/ void fromLLSD(const LLSD& params);
 	/*virtual*/ void handleRespond(const LLSD& notification, const LLSD& response);
 
-	void send_auto_receive_response(void);
+	void send_auto_receive_response() { sendReceiveResponse(true, mFolderID); }
 
 	// TODO - replace all references with handleRespond()
 	bool inventory_offer_callback(const LLSD& notification, const LLSD& response);
@@ -264,6 +264,7 @@ class LLOfferInfo : public LLNotificationResponderInterface
 
 	void initRespondFunctionMap();
 	std::string getSanitizedDescription();
+	void sendReceiveResponse(bool accept, const LLUUID &destination_folder_id);
 
 	typedef boost::function<bool (const LLSD&, const LLSD&)> respond_function_t;
 	typedef std::map<std::string, respond_function_t> respond_function_map_t;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index c7a77d4d2ab82c363f6ebf3ef963586aaa544d2a..05230c17e0421bae9dd161c4b33cc44bd669c97e 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -142,6 +142,9 @@ const F32 PHYSICS_TIMESTEP = 1.f / 45.f;
 const U32 MAX_INV_FILE_READ_FAILS = 25;
 const S32 MAX_OBJECT_BINARY_DATA_SIZE = 60 + 16;
 
+const F64 INVENTORY_UPDATE_WAIT_TIME_DESYNC = 5; // seconds
+const F64 INVENTORY_UPDATE_WAIT_TIME_OUTDATED = 1;
+
 static LLTrace::BlockTimerStatHandle FTM_CREATE_OBJECT("Create Object");
 
 // static
@@ -265,10 +268,12 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
 	mData(NULL),
 	mAudioSourcep(NULL),
 	mAudioGain(1.f),
+	mSoundCutOffRadius(0.f),
 	mAppAngle(0.f),
 	mPixelArea(1024.f),
 	mInventory(NULL),
 	mInventorySerialNum(0),
+	mExpectedInventorySerialNum(0),
 	mInvRequestState(INVENTORY_REQUEST_STOPPED),
 	mInvRequestXFerId(0),
 	mInventoryDirty(FALSE),
@@ -1241,6 +1246,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 				LLUUID audio_uuid;
 				LLUUID owner_id;	// only valid if audio_uuid or particle system is not null
 				F32    gain;
+				F32    cutoff;
 				U8     sound_flags;
 
 				mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_CRC, crc, block_num);
@@ -1249,6 +1255,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 				// HACK: Owner id only valid if non-null sound id or particle system
 				mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, block_num );
 				mesgsys->getF32Fast( _PREHASH_ObjectData, _PREHASH_Gain, gain, block_num );
+				mesgsys->getF32Fast(  _PREHASH_ObjectData, _PREHASH_Radius, cutoff, block_num );
 				mesgsys->getU8Fast(  _PREHASH_ObjectData, _PREHASH_Flags, sound_flags, block_num );
 				mesgsys->getU8Fast(  _PREHASH_ObjectData, _PREHASH_Material, material, block_num );
 				mesgsys->getU8Fast(  _PREHASH_ObjectData, _PREHASH_ClickAction, click_action, block_num); 
@@ -1257,6 +1264,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 				mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_BINARY_DATA_SIZE);
 
 				mTotalCRC = crc;
+				mSoundCutOffRadius = cutoff;
 
 				// Owner ID used for sound muting or particle system muting
 				setAttachedSound(audio_uuid, owner_id, gain, sound_flags);
@@ -1279,7 +1287,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 				{
 				case (60 + 16):
 					// pull out collision normal for avatar
-					htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
+					htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
 					((LLVOAvatar*)this)->setFootPlane(collision_plane);
 					count += sizeof(LLVector4);
 					// fall through
@@ -1287,23 +1295,23 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 					this_update_precision = 32;
 					// this is a terse update
 					// pos
-					htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+					htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
 					count += sizeof(LLVector3);
 					// vel
-					htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+					htolememcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
 					count += sizeof(LLVector3);
 					// acc
-					htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+					htolememcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
 					count += sizeof(LLVector3);
 					// theta
 					{
 						LLVector3 vec;
-						htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+						htolememcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
 						new_rot.unpackFromVector3(vec);
 					}
 					count += sizeof(LLVector3);
 					// omega
-					htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+					htolememcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
 					if (new_angv.isExactlyZero())
 					{
 						// reset rotation time
@@ -1319,7 +1327,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 					break;
 				case(32 + 16):
 					// pull out collision normal for avatar
-					htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
+					htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
 					((LLVOAvatar*)this)->setFootPlane(collision_plane);
 					count += sizeof(LLVector4);
 					// fall through
@@ -1329,7 +1337,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 
 					// This is a terse 16 update, so treat data as an array of U16's.
 #ifdef LL_BIG_ENDIAN
-					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
+					htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
 					val = valswizzle;
 #else
 					val = (U16 *) &data[count];
@@ -1340,7 +1348,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 					new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
 
 #ifdef LL_BIG_ENDIAN
-					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
+					htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
 					val = valswizzle;
 #else
 					val = (U16 *) &data[count];
@@ -1351,7 +1359,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 													   U16_to_F32(val[VZ], -size, size)));
 
 #ifdef LL_BIG_ENDIAN
-					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
+					htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
 					val = valswizzle;
 #else
 					val = (U16 *) &data[count];
@@ -1362,7 +1370,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 														   U16_to_F32(val[VZ], -size, size)));
 
 #ifdef LL_BIG_ENDIAN
-					htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 4); 
+					htolememcpy(valswizzle, &data[count], MVT_U16Quat, 4); 
 					val = valswizzle;
 #else
 					val = (U16 *) &data[count];
@@ -1374,7 +1382,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 					new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
 
 #ifdef LL_BIG_ENDIAN
-					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
+					htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
 					val = valswizzle;
 #else
 					val = (U16 *) &data[count];
@@ -1570,7 +1578,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 				{
 				case(60 + 16):
 					// pull out collision normal for avatar
-					htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
+					htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
 					((LLVOAvatar*)this)->setFootPlane(collision_plane);
 					count += sizeof(LLVector4);
 					// fall through
@@ -1578,23 +1586,23 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 					// this is a terse 32 update
 					// pos
 					this_update_precision = 32;
-					htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+					htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
 					count += sizeof(LLVector3);
 					// vel
-					htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+					htolememcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
 					count += sizeof(LLVector3);
 					// acc
-					htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+					htolememcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
 					count += sizeof(LLVector3);
 					// theta
 					{
 						LLVector3 vec;
-						htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+						htolememcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
 						new_rot.unpackFromVector3(vec);
 					}
 					count += sizeof(LLVector3);
 					// omega
-					htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+					htolememcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
 					if (new_angv.isExactlyZero())
 					{
 						// reset rotation time
@@ -1610,7 +1618,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 					break;
 				case(32 + 16):
 					// pull out collision normal for avatar
-					htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
+					htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
 					((LLVOAvatar*)this)->setFootPlane(collision_plane);
 					count += sizeof(LLVector4);
 					// fall through
@@ -1620,7 +1628,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 					test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
 
 #ifdef LL_BIG_ENDIAN
-					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
+					htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
 					val = valswizzle;
 #else
 					val = (U16 *) &data[count];
@@ -1631,7 +1639,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 					new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
 
 #ifdef LL_BIG_ENDIAN
-					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
+					htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
 					val = valswizzle;
 #else
 					val = (U16 *) &data[count];
@@ -1642,7 +1650,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 								U16_to_F32(val[VZ], -size, size));
 
 #ifdef LL_BIG_ENDIAN
-					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
+					htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
 					val = valswizzle;
 #else
 					val = (U16 *) &data[count];
@@ -1653,7 +1661,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 									U16_to_F32(val[VZ], -size, size));
 
 #ifdef LL_BIG_ENDIAN
-					htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 8); 
+					htolememcpy(valswizzle, &data[count], MVT_U16Quat, 8); 
 					val = valswizzle;
 #else
 					val = (U16 *) &data[count];
@@ -1665,7 +1673,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 					new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
 
 #ifdef LL_BIG_ENDIAN
-					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
+					htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
 					val = valswizzle;
 #else
 					val = (U16 *) &data[count];
@@ -1953,6 +1961,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 				}
 
 				mTotalCRC = crc;
+				mSoundCutOffRadius = cutoff;
 
 				setAttachedSound(sound_uuid, owner_id, gain, sound_flags);
 
@@ -2802,13 +2811,13 @@ void LLViewerObject::doUpdateInventory(
 			{
 				// best guess.
 				perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), item->getPermissions().getGroup(), is_atomic);
-				--mInventorySerialNum;
+				--mExpectedInventorySerialNum;
 			}
 			else
 			{
 				// dummy it up.
 				perm.setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, is_atomic);
-				--mInventorySerialNum;
+				--mExpectedInventorySerialNum;
 			}
 		}
 		LLViewerInventoryItem* oldItem = item;
@@ -2816,7 +2825,11 @@ void LLViewerObject::doUpdateInventory(
 		new_item->setPermissions(perm);
 		mInventory->push_front(new_item);
 		doInventoryCallback();
-		++mInventorySerialNum;
+		++mExpectedInventorySerialNum;
+	}
+	else if (is_new)
+	{
+		++mExpectedInventorySerialNum;
 	}
 }
 
@@ -2883,7 +2896,7 @@ void LLViewerObject::moveInventory(const LLUUID& folder_id,
 		if(!item->getPermissions().allowCopyBy(gAgent.getID()))
 		{
 			deleteInventoryItem(item_id);
-			++mInventorySerialNum;
+			++mExpectedInventorySerialNum;
 		}
 	}
 }
@@ -2974,6 +2987,8 @@ void LLViewerObject::fetchInventoryFromServer()
 	if (!isInventoryPending())
 	{
 		delete mInventory;
+
+		// Results in processTaskInv
 		LLMessageSystem* msg = gMessageSystem;
 		msg->newMessageFast(_PREHASH_RequestTaskInventory);
 		msg->nextBlockFast(_PREHASH_AgentData);
@@ -2983,11 +2998,44 @@ void LLViewerObject::fetchInventoryFromServer()
 		msg->addU32Fast(_PREHASH_LocalID, mLocalID);
 		msg->sendReliable(mRegionp->getHost());
 
-		// this will get reset by dirtyInventory or doInventoryCallback
+		// This will get reset by doInventoryCallback or processTaskInv
 		mInvRequestState = INVENTORY_REQUEST_PENDING;
 	}
 }
 
+void LLViewerObject::fetchInventoryDelayed(const F64 &time_seconds)
+{
+    // unless already waiting, drop previous request and shedule an update
+    if (mInvRequestState != INVENTORY_REQUEST_WAIT)
+    {
+        if (mInvRequestXFerId != 0)
+        {
+            // abort download.
+            gXferManager->abortRequestById(mInvRequestXFerId, -1);
+            mInvRequestXFerId = 0;
+        }
+        mInvRequestState = INVENTORY_REQUEST_WAIT; // affects isInventoryPending()
+        LLCoros::instance().launch("LLViewerObject::fetchInventoryDelayedCoro()",
+            boost::bind(&LLViewerObject::fetchInventoryDelayedCoro, mID, time_seconds));
+    }
+}
+
+//static
+void LLViewerObject::fetchInventoryDelayedCoro(const LLUUID task_inv, const F64 time_seconds)
+{
+    llcoro::suspendUntilTimeout(time_seconds);
+    LLViewerObject *obj = gObjectList.findObject(task_inv);
+    if (obj)
+    {
+        // Might be good idea to prolong delay here in case expected serial changed.
+        // As it is, it will get a response with obsolete serial and will delay again.
+
+        // drop waiting state to unlock isInventoryPending()
+        obj->mInvRequestState = INVENTORY_REQUEST_STOPPED;
+        obj->fetchInventoryFromServer();
+    }
+}
+
 LLControlAvatar *LLViewerObject::getControlAvatar()
 {
     return getRootEdit()->mControlAvatar.get();
@@ -3146,74 +3194,97 @@ S32 LLFilenameAndTask::sCount = 0;
 // static
 void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
 {
-	LLUUID task_id;
-	msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
-	LLViewerObject* object = gObjectList.findObject(task_id);
-	if(!object)
-	{
-		LL_WARNS() << "LLViewerObject::processTaskInv object "
-			<< task_id << " does not exist." << LL_ENDL;
-		return;
-	}
+    LLUUID task_id;
+    msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
+    LLViewerObject* object = gObjectList.findObject(task_id);
+    if (!object)
+    {
+        LL_WARNS() << "LLViewerObject::processTaskInv object "
+            << task_id << " does not exist." << LL_ENDL;
+        return;
+    }
 
-	LLFilenameAndTask* ft = new LLFilenameAndTask;
-	ft->mTaskID = task_id;
-	// we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
-	msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
+    LLFilenameAndTask* ft = new LLFilenameAndTask;
+    ft->mTaskID = task_id;
+    // we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
+    msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
 
-	if (ft->mSerial < object->mInventorySerialNum)
-	{
-		// viewer did some changes to inventory that were not saved yet.
-		LL_DEBUGS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client serial: " << object->mInventorySerialNum << LL_ENDL;
-		object->mInventorySerialNum = ft->mSerial;
-	}
+    if (ft->mSerial == object->mInventorySerialNum
+        && ft->mSerial < object->mExpectedInventorySerialNum)
+    {
+        // Loop Protection.
+        // We received same serial twice.
+        // Viewer did some changes to inventory that couldn't be saved server side
+        // or something went wrong to cause serial to be out of sync.
+        // Drop xfer and restart after some time, assign server's value as expected
+        LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL;
+        object->mExpectedInventorySerialNum = ft->mSerial;
+        object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_DESYNC);
+    }
+    else if (ft->mSerial < object->mExpectedInventorySerialNum)
+    {
+        // Out of date message, record to current serial for loop protection, but do not load it
+        // Drop xfer and restart after some time
+        if (ft->mSerial < object->mInventorySerialNum)
+        {
+            LL_WARNS() << "Task serial decreased. Potentially out of order packet or desync." << LL_ENDL;
+        }
+        object->mInventorySerialNum = ft->mSerial;
+        object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_OUTDATED);
+    }
+    else if (ft->mSerial >= object->mExpectedInventorySerialNum)
+    {
+        // We received version we expected or newer. Load it.
+        object->mInventorySerialNum = ft->mSerial;
+        object->mExpectedInventorySerialNum = ft->mSerial;
 
-	std::string unclean_filename;
-	msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
-	ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
+        std::string unclean_filename;
+        msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
+        ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
 
-	if(ft->mFilename.empty())
-	{
-		LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
-		// mock up some inventory to make a drop target.
-		if(object->mInventory)
-		{
-			object->mInventory->clear(); // will deref and delete it
-		}
-		else
-		{
-			object->mInventory = new LLInventoryObject::object_list_t();
-		}
-		LLPointer<LLInventoryObject> obj;
-		obj = new LLInventoryObject(object->mID, LLUUID::null,
-									LLAssetType::AT_CATEGORY,
-									"Contents");
-		object->mInventory->push_front(obj);
-		object->doInventoryCallback();
-		delete ft;
-		return;
-	}
-	U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename), 
-								ft->mFilename, LL_PATH_CACHE,
-								object->mRegionp->getHost(),
-								TRUE,
-								&LLViewerObject::processTaskInvFile,
-								(void**)ft,
-								LLXferManager::HIGH_PRIORITY);
-	if (object->mInvRequestState == INVENTORY_XFER)
-	{
-		if (new_id > 0 && new_id != object->mInvRequestXFerId)
-		{
-			// we started new download.
-			gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
-			object->mInvRequestXFerId = new_id;
-		}
-	}
-	else
-	{
-		object->mInvRequestState = INVENTORY_XFER;
-		object->mInvRequestXFerId = new_id;
-	}
+        if (ft->mFilename.empty())
+        {
+            LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
+            // mock up some inventory to make a drop target.
+            if (object->mInventory)
+            {
+                object->mInventory->clear(); // will deref and delete it
+            }
+            else
+            {
+                object->mInventory = new LLInventoryObject::object_list_t();
+            }
+            LLPointer<LLInventoryObject> obj;
+            obj = new LLInventoryObject(object->mID, LLUUID::null,
+                LLAssetType::AT_CATEGORY,
+                "Contents");
+            object->mInventory->push_front(obj);
+            object->doInventoryCallback();
+            delete ft;
+            return;
+        }
+        U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
+            ft->mFilename, LL_PATH_CACHE,
+            object->mRegionp->getHost(),
+            TRUE,
+            &LLViewerObject::processTaskInvFile,
+            (void**)ft,
+            LLXferManager::HIGH_PRIORITY);
+        if (object->mInvRequestState == INVENTORY_XFER)
+        {
+            if (new_id > 0 && new_id != object->mInvRequestXFerId)
+            {
+                // we started new download.
+                gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
+                object->mInvRequestXFerId = new_id;
+            }
+        }
+        else
+        {
+            object->mInvRequestState = INVENTORY_XFER;
+            object->mInvRequestXFerId = new_id;
+        }
+    }
 }
 
 void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status)
@@ -3227,6 +3298,13 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS
 		&& ft->mSerial >= object->mInventorySerialNum)
 	{
 		object->mInventorySerialNum = ft->mSerial;
+		LL_DEBUGS() << "Receiving inventory task file for serial " << object->mInventorySerialNum << " taskid: " << ft->mTaskID << LL_ENDL;
+		if (ft->mSerial < object->mExpectedInventorySerialNum)
+		{
+			// User managed to change something while inventory was loading
+			LL_DEBUGS() << "Processing file that is potentially out of date for task: " << ft->mTaskID << LL_ENDL;
+		}
+
 		if (object->loadTaskInvFile(ft->mFilename))
 		{
 
@@ -3376,7 +3454,7 @@ void LLViewerObject::removeInventory(const LLUUID& item_id)
 	msg->addUUIDFast(_PREHASH_ItemID, item_id);
 	msg->sendReliable(mRegionp->getHost());
 	deleteInventoryItem(item_id);
-	++mInventorySerialNum;
+	++mExpectedInventorySerialNum;
 }
 
 bool LLViewerObject::isTextureInInventory(LLViewerInventoryItem* item)
@@ -5839,6 +5917,8 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow
 		if( gAgent.canAccessMaturityAtGlobal(this->getPositionGlobal()) )
 		{
 			//LL_INFOS() << "Playing attached sound " << audio_uuid << LL_ENDL;
+			// recheck cutoff radius in case this update was an object-update with new value
+			mAudioSourcep->checkCutOffRadius();
 			mAudioSourcep->play(audio_uuid);
 		}
 	}
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 873b300489bc8c609e96880f13075a91e2b4fd01..03c5403a1e596ae3cb016006d4edf0143f755897 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -403,6 +403,7 @@ class LLViewerObject
 	// Owner id is this object's owner
 	void setAttachedSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const U8 flags);
 	void adjustAudioGain(const F32 gain);
+	F32  getSoundCutOffRadius() const { return mSoundCutOffRadius; }
 	void clearAttachedSound()								{ mAudioSourcep = NULL; }
 
 	 // Create if necessary
@@ -474,6 +475,8 @@ class LLViewerObject
 	void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging.
 	void updateTextureInventory(LLViewerInventoryItem* item, U8 key, bool is_new);
 	LLInventoryObject* getInventoryObject(const LLUUID& item_id);
+
+	// Get content except for root category
 	void getInventoryContents(LLInventoryObject::object_list_t& objects);
 	LLInventoryObject* getInventoryRoot();
 	LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id);
@@ -623,9 +626,13 @@ class LLViewerObject
 
 	static void initObjectDataMap();
 
-	// forms task inventory request if none are pending
+	// forms task inventory request if none are pending, marks request as pending
 	void fetchInventoryFromServer();
 
+	// forms task inventory request after some time passed, marks request as pending
+	void fetchInventoryDelayed(const F64 &time_seconds);
+	static void fetchInventoryDelayedCoro(const LLUUID task_inv, const F64 time_seconds);
+
 public:
 	//
 	// Viewer-side only types - use the LL_PCODE_APP mask.
@@ -784,6 +791,7 @@ class LLViewerObject
 	LLPointer<LLViewerPartSourceScript>		mPartSourcep;	// Particle source associated with this object.
 	LLAudioSourceVO* mAudioSourcep;
 	F32				mAudioGain;
+	F32				mSoundCutOffRadius;
 	
 	F32				mAppAngle;	// Apparent visual arc in degrees
 	F32				mPixelArea; // Apparent area in pixels
@@ -804,12 +812,14 @@ class LLViewerObject
 	typedef std::list<LLInventoryCallbackInfo*> callback_list_t;
 	callback_list_t mInventoryCallbacks;
 	S16 mInventorySerialNum;
+	S16 mExpectedInventorySerialNum;
 
 	enum EInventoryRequestState
 	{
 		INVENTORY_REQUEST_STOPPED,
-		INVENTORY_REQUEST_PENDING,
-		INVENTORY_XFER
+		INVENTORY_REQUEST_WAIT,    // delay before requesting
+		INVENTORY_REQUEST_PENDING, // just did fetchInventoryFromServer()
+		INVENTORY_XFER             // processed response from 'fetch', now doing an xfer
 	};
 	EInventoryRequestState	mInvRequestState;
 	U64						mInvRequestXFerId;
diff --git a/indra/newview/llviewerparcelaskplay.cpp b/indra/newview/llviewerparcelaskplay.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d4aa783f120a08bc084e5f84ed4929a4ce307626
--- /dev/null
+++ b/indra/newview/llviewerparcelaskplay.cpp
@@ -0,0 +1,301 @@
+/**
+ * @file llviewerparcelaskplay.cpp
+ * @brief stores data about parcel media user wants to auto-play and shows related notifications
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, 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 "llviewerprecompiledheaders.h"
+
+#include "llviewerparcelaskplay.h"
+
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llparcel.h"
+#include "llstartup.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llagent.h"
+#include "llsdserialize.h"
+
+#include <boost/lexical_cast.hpp>
+
+
+// class LLViewerParcelAskPlay
+
+LLViewerParcelAskPlay::LLViewerParcelAskPlay() :
+pNotification(NULL)
+{
+}
+
+LLViewerParcelAskPlay::~LLViewerParcelAskPlay()
+{
+
+}
+
+void LLViewerParcelAskPlay::initSingleton()
+{
+
+}
+void LLViewerParcelAskPlay::cleanupSingleton()
+{
+    cancelNotification();
+}
+
+void LLViewerParcelAskPlay::askToPlay(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, ask_callback cb)
+{
+    EAskPlayMode mode = getPlayMode(region_id, parcel_id);
+
+    switch (mode)
+    {
+    case ASK_PLAY_IGNORE:
+        cb(region_id, parcel_id, url, false);
+        break;
+    case ASK_PLAY_PLAY:
+        cb(region_id, parcel_id, url, true);
+        break;
+    case ASK_PLAY_ASK:
+    default:
+        {
+            // create or re-create notification
+            cancelNotification();
+
+            if (LLStartUp::getStartupState() > STATE_PRECACHE)
+            {
+                LLSD args;
+                args["URL"] = url;
+                LLSD payload;
+                payload["url"] = url; // or we can extract it from notification["substitutions"]
+                payload["parcel_id"] = parcel_id;
+                payload["region_id"] = region_id;
+                pNotification = LLNotificationsUtil::add("ParcelPlayingMedia", args, payload, boost::bind(onAskPlayResponse, _1, _2, cb));
+            }
+            else
+            {
+                // workaround: avoid 'new notifications arrived' on startup and just play
+                // (alternative: move to different channel, may be create new one...)
+                cb(region_id, parcel_id, url, true);
+            }
+        }
+    }
+}
+
+void LLViewerParcelAskPlay::cancelNotification()
+{
+    if (pNotification)
+    {
+        if (!pNotification->isCancelled())
+        {
+            // Force a responce
+            // Alternative is to mark notification as unique
+            pNotification->setIgnored(false);
+            LLNotifications::getInstance()->cancel(pNotification);
+        }
+        pNotification = NULL;
+    }
+}
+
+void LLViewerParcelAskPlay::resetCurrentParcelSetting()
+{
+    LLParcel *agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+    if (agent_parcel && gAgent.getRegion())
+    {
+        LLViewerParcelAskPlay::resetSetting(gAgent.getRegion()->getRegionID(), agent_parcel->getLocalID());
+    }
+}
+
+void LLViewerParcelAskPlay::resetSetting(const LLUUID &region_id, const S32 &parcel_id)
+{
+    region_map_t::iterator found = mRegionMap.find(region_id);
+    if (found != mRegionMap.end())
+    {
+        found->second.erase(parcel_id);
+    }
+}
+
+void LLViewerParcelAskPlay::resetSettings()
+{
+    if (LLViewerParcelAskPlay::instanceExists())
+    {
+        LLViewerParcelAskPlay::getInstance()->mRegionMap.clear();
+    }
+    LLFile::remove(getAskPlayFilename());
+}
+
+void LLViewerParcelAskPlay::setSetting(const LLUUID &region_id, const S32 &parcel_id, const LLViewerParcelAskPlay::ParcelData &data)
+{
+    mRegionMap[region_id][parcel_id] = data;
+}
+
+LLViewerParcelAskPlay::ParcelData* LLViewerParcelAskPlay::getSetting(const LLUUID &region_id, const S32 &parcel_id)
+{
+    region_map_t::iterator found = mRegionMap.find(region_id);
+    if (found != mRegionMap.end())
+    {
+        parcel_data_map_t::iterator found_parcel = found->second.find(parcel_id);
+        if (found_parcel != found->second.end())
+        {
+            return &(found_parcel->second);
+        }
+    }
+    return NULL;
+}
+
+LLViewerParcelAskPlay::EAskPlayMode LLViewerParcelAskPlay::getPlayMode(const LLUUID &region_id, const S32 &parcel_id)
+{
+    EAskPlayMode mode = ASK_PLAY_ASK;
+    ParcelData* data = getSetting(region_id, parcel_id);
+    if (data)
+    {
+        mode = data->mMode;
+        // refresh date
+        data->mDate = LLDate::now();
+    }
+    return mode;
+}
+
+void LLViewerParcelAskPlay::setPlayMode(const LLUUID &region_id, const S32 &parcel_id, LLViewerParcelAskPlay::EAskPlayMode mode)
+{
+    ParcelData data;
+    data.mMode = mode;
+    data.mDate = LLDate::now();
+    setSetting(region_id, parcel_id, data);
+}
+
+//static
+void LLViewerParcelAskPlay::onAskPlayResponse(const LLSD& notification, const LLSD& response, ask_callback cb)
+{
+    S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+    LLUUID region_id = notification["payload"]["region_id"];
+    S32 parcel_id = notification["payload"]["parcel_id"];
+    std::string url = notification["payload"]["url"];
+
+    bool play = option == 1;
+
+    cb(region_id, parcel_id, url, play);
+
+    LLViewerParcelAskPlay *inst = getInstance();
+    bool save_choice = inst->pNotification->isIgnored(); // checkbox selected
+    if (save_choice)
+    {
+        EAskPlayMode mode = (play) ? ASK_PLAY_PLAY : ASK_PLAY_IGNORE;
+        inst->setPlayMode(region_id, parcel_id, mode);
+    }
+}
+
+// static
+std::string LLViewerParcelAskPlay::getAskPlayFilename()
+{
+    return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "media_autoplay.xml");
+}
+
+void LLViewerParcelAskPlay::loadSettings()
+{
+    mRegionMap.clear();
+
+    std::string path = getAskPlayFilename();
+    if (!gDirUtilp->fileExists(path))
+    {
+        return;
+    }
+
+    LLSD autoplay_llsd;
+    llifstream file;
+    file.open(path.c_str());
+    if (!file.is_open())
+    {
+        return;
+    }
+    S32 status = LLSDSerialize::fromXML(autoplay_llsd, file);
+    file.close();
+
+    if (status == LLSDParser::PARSE_FAILURE || !autoplay_llsd.isMap())
+    {
+        return;
+    }
+
+    for (LLSD::map_const_iterator iter_region = autoplay_llsd.beginMap();
+        iter_region != autoplay_llsd.endMap(); ++iter_region)
+    {
+        LLUUID region_id = LLUUID(iter_region->first);
+        mRegionMap[region_id] = parcel_data_map_t();
+
+        const LLSD &parcel_map = iter_region->second;
+
+        if (parcel_map.isMap())
+        {
+            for (LLSD::map_const_iterator iter_parcel = parcel_map.beginMap();
+                iter_parcel != parcel_map.endMap(); ++iter_parcel)
+            {
+                if (!iter_parcel->second.isMap())
+                {
+                    break;
+                }
+                S32 parcel_id = boost::lexical_cast<S32>(iter_parcel->first.c_str());
+                ParcelData data;
+                data.mMode = (EAskPlayMode)(iter_parcel->second["mode"].asInteger());
+                data.mDate = iter_parcel->second["date"].asDate();
+                mRegionMap[region_id][parcel_id] = data;
+            }
+        }
+    }
+}
+
+void LLViewerParcelAskPlay::saveSettings()
+{
+    LLSD write_llsd;
+    std::string key;
+    for (region_map_t::iterator iter_region = mRegionMap.begin();
+        iter_region != mRegionMap.end(); ++iter_region)
+    {
+        if (iter_region->second.empty())
+        {
+            continue;
+        }
+        key = iter_region->first.asString();
+        write_llsd[key] = LLSD();
+        
+        for (parcel_data_map_t::iterator iter_parcel = iter_region->second.begin();
+            iter_parcel != iter_region->second.end(); ++iter_parcel)
+        {
+            if ((iter_parcel->second.mDate.secondsSinceEpoch() + (F64SecondsImplicit)U32Days(30)) > LLTimer::getTotalSeconds())
+            {
+                // write unexpired parcels
+                std::string parcel_id = boost::lexical_cast<std::string>(iter_parcel->first);
+                write_llsd[key][parcel_id] = LLSD();
+                write_llsd[key][parcel_id]["mode"] = (LLSD::Integer)iter_parcel->second.mMode;
+                write_llsd[key][parcel_id]["date"] = iter_parcel->second.mDate;
+            }
+        }
+    }
+    
+    llofstream file;
+    file.open(getAskPlayFilename().c_str());
+    if (file.is_open())
+    {
+        LLSDSerialize::toPrettyXML(write_llsd, file);
+        file.close();
+    }
+}
+
diff --git a/indra/newview/llviewerparcelaskplay.h b/indra/newview/llviewerparcelaskplay.h
new file mode 100644
index 0000000000000000000000000000000000000000..dc711917d29368f1e755d6ecd0594a6833782e31
--- /dev/null
+++ b/indra/newview/llviewerparcelaskplay.h
@@ -0,0 +1,89 @@
+/**
+ * @file llviewerparcelaskplay.h
+ * @brief stores data about parcel media user wants to auto-play and shows related notifications
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, 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$
+ */
+
+#ifndef LLVIEWERPARCELASKPLAY_H
+#define LLVIEWERPARCELASKPLAY_H
+
+#include "llnotificationptr.h"
+#include "lluuid.h"
+
+class LLViewerParcelAskPlay : public LLSingleton<LLViewerParcelAskPlay>
+{
+    LLSINGLETON(LLViewerParcelAskPlay);
+    ~LLViewerParcelAskPlay();
+    void initSingleton();
+    void cleanupSingleton();
+public:
+    // functor expects functor(region_id, parcel_id, url, play/stop)
+    typedef boost::function<void(const LLUUID&, const S32&, const std::string&, const bool&)> ask_callback;
+    void        askToPlay(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, ask_callback cb);
+    void        cancelNotification();
+
+    void        resetCurrentParcelSetting();
+    void        resetSetting(const LLUUID &region_id, const S32 &parcel_id);
+    static void resetSettings();
+
+    void        loadSettings();
+    void        saveSettings();
+
+    S32         hasData() { return !mRegionMap.empty(); } // subsitution for 'isInitialized'
+
+private:
+    enum EAskPlayMode{
+        ASK_PLAY_IGNORE = 0,
+        ASK_PLAY_PLAY,
+        ASK_PLAY_ASK
+    };
+
+    class ParcelData
+    {
+    public:
+        LLDate mDate;
+        EAskPlayMode mMode;
+    };
+
+    void               setSetting(const LLUUID &region_id, const S32 &parcel_id, const ParcelData &data);
+    ParcelData*        getSetting(const LLUUID &region_id, const S32 &parcel_id);
+    EAskPlayMode       getPlayMode(const LLUUID &region_id, const S32 &parcel_id);
+    void               setPlayMode(const LLUUID &region_id, const S32 &parcel_id, EAskPlayMode);
+
+    static void        onAskPlayResponse(const LLSD& notification, const LLSD& response, ask_callback cb);
+
+    static std::string getAskPlayFilename();
+
+private:
+    // Variables
+
+    typedef std::map<S32, ParcelData> parcel_data_map_t;
+    typedef std::map<LLUUID, parcel_data_map_t> region_map_t;
+    region_map_t mRegionMap;
+
+    // only one notification is supposed to exists and be visible
+    LLNotificationPtr pNotification;
+};
+
+
+#endif // LLVIEWERPARCELASKPLAY_H
diff --git a/indra/newview/llviewerparcelmediaautoplay.cpp b/indra/newview/llviewerparcelmediaautoplay.cpp
index b5a76ccba2a9c2d4fca938e9e417650da45951d0..54d9804b9c5bb46026a094a606a0552d270ee3c5 100644
--- a/indra/newview/llviewerparcelmediaautoplay.cpp
+++ b/indra/newview/llviewerparcelmediaautoplay.cpp
@@ -24,17 +24,20 @@
  * $/LicenseInfo$
  */
 
+
 #include "llviewerprecompiledheaders.h"
+
 #include "llviewerparcelmediaautoplay.h"
-#include "llviewerparcelmedia.h"
+
+#include "llparcel.h"
 #include "llviewercontrol.h"
 #include "llviewermedia.h"
-#include "llviewerregion.h"
-#include "llparcel.h"
+#include "llviewerparcelaskplay.h"
+#include "llviewerparcelmedia.h"
 #include "llviewerparcelmgr.h"
-#include "lluuid.h"
-#include "message.h"
+#include "llviewerregion.h"
 #include "llviewertexturelist.h"         // for texture stats
+#include "message.h"
 #include "llagent.h"
 #include "llmimetypes.h"
 
@@ -122,11 +125,28 @@ BOOL LLViewerParcelMediaAutoPlay::tick()
 				{
 					if (this_parcel)
 					{
-						if (gSavedSettings.getBOOL("ParcelMediaAutoPlayEnable"))
+						static LLCachedControl<S32> autoplay_mode(gSavedSettings, "ParcelMediaAutoPlayEnable");
+
+						switch (autoplay_mode())
 						{
-							// and last but not least, only play when autoplay is enabled
-							LLViewerParcelMedia::getInstance()->play(this_parcel);
-						}
+							case 0:
+								// Disabled
+								break;
+							case 1:
+								// Play, default value for ParcelMediaAutoPlayEnable
+								LLViewerParcelMedia::getInstance()->play(this_parcel);
+								break;
+							case 2:
+							default:
+							{
+								// Ask
+								LLViewerParcelAskPlay::getInstance()->askToPlay(this_region->getRegionID(),
+																				this_parcel->getLocalID(),
+																				this_parcel->getMediaURL(),
+																				onStartMusicResponse);
+								break;
+  							}
+  						}
 					}
 
 					mPlayed = TRUE;
@@ -139,5 +159,18 @@ BOOL LLViewerParcelMediaAutoPlay::tick()
 	return FALSE; // continue ticking forever please.
 }
 
-
+//static
+void LLViewerParcelMediaAutoPlay::onStartMusicResponse(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, const bool &play)
+{
+    if (play)
+    {
+        LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+        // make sure we are still there
+        if (parcel->getLocalID() == parcel_id && gAgent.getRegion()->getRegionID() == region_id)
+        {
+            LLViewerParcelMedia::play(parcel);
+        }
+    }
+}
 
diff --git a/indra/newview/llviewerparcelmediaautoplay.h b/indra/newview/llviewerparcelmediaautoplay.h
index 33565307f285e2c5ab84d5c79593c18edaccff4c..cf8e9a97e76149346c1ab932bf930a795de9b40d 100644
--- a/indra/newview/llviewerparcelmediaautoplay.h
+++ b/indra/newview/llviewerparcelmediaautoplay.h
@@ -38,6 +38,9 @@ class LLViewerParcelMediaAutoPlay : LLEventTimer, public LLSingleton<LLViewerPar
 	virtual BOOL tick();
 	static void playStarted();
 
+ private:
+	static void onStartMusicResponse(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, const bool &play);
+
  private:
 	S32 mLastParcelID;
 	LLUUID mLastRegionID;
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 6cc88d0c0be698ba7956a4469ed5c94d464b0cd8..d91d0abb991ecb81f4b7e5457a50935f48531287 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -42,6 +42,7 @@
 // Viewer includes
 #include "llagent.h"
 #include "llagentaccess.h"
+#include "llviewerparcelaskplay.h"
 #include "llviewerwindow.h"
 #include "llviewercontrol.h"
 //#include "llfirstuse.h"
@@ -1832,6 +1833,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
                 // Only update stream if parcel changed (recreated) or music is playing (enabled)
                 if (!agent_parcel_update || gSavedSettings.getBOOL("MediaTentativeAutoPlay"))
                 {
+                    LLViewerParcelAskPlay::getInstance()->cancelNotification();
                     std::string music_url_raw = parcel->getMusicURL();
 
                     // Trim off whitespace from front and back
@@ -1843,7 +1845,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
                     {
                         if (music_url.substr(0, 7) == "http://")
                         {
-                            optionally_start_music(music_url);
+                            LLViewerRegion *region = LLWorld::getInstance()->getRegion(msg->getSender());
+                            optionally_start_music(music_url, parcel->mLocalID, region->getRegionID());
                         }
                         else
                         {
@@ -1864,25 +1867,61 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
 			else
 			{
 				// Public land has no music
+				LLViewerParcelAskPlay::getInstance()->cancelNotification();
 				LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade();
 			}
 		}//if gAudiop
 	};
 }
 
-void LLViewerParcelMgr::optionally_start_music(const std::string& music_url)
+//static
+void LLViewerParcelMgr::onStartMusicResponse(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, const bool &play)
 {
-	if (gSavedSettings.getBOOL("AudioStreamingMusic"))
+    if (play)
+    {
+        LL_INFOS("ParcelMgr") << "Starting parcel music " << url << LL_ENDL;
+        LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(url);
+    }
+}
+
+void LLViewerParcelMgr::optionally_start_music(const std::string &music_url, const S32 &local_id, const LLUUID &region_id)
+{
+	static LLCachedControl<bool> streaming_music(gSavedSettings, "AudioStreamingMusic", true);
+	if (streaming_music)
 	{
+		static LLCachedControl<S32> autoplay_mode(gSavedSettings, "ParcelMediaAutoPlayEnable", 1);
+		static LLCachedControl<bool> tentative_autoplay(gSavedSettings, "MediaTentativeAutoPlay", true);
 		// only play music when you enter a new parcel if the UI control for this
 		// was not *explicitly* stopped by the user. (part of SL-4878)
 		LLPanelNearByMedia* nearby_media_panel = gStatusBar->getNearbyMediaPanel();
-		if ((nearby_media_panel &&
-		     nearby_media_panel->getParcelAudioAutoStart()) ||
-		    // or they have expressed no opinion in the UI, but have autoplay on...
-		    (!nearby_media_panel &&
-		     gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
-			 gSavedSettings.getBOOL("MediaTentativeAutoPlay")))
+
+        // ask mode //todo constants
+        if (autoplay_mode == 2)
+        {
+            // stop previous stream
+            LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null);
+
+            // if user set media to play - ask
+            if ((nearby_media_panel && nearby_media_panel->getParcelAudioAutoStart())
+                || (!nearby_media_panel && tentative_autoplay))
+            {
+                LLViewerParcelAskPlay::getInstance()->askToPlay(region_id,
+                    local_id,
+                    music_url,
+                    onStartMusicResponse);
+            }
+            else
+            {
+                LLViewerParcelAskPlay::getInstance()->cancelNotification();
+            }
+        }
+        // autoplay
+        else if ((nearby_media_panel
+                  && nearby_media_panel->getParcelAudioAutoStart())
+                  // or they have expressed no opinion in the UI, but have autoplay on...
+                 || (!nearby_media_panel
+                     && autoplay_mode == 1
+                     && tentative_autoplay))
 		{
 			LL_INFOS("ParcelMgr") << "Starting parcel music " << music_url << LL_ENDL;
 			LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(music_url);
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 29219843c9ef20b3ea5161a9d28dcd65b37882d4..288077fafc8a9624cf25b59446c6d37c108abf53 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -268,7 +268,8 @@ class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr>
 	// *NOTE: Taken out 2005-03-21. Phoenix.
 	//void makeLandmarkAtSelection();
 
-	static void optionally_start_music(const std::string& music_url);
+	static void onStartMusicResponse(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, const bool &play);
+	static void optionally_start_music(const std::string &music_url, const S32 &local_id, const LLUUID &region_id);
 
 	static void processParcelOverlay(LLMessageSystem *msg, void **user_data);
 	static void processParcelProperties(LLMessageSystem *msg, void **user_data);
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 15b2ac8acf0d90501259e9b80b715e61afbd8b74..85d87a43af72a1fbbef76519563a0f6e031d6b44 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -359,16 +359,19 @@ void update_statistics()
 	record(LLStatViewer::REBUILD_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Sort Draw State")));
 	record(LLStatViewer::RENDER_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Render Geometry")));
 		
-	LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
-	if (cdp)
+	if (gAgent.getRegion() && isAgentAvatarValid())
 	{
-		sample(LLStatViewer::SIM_PING, F64Milliseconds (cdp->getPingDelay()));
-		gAvgSimPing = ((gAvgSimPing * gSimPingCount) + cdp->getPingDelay()) / (gSimPingCount + 1);
-		gSimPingCount++;
-	}
-	else
-	{
-		sample(LLStatViewer::SIM_PING, U32Seconds(10));
+		LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
+		if (cdp)
+		{
+			sample(LLStatViewer::SIM_PING, F64Milliseconds(cdp->getPingDelay()));
+			gAvgSimPing = ((gAvgSimPing * gSimPingCount) + cdp->getPingDelay()) / (gSimPingCount + 1);
+			gSimPingCount++;
+		}
+		else
+		{
+			sample(LLStatViewer::SIM_PING, U32Seconds(10));
+		}
 	}
 
 	if (LLViewerStats::instance().getRecording().getSum(LLStatViewer::FPS))
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 06524847d1780783df9272812a8d2a33f24b2148..561319ca5d2b4eb61e555f3b4e9bbbc4271d7c17 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1385,8 +1385,6 @@ S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, fl
 		{
 			max_texmem = (S32Megabytes)128;
 		}
-
-		LL_WARNS() << "VRAM amount not detected, defaulting to " << max_texmem << " MB" << LL_ENDL;
 	}
 
 	S32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB(); // In MB
@@ -1428,6 +1426,11 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem)
 		return; //listener will re-enter this function
 	}
 
+	if (gGLManager.mVRAM == 0)
+	{
+		LL_WARNS() << "VRAM amount not detected, defaulting to " << mem << " MB" << LL_ENDL;
+	}
+
 	// TODO: set available resident texture mem based on use by other subsystems
 	// currently max(12MB, VRAM/4) assumed...
 	
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 61f4ee463dc70d95d222a6ec108255f6c46c7bc7..7f87836644fa2ba6773dc035abe1475e6a8d5e58 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -45,7 +45,8 @@
 #include "llmeshrepository.h"
 #include "llnotificationhandler.h"
 #include "llpanellogin.h"
-#include "llviewerkeyboard.h"
+#include "llsetkeybinddialog.h"
+#include "llviewerinput.h"
 #include "llviewermenu.h"
 
 #include "llviewquery.h"
@@ -173,7 +174,7 @@
 #include "llviewergesture.h"
 #include "llviewertexturelist.h"
 #include "llviewerinventory.h"
-#include "llviewerkeyboard.h"
+#include "llviewerinput.h"
 #include "llviewermedia.h"
 #include "llviewermediafocus.h"
 #include "llviewermenu.h"
@@ -898,7 +899,18 @@ LLViewerWindow::Params::Params()
 {}
 
 
-BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
+void LLViewerWindow::handlePieMenu(S32 x, S32 y, MASK mask)
+{
+    if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() && gAgent.isInitialized())
+    {
+        // If the current tool didn't process the click, we should show
+        // the pie menu.  This can be done by passing the event to the pie
+        // menu tool.
+        LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
+    }
+}
+
+BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down)
 {
 	const char* buttonname = "";
 	const char* buttonstatestr = "";
@@ -922,22 +934,30 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK
 		
 		switch (clicktype)
 		{
-		case LLMouseHandler::CLICK_LEFT:
+		case CLICK_LEFT:
 			mLeftMouseDown = down;
 			buttonname = "Left";
 			break;
-		case LLMouseHandler::CLICK_RIGHT:
+		case CLICK_RIGHT:
 			mRightMouseDown = down;
 			buttonname = "Right";
 			break;
-		case LLMouseHandler::CLICK_MIDDLE:
+		case CLICK_MIDDLE:
 			mMiddleMouseDown = down;
 			buttonname = "Middle";
 			break;
-		case LLMouseHandler::CLICK_DOUBLELEFT:
+		case CLICK_DOUBLELEFT:
 			mLeftMouseDown = down;
 			buttonname = "Left Double Click";
 			break;
+		case CLICK_BUTTON4:
+			buttonname = "Button 4";
+			break;
+		case CLICK_BUTTON5:
+			buttonname = "Button 5";
+			break;
+		default:
+			break; // COUNT and NONE
 		}
 		
 		LLView::sMouseHandlerMessage.clear();
@@ -988,6 +1008,11 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK
 				LLViewerEventRecorder::instance().logMouseEvent(std::string(buttonstatestr),std::string(buttonname)); 
 
 			}
+			else if (down && clicktype == CLICK_RIGHT)
+			{
+				handlePieMenu(x, y, mask);
+				r = TRUE;
+			}
 			return r;
 		}
 
@@ -1034,7 +1059,12 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK
 		return TRUE;
 	}
 
-	
+	if (down && clicktype == CLICK_RIGHT)
+	{
+		handlePieMenu(x, y, mask);
+		return TRUE;
+	}
+
 	// If we got this far on a down-click, it wasn't handled.
 	// Up-clicks, though, are always handled as far as the OS is concerned.
 	BOOL default_rtn = !down;
@@ -1053,7 +1083,8 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask
         mMouseDownTimer.reset();
     }    
     BOOL down = TRUE;
-	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
+    //handleMouse() loops back to LLViewerWindow::handleAnyMouseClick
+    return gViewerInput.handleMouse(window, pos, mask, CLICK_LEFT, down);
 }
 
 BOOL LLViewerWindow::handleDoubleClick(LLWindow *window,  LLCoordGL pos, MASK mask)
@@ -1061,8 +1092,7 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window,  LLCoordGL pos, MASK ma
 	// try handling as a double-click first, then a single-click if that
 	// wasn't handled.
 	BOOL down = TRUE;
-	if (handleAnyMouseClick(window, pos, mask,
-				LLMouseHandler::CLICK_DOUBLELEFT, down))
+	if (gViewerInput.handleMouse(window, pos, mask, CLICK_DOUBLELEFT, down))
 	{
 		return TRUE;
 	}
@@ -1076,47 +1106,24 @@ BOOL LLViewerWindow::handleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
         mMouseDownTimer.stop();
     }
     BOOL down = FALSE;
-	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
+    return gViewerInput.handleMouse(window, pos, mask, CLICK_LEFT, down);
 }
-
-
 BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
 {
-	S32 x = pos.mX;
-	S32 y = pos.mY;
-	x = ll_round((F32)x / mDisplayScale.mV[VX]);
-	y = ll_round((F32)y / mDisplayScale.mV[VY]);
-
 	BOOL down = TRUE;
-	BOOL handle = handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
-	if (handle)
-		return handle;
-
-	// *HACK: this should be rolled into the composite tool logic, not
-	// hardcoded at the top level.
-	if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() && gAgent.isInitialized())
-	{
-		// If the current tool didn't process the click, we should show
-		// the pie menu.  This can be done by passing the event to the pie
-		// menu tool.
-		LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
-		// show_context_menu( x, y, mask );
-	}
-
-	return TRUE;
+	return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down);
 }
 
 BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
 {
 	BOOL down = FALSE;
- 	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
+ 	return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down);
 }
 
 BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
 {
 	BOOL down = TRUE;
-	LLVoiceClient::getInstance()->middleMouseState(true);
- 	handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
+ 	gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down);
   
   	// Always handled as far as the OS is concerned.
 	return TRUE;
@@ -1267,17 +1274,44 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
 	
 	return result;
 }
-  
+
 BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
 {
 	BOOL down = FALSE;
-	LLVoiceClient::getInstance()->middleMouseState(false);
- 	handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
+ 	gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down);
   
   	// Always handled as far as the OS is concerned.
 	return TRUE;
 }
 
+BOOL LLViewerWindow::handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask, S32 button, bool down)
+{
+    switch (button)
+    {
+    case 4:
+        gViewerInput.handleMouse(window, pos, mask, CLICK_BUTTON4, down);
+        break;
+    case 5:
+        gViewerInput.handleMouse(window, pos, mask, CLICK_BUTTON5, down);
+        break;
+    default:
+        break;
+    }
+
+    // Always handled as far as the OS is concerned.
+    return TRUE;
+}
+
+BOOL LLViewerWindow::handleOtherMouseDown(LLWindow *window, LLCoordGL pos, MASK mask, S32 button)
+{
+    return handleOtherMouse(window, pos, mask, button, TRUE);
+}
+
+BOOL LLViewerWindow::handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK mask, S32 button)
+{
+    return handleOtherMouse(window, pos, mask, button, FALSE);
+}
+
 // WARNING: this is potentially called multiple times per frame
 void LLViewerWindow::handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask)
 {
@@ -1404,9 +1438,6 @@ void LLViewerWindow::handleFocusLost(LLWindow *window)
 
 BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key,  MASK mask, BOOL repeated)
 {
-	// Let the voice chat code check for its PTT key.  Note that this never affects event processing.
-	LLVoiceClient::getInstance()->keyDown(key, mask);
-
 	if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME)
 	{
 		gAgent.clearAFK();
@@ -1425,14 +1456,12 @@ BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key,  MASK mask, BOOL repeated)
     		return FALSE;
 	}
 
-	return gViewerKeyboard.handleKey(key, mask, repeated);
+    // remaps, handles ignored cases and returns back to viewer window.
+    return gViewerInput.handleKey(key, mask, repeated);
 }
 
 BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key,  MASK mask)
 {
-	// Let the voice chat code check for its PTT key.  Note that this never affects event processing.
-	LLVoiceClient::getInstance()->keyUp(key, mask);
-
 	// Let the inspect tool code check for ALT key to set LLToolSelectRect active instead LLToolCamera
 	LLToolCompInspect * tool_inspectp = LLToolCompInspect::getInstance();
 	if (LLToolMgr::getInstance()->getCurrentTool() == tool_inspectp)
@@ -1440,13 +1469,13 @@ BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key,  MASK mask)
 		tool_inspectp->keyUp(key, mask);
 	}
 
-	return gViewerKeyboard.handleKeyUp(key, mask);
+	return gViewerInput.handleKeyUp(key, mask);
 }
 
 void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
 {
 	LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
-	gViewerKeyboard.scanKey(key, key_down, key_up, key_level);
+	gViewerInput.scanKey(key, key_down, key_up, key_level);
 	return; // Be clear this function returns nothing
 }
 
@@ -1551,6 +1580,11 @@ void LLViewerWindow::handleScrollWheel(LLWindow *window,  S32 clicks)
 	handleScrollWheel( clicks );
 }
 
+void LLViewerWindow::handleScrollHWheel(LLWindow *window,  S32 clicks)
+{
+	handleScrollHWheel(clicks);
+}
+
 void LLViewerWindow::handleWindowBlock(LLWindow *window)
 {
 	send_agent_pause();
@@ -1951,6 +1985,11 @@ void LLViewerWindow::initBase()
 	LLPanel* panel_holder = main_view->getChild<LLPanel>("toolbar_view_holder");
 	// Load the toolbar view from file 
 	gToolBarView = LLUICtrlFactory::getInstance()->createFromFile<LLToolBarView>("panel_toolbar_view.xml", panel_holder, LLDefaultChildRegistry::instance());
+	if (!gToolBarView)
+	{
+		LL_ERRS() << "Failed to initialize viewer: Viewer couldn't process file panel_toolbar_view.xml, "
+				<< "if this problem happens again, please validate your installation." << LL_ENDL;
+	}
 	gToolBarView->setShape(panel_holder->getLocalRect());
 	// Hide the toolbars for the moment: we'll make them visible after logging in world (see LLViewerWindow::initWorldUI())
 	gToolBarView->setVisible(FALSE);
@@ -2676,6 +2715,14 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
 	// hide tooltips on keypress
 	LLToolTipMgr::instance().blockToolTips();
 
+    // let menus handle navigation keys for navigation
+    if (LLSetKeyBindDialog::recordKey(key, mask))
+    {
+        LL_DEBUGS() << "Key handled by LLSetKeyBindDialog" << LL_ENDL;
+        LLViewerEventRecorder::instance().logKeyEvent(key,mask);
+        return TRUE;
+    }
+
     LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
 
     if (keyboard_focus
@@ -2836,7 +2883,8 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
 	// If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, 
 	// no view has keyboard focus, this is a printable character key (and no modifier key is 
 	// pressed except shift), then give focus to nearby chat (STORM-560)
-	if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && 
+	if ( LLStartUp::getStartupState() >= STATE_STARTED && 
+		gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && 
 		!keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )
 	{
 		// Initialize nearby chat if it's missing
@@ -2890,7 +2938,8 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
 	{
 		if (mask != MASK_ALT)
 		{
-			return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
+			// remaps, handles ignored cases and returns back to viewer window.
+			return gViewerInput.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
 		}
 	}
 
@@ -2966,6 +3015,49 @@ void LLViewerWindow::handleScrollWheel(S32 clicks)
 	return;
 }
 
+void LLViewerWindow::handleScrollHWheel(S32 clicks)
+{
+    LLUI::resetMouseIdleTimer();
+
+    LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
+    if (mouse_captor)
+    {
+        S32 local_x;
+        S32 local_y;
+        mouse_captor->screenPointToLocal(mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y);
+        mouse_captor->handleScrollHWheel(local_x, local_y, clicks);
+        if (LLView::sDebugMouseHandling)
+        {
+            LL_INFOS() << "Scroll Horizontal Wheel handled by captor " << mouse_captor->getName() << LL_ENDL;
+        }
+        return;
+    }
+
+    LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+    if (top_ctrl)
+    {
+        S32 local_x;
+        S32 local_y;
+        top_ctrl->screenPointToLocal(mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y);
+        if (top_ctrl->handleScrollHWheel(local_x, local_y, clicks)) return;
+    }
+
+    if (mRootView->handleScrollHWheel(mCurrentMousePoint.mX, mCurrentMousePoint.mY, clicks))
+    {
+        if (LLView::sDebugMouseHandling)
+        {
+            LL_INFOS() << "Scroll Horizontal Wheel" << LLView::sMouseHandlerMessage << LL_ENDL;
+        }
+        return;
+    }
+    else if (LLView::sDebugMouseHandling)
+    {
+        LL_INFOS() << "Scroll Horizontal Wheel not handled by view" << LL_ENDL;
+    }
+
+    return;
+}
+
 void LLViewerWindow::addPopup(LLView* popup)
 {
 	if (mPopupView)
@@ -3329,7 +3421,8 @@ void LLViewerWindow::updateUI()
 			LLRect screen_sticky_rect = mRootView->getLocalRect();
 			S32 local_x, local_y;
 
-			if (gSavedSettings.getBOOL("DebugShowXUINames"))
+			static LLCachedControl<bool> debug_show_xui_names(gSavedSettings, "DebugShowXUINames", 0);
+			if (debug_show_xui_names)
 			{
 				LLToolTip::Params params;
 
@@ -4485,12 +4578,12 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
 	}
 }
 
-BOOL LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type, LLSnapshotModel::ESnapshotFormat format)
+BOOL LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type, LLSnapshotModel::ESnapshotFormat format)
 {
     LL_INFOS() << "Saving snapshot to: " << filepath << LL_ENDL;
 
     LLPointer<LLImageRaw> raw = new LLImageRaw;
-    BOOL success = rawSnapshot(raw, image_width, image_height, TRUE, FALSE, show_ui, do_rebuild);
+    BOOL success = rawSnapshot(raw, image_width, image_height, TRUE, FALSE, show_ui, show_hud, do_rebuild);
 
     if (success)
     {
@@ -4549,16 +4642,16 @@ void LLViewerWindow::resetSnapshotLoc() const
 	gSavedPerAccountSettings.setString("SnapshotBaseDir", std::string());
 }
 
-BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type)
+BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type)
 {
-	return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type);
+	return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, show_hud, do_rebuild, type);
 }
 
 // Saves the image from the screen to a raw image
 // Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy
 // the results over to the final raw image.
 BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, 
-	BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type, S32 max_size)
+    BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type, S32 max_size)
 {
 	if (!raw)
 	{
@@ -4592,7 +4685,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
 		LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI);
 	}
 
-	BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
+    BOOL hide_hud = !show_hud && LLPipeline::sShowHUDAttachments;
 	if (hide_hud)
 	{
 		LLPipeline::sShowHUDAttachments = FALSE;
@@ -4632,7 +4725,8 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
 		if ((image_width <= gGLManager.mGLMaxTextureSize && image_height <= gGLManager.mGLMaxTextureSize) && 
 			(image_width > window_width || image_height > window_height) && LLPipeline::sRenderDeferred && !show_ui)
 		{
-			if (scratch_space.allocate(image_width, image_height, GL_DEPTH_COMPONENT, true, true))
+			U32 color_fmt = type == LLSnapshotModel::SNAPSHOT_TYPE_DEPTH ? GL_DEPTH_COMPONENT : GL_RGBA;
+			if (scratch_space.allocate(image_width, image_height, color_fmt, true, true))
 			{
 				original_width = gPipeline.mDeferredScreen.getWidth();
 				original_height = gPipeline.mDeferredScreen.getHeight();
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 071a3632ddb5be7c2c422f486e87ab7891162d0a..1f49c0756c98e5fe0ef78928728ee82896ad4cf2 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -175,8 +175,9 @@ class LLViewerWindow : public LLWindowCallbacks
 	void			initWorldUI();
 	void			setUIVisibility(bool);
 	bool			getUIVisibility();
+	void			handlePieMenu(S32 x, S32 y, MASK mask);
 
-	BOOL handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
+	BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
 
 	//
 	// LLWindowCallback interface implementation
@@ -192,7 +193,10 @@ class LLViewerWindow : public LLWindowCallbacks
 	/*virtual*/ BOOL handleRightMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask);
 	/*virtual*/ BOOL handleRightMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask);
 	/*virtual*/ BOOL handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask);
-	/*virtual*/ BOOL handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask);
+	/*virtual*/ BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
+	/*virtual*/ BOOL handleOtherMouseDown(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
+	/*virtual*/ BOOL handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
+	BOOL handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask, S32 button, bool down);
 	/*virtual*/ LLWindowCallbacks::DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data);
 				void handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask);
                 void handleMouseDragged(LLWindow *window,  LLCoordGL pos, MASK mask);
@@ -205,6 +209,7 @@ class LLViewerWindow : public LLWindowCallbacks
 	/*virtual*/ void handleMenuSelect(LLWindow *window,  S32 menu_item);
 	/*virtual*/ BOOL handlePaint(LLWindow *window,  S32 x,  S32 y,  S32 width,  S32 height);
 	/*virtual*/ void handleScrollWheel(LLWindow *window,  S32 clicks);
+	/*virtual*/ void handleScrollHWheel(LLWindow *window,  S32 clicks);
 	/*virtual*/ BOOL handleDoubleClick(LLWindow *window,  LLCoordGL pos, MASK mask);
 	/*virtual*/ void handleWindowBlock(LLWindow *window);
 	/*virtual*/ void handleWindowUnblock(LLWindow *window);
@@ -323,6 +328,7 @@ class LLViewerWindow : public LLWindowCallbacks
 	BOOL			handleKey(KEY key, MASK mask);
 	BOOL			handleKeyUp(KEY key, MASK mask);
 	void			handleScrollWheel	(S32 clicks);
+	void			handleScrollHWheel	(S32 clicks);
 
 	// add and remove views from "popup" layer
 	void			addPopup(LLView* popup);
@@ -347,10 +353,10 @@ class LLViewerWindow : public LLWindowCallbacks
 	// snapshot functionality.
 	// perhaps some of this should move to llfloatershapshot?  -MG
 
-	BOOL			saveSnapshot(const std::string&  filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::ESnapshotFormat format = LLSnapshotModel::SNAPSHOT_FORMAT_BMP);
+	BOOL			saveSnapshot(const std::string&  filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL show_hud = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::ESnapshotFormat format = LLSnapshotModel::SNAPSHOT_FORMAT_BMP);
 	BOOL			rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE,
-		BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE);
-	BOOL			thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type);
+		BOOL show_ui = TRUE, BOOL show_hud = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE);
+	BOOL			thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type);
 	BOOL			isSnapshotLocSet() const;
 	void			resetSnapshotLoc() const;
 
diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp
index 97b405c1d0943ed0f61f0cf72d79ba00e12f8bf1..acf25b9792fc4cfc3636b051fac07d34972c2b8c 100644
--- a/indra/newview/llviewerwindowlistener.cpp
+++ b/indra/newview/llviewerwindowlistener.cpp
@@ -50,10 +50,11 @@ LLViewerWindowListener::LLViewerWindowListener(LLViewerWindow* llviewerwindow):
 //  saveSnapshotArgs["width"] = LLSD::Integer();
 //  saveSnapshotArgs["height"] = LLSD::Integer();
 //  saveSnapshotArgs["showui"] = LLSD::Boolean();
+//  saveSnapshotArgs["showhud"] = LLSD::Boolean();
 //  saveSnapshotArgs["rebuild"] = LLSD::Boolean();
 //  saveSnapshotArgs["type"] = LLSD::String();
     add("saveSnapshot",
-        "Save screenshot: [\"filename\"], [\"width\"], [\"height\"], [\"showui\"], [\"rebuild\"], [\"type\"]\n"
+        "Save screenshot: [\"filename\"], [\"width\"], [\"height\"], [\"showui\"], [\"showhud\"], [\"rebuild\"], [\"type\"]\n"
         "type: \"COLOR\", \"DEPTH\"\n"
         "Post on [\"reply\"] an event containing [\"ok\"]",
         &LLViewerWindowListener::saveSnapshot,
@@ -83,6 +84,9 @@ void LLViewerWindowListener::saveSnapshot(const LLSD& event) const
     bool showui = true;
     if (event.has("showui"))
         showui = event["showui"].asBoolean();
+    bool showhud = true;
+    if (event.has("showhud"))
+        showhud = event["showhud"].asBoolean();
     bool rebuild(event["rebuild"]); // defaults to false
     LLSnapshotModel::ESnapshotLayerType type(LLSnapshotModel::SNAPSHOT_TYPE_COLOR);
     if (event.has("type"))
@@ -96,7 +100,7 @@ void LLViewerWindowListener::saveSnapshot(const LLSD& event) const
         }
         type = found->second;
     }
-    bool ok = mViewerWindow->saveSnapshot(event["filename"], width, height, showui, rebuild, type);
+    bool ok = mViewerWindow->saveSnapshot(event["filename"], width, height, showui, showhud, rebuild, type);
     sendReply(LLSDMap("ok", ok), event);
 }
 
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index ca1216b89db6790c1eae95f14f5404cc0be26f36..3c4c785a42512548a38525cb3b45dcba29b4e8bb 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -78,6 +78,7 @@
 #include "llselectmgr.h"
 #include "llsprite.h"
 #include "lltargetingmotion.h"
+#include "lltoolmgr.h"
 #include "lltoolmorph.h"
 #include "llviewercamera.h"
 #include "llviewertexlayer.h"
@@ -882,8 +883,9 @@ BOOL LLVOAvatar::hasGray() const
 S32 LLVOAvatar::getRezzedStatus() const
 {
 	if (getIsCloud()) return 0;
-	if (isFullyTextured() && allBakedTexturesCompletelyDownloaded()) return 3;
-	if (isFullyTextured()) return 2;
+	bool textured = isFullyTextured();
+	if (textured && allBakedTexturesCompletelyDownloaded()) return 3;
+	if (textured) return 2;
 	llassert(hasGray());
 	return 1; // gray
 }
@@ -2044,8 +2046,10 @@ void LLVOAvatar::resetSkeleton(bool reset_animations)
         LL_ERRS() << "Error resetting skeleton" << LL_ENDL;
 	}
 
-    // Reset attachment points (buildSkeleton only does bones and CVs)
-    bool ignore_hud_joints = true;
+    // Reset attachment points
+    // BuildSkeleton only does bones and CVs but we still need to reinit huds
+    // since huds can be animated.
+    bool ignore_hud_joints = !isSelf();
     initAttachmentPoints(ignore_hud_joints);
 
     // Fix up collision volumes
@@ -4803,6 +4807,15 @@ U32 LLVOAvatar::renderSkinned()
 		BOOL first_pass = TRUE;
 		if (!LLDrawPoolAvatar::sSkipOpaque)
 		{
+			if (isUIAvatar() && mIsDummy)
+			{
+				LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR);
+				if (hair_mesh)
+				{
+					num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy);
+				}
+				first_pass = FALSE;
+			}
 			if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
 			{
 				if (isTextureVisible(TEX_HEAD_BAKED) || isUIAvatar())
@@ -4810,7 +4823,7 @@ U32 LLVOAvatar::renderSkinned()
 					LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD);
 					if (head_mesh)
 					{
-						num_indices += head_mesh->render(mAdjustedPixelArea, TRUE, mIsDummy);
+						num_indices += head_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy);
 					}
 					first_pass = FALSE;
 				}
@@ -5646,7 +5659,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
 		}
 		else
 		{
-			LL_WARNS() << "Failed to start motion!" << LL_ENDL;
+			LL_WARNS("Motion") << "Failed to start motion!" << LL_ENDL;
 		}
 	}
 	else //stop animation
@@ -5753,13 +5766,13 @@ LLUUID LLVOAvatar::remapMotionID(const LLUUID& id)
 //-----------------------------------------------------------------------------
 BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
 {
-	LL_DEBUGS() << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
+	LL_DEBUGS("Motion") << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
 
 	LLUUID remap_id = remapMotionID(id);
 
 	if (remap_id != id)
 	{
-		LL_DEBUGS() << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
+		LL_DEBUGS("Motion") << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
 	}
 
 	if (isSelf() && remap_id == ANIM_AGENT_AWAY)
@@ -5775,13 +5788,13 @@ BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
 //-----------------------------------------------------------------------------
 BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate)
 {
-	LL_DEBUGS() << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
+	LL_DEBUGS("Motion") << "Motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
 
 	LLUUID remap_id = remapMotionID(id);
 	
 	if (remap_id != id)
 	{
-		LL_DEBUGS() << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
+		LL_DEBUGS("Motion") << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
 	}
 
 	if (isSelf())
@@ -6575,7 +6588,7 @@ void LLVOAvatar::initAttachmentPoints(bool ignore_hud_joints)
         LLAvatarXmlInfo::LLAvatarAttachmentInfo *info = *iter;
         if (info->mIsHUDAttachment && (!isSelf() || ignore_hud_joints))
         {
-		    //don't process hud joint for other avatars, or when doing a skeleton reset.
+		    //don't process hud joint for other avatars.
             continue;
         }
 
@@ -7320,6 +7333,19 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
 		{
 			gAgentCamera.changeCameraToMouselook();
 		}
+
+        if (gAgentCamera.getFocusOnAvatar() && LLToolMgr::getInstance()->inEdit())
+        {
+            LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+            if (node && node->mValid)
+            {
+                LLViewerObject* root_object = node->getObject();
+                if (root_object == sit_object)
+                {
+                    LLFloaterTools::sPreviousFocusOnAvatar = true;
+                }
+            }
+        }
 	}
 
 	if (mDrawable.isNull())
@@ -7600,14 +7626,13 @@ bool LLVOAvatar::getIsCloud() const
 			);
 }
 
-void LLVOAvatar::updateRezzedStatusTimers()
+void LLVOAvatar::updateRezzedStatusTimers(S32 rez_status)
 {
 	// State machine for rezzed status. Statuses are -1 on startup, 0
 	// = cloud, 1 = gray, 2 = downloading, 3 = full.
 	// Purpose is to collect time data for each it takes avatar to reach
 	// various loading landmarks: gray, textured (partial), textured fully.
 
-	S32 rez_status = getRezzedStatus();
 	if (rez_status != mLastRezzedStatus)
 	{
 		LL_DEBUGS("Avatar") << avString() << "rez state change: " << mLastRezzedStatus << " -> " << rez_status << LL_ENDL;
@@ -7777,8 +7802,13 @@ void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapse
 // returns true if the value has changed.
 BOOL LLVOAvatar::updateIsFullyLoaded()
 {
-	const bool loading = getIsCloud();
-	updateRezzedStatusTimers();
+	S32 rez_status = getRezzedStatus();
+	bool loading = getIsCloud();
+	if (mFirstFullyVisible && !mIsControlAvatar && rez_status < 3)
+	{
+		loading = ((rez_status < 2) || !isFullyBaked());
+	}
+	updateRezzedStatusTimers(rez_status);
 	updateRuthTimer(loading);
 	return processFullyLoadedChange(loading);
 }
@@ -7814,13 +7844,22 @@ void LLVOAvatar::updateRuthTimer(bool loading)
 
 BOOL LLVOAvatar::processFullyLoadedChange(bool loading)
 {
-	// we wait a little bit before giving the all clear,
-	// to let textures settle down
-	const F32 PAUSE = 1.f;
+	// We wait a little bit before giving the 'all clear', to let things to
+	// settle down (models to snap into place, textures to get first packets)
+	const F32 LOADED_DELAY = 1.f;
+	const F32 FIRST_USE_DELAY = 3.f;
+
 	if (loading)
 		mFullyLoadedTimer.reset();
-	
-	mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > PAUSE);
+
+	if (mFirstFullyVisible)
+	{
+		mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > FIRST_USE_DELAY);
+	}
+	else
+	{
+		mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > LOADED_DELAY);
+	}
 
 	if (!mPreviousFullyLoaded && !loading && mFullyLoaded)
 	{
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 00dccc5d1215c66a7503f61109583bb79b96c403..e352a6c1fafccb82d624eb53ef3b8dd73f2de7e7 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -348,7 +348,7 @@ class LLVOAvatar :
 	BOOL			isFullyTextured() const;
 	BOOL			hasGray() const; 
 	S32				getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = textured, 3 = textured and fully downloaded.
-	void			updateRezzedStatusTimers();
+	void			updateRezzedStatusTimers(S32 status);
 
 	S32				mLastRezzedStatus;
 
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 63ace4fe5298931dcd190779cc4673915ef77700..16b27fd1445cd3283639c6087b3d50e7d5396f2a 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -1250,7 +1250,7 @@ BOOL LLVOAvatarSelf::detachAttachmentIntoInventory(const LLUUID &item_id)
 		gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
 		gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
 		gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id);
-		gMessageSystem->sendReliable(gAgent.getRegion()->getHost());
+		gMessageSystem->sendReliable(gAgent.getRegionHost());
 		
 		// This object might have been selected, so let the selection manager know it's gone now
 		LLViewerObject *found_obj = gObjectList.findObject(item_id);
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index d8c8cb04614f5d6e414f108435871484f9542890..fca8de7410c354a8e87101b5cecdec6ca70f0798 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -125,7 +125,7 @@ LLVoiceClient::LLVoiceClient(LLPumpIO *pump)
 	mPTTDirty(true),
 	mPTT(true),
 	mUsePTT(true),
-	mPTTIsMiddleMouse(false),
+	mPTTMouseButton(0),
 	mPTTKey(0),
 	mPTTIsToggle(false),
 	mUserPTTState(false),
@@ -200,8 +200,6 @@ const LLVoiceVersionInfo LLVoiceClient::getVersion()
 void LLVoiceClient::updateSettings()
 {
 	setUsePTT(gSavedSettings.getBOOL("PTTCurrentlyEnabled"));
-	std::string keyString = gSavedSettings.getString("PushToTalkButton");
-	setPTTKey(keyString);
 	setPTTIsToggle(gSavedSettings.getBOOL("PushToTalkToggle"));
 	mDisableMic = gSavedSettings.getBOOL("VoiceDisableMic");
 
@@ -637,23 +635,6 @@ bool LLVoiceClient::getPTTIsToggle()
 	return mPTTIsToggle;
 }
 
-void LLVoiceClient::setPTTKey(std::string &key)
-{
-	if(key == "MiddleMouse")
-	{
-		mPTTIsMiddleMouse = true;
-	}
-	else
-	{
-		mPTTIsMiddleMouse = false;
-		if(!LLKeyboard::keyFromString(key, &mPTTKey))
-		{
-			// If the call failed, don't match any key.
-			key = KEY_NONE;
-		}
-	}
-}
-
 void LLVoiceClient::inputUserControlState(bool down)
 {
 	if(mPTTIsToggle)
@@ -674,43 +655,6 @@ void LLVoiceClient::toggleUserPTTState(void)
 	setUserPTTState(!getUserPTTState());
 }
 
-void LLVoiceClient::keyDown(KEY key, MASK mask)
-{	
-	if (gKeyboard->getKeyRepeated(key))
-	{
-		// ignore auto-repeat keys                                                                         
-		return;
-	}
-	
-	if (!mPTTIsMiddleMouse && LLAgent::isActionAllowed("speak") && (key == mPTTKey))
-	{
-		bool down = gKeyboard->getKeyDown(mPTTKey);
-		if (down)
-		{
-			inputUserControlState(down);
-		}
-	}
-	
-}
-void LLVoiceClient::keyUp(KEY key, MASK mask)
-{
-	if (!mPTTIsMiddleMouse && (key == mPTTKey))
-	{
-		bool down = gKeyboard->getKeyDown(mPTTKey);
-		if (!down)
-		{
-			inputUserControlState(down);
-		}
-	}
-}
-void LLVoiceClient::middleMouseState(bool down)
-{
-	if(mPTTIsMiddleMouse && LLAgent::isActionAllowed("speak"))
-	{
-		inputUserControlState(down);
-	}
-}
-
 
 //-------------------------------------------
 // nearby speaker accessors
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index f95b853c31daf475ee8b2936e639189576e14cda..cecaac7f856421e7e9a9ac6409e9b692d045ed80 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -408,17 +408,11 @@ class LLVoiceClient: public LLParamSingleton<LLVoiceClient>
 	void setUsePTT(bool usePTT);
 	void setPTTIsToggle(bool PTTIsToggle);
 	bool getPTTIsToggle();	
-	void setPTTKey(std::string &key);
-	
+
 	void updateMicMuteLogic();
-	
+
 	BOOL lipSyncEnabled();
-	
-	// PTT key triggering
-	void keyDown(KEY key, MASK mask);
-	void keyUp(KEY key, MASK mask);
-	void middleMouseState(bool down);
-	
+
 	boost::signals2::connection MicroChangedCallback(const micro_changed_signal_t::slot_type& cb ) { return mMicroChangedSignal.connect(cb); }
 
 	
@@ -486,7 +480,7 @@ class LLVoiceClient: public LLParamSingleton<LLVoiceClient>
 	bool		mPTT;
 	
 	bool		mUsePTT;
-	bool		mPTTIsMiddleMouse;
+	S32			mPTTMouseButton;
 	KEY			mPTTKey;
 	bool		mPTTIsToggle;
 	bool		mUserPTTState;
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 739f7bd47cb340687760bc8a5937d746d14cce30..530adb89754d943579a40e5b2d4af9ea80dda3cc 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -5158,6 +5158,7 @@ void LLVivoxVoiceClient::setVoiceEnabled(bool enabled)
 		{
 			// Turning voice off looses your current channel -- this makes sure the UI isn't out of sync when you re-enable it.
 			LLVoiceChannel::getCurrentVoiceChannel()->deactivate();
+			gAgent.setVoiceConnected(false);
 			status = LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED;
 		}
 
diff --git a/indra/newview/llwindowlistener.cpp b/indra/newview/llwindowlistener.cpp
index 9e4297baafc13a903d8ae97dc6436cd11d8aed51..aa8c79b0d280a89e6cb30860017f94c18cc854aa 100644
--- a/indra/newview/llwindowlistener.cpp
+++ b/indra/newview/llwindowlistener.cpp
@@ -37,7 +37,7 @@
 #include "llview.h"
 #include "llviewinject.h"
 #include "llviewerwindow.h"
-#include "llviewerkeyboard.h"
+#include "llviewerinput.h"
 #include "llrootview.h"
 #include "llsdutil.h"
 #include "stringize.h"
@@ -279,7 +279,7 @@ void LLWindowListener::keyDown(LLSD const & evt)
 			response.setResponse(target_view->getInfo());
 			
 			gFocusMgr.setKeyboardFocus(target_view);
-			gViewerKeyboard.handleKey(key, mask, false);
+			gViewerInput.handleKey(key, mask, false);
 			if(key < 0x80) mWindow->handleUnicodeChar(key, mask);
 		}
 		else 
@@ -291,7 +291,7 @@ void LLWindowListener::keyDown(LLSD const & evt)
 	}
 	else 
 	{
-		gViewerKeyboard.handleKey(key, mask, false); 
+		gViewerInput.handleKey(key, mask, false); 
 		if(key < 0x80) mWindow->handleUnicodeChar(key, mask);
 	}
 }
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 9bc3a2a33bc59b3e838e64d53daf3b320afa5f0f..a6df0792233581c1aabe4c1c268298b99a0003c4 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -1154,7 +1154,7 @@ void LLWorldMapView::drawAvatar(F32 x_pixels,
 {
 	const F32 HEIGHT_THRESHOLD = 7.f;
 	LLUIImagePtr dot_image = sAvatarLevelImage;
-	if (unknown_relative_z)
+	if (unknown_relative_z && llabs(relative_z) > HEIGHT_THRESHOLD)
 	{
 		dot_image = sAvatarUnknownImage;
 	}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index bd73c234a6a40d2f90fdcd13f702eea8937b2ce9..eb2d3bf8737714a4e9a16764cbb8c667a7425e3f 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -973,7 +973,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 			mDeferredLight.release();
 		}
 
-		F32 scale = RenderShadowResolutionScale;
+		F32 scale = llmax(0.f, RenderShadowResolutionScale);
 
 		if (shadow_detail > 0)
 		{ //allocate 4 sun shadow maps
@@ -8685,8 +8685,8 @@ void LLPipeline::renderDeferredLighting()
 					}
 
 					const LLViewerObject *vobj = drawablep->getVObj();
-					if(vobj && vobj->getAvatar()
-						&& (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList()))
+					if((vobj && vobj->getAvatar() && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList()))
+						|| (vobj && dist_vec(vobj->getPosition(), LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip))
 					{
 						continue;
 					}
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 5aba0546f3cd042c79bb67d9feebe23232f37b1a..9b18dbc2e26a069e38081b37da7ccad791d91908 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -144,7 +144,6 @@ with the same filename but different name
   <texture name="Command_MiniCart_Icon"     file_name="toolbar_icons/mini_cart.png"    preload="true" />
   <texture name="Command_MiniMap_Icon"      file_name="toolbar_icons/mini_map.png"     preload="true" />
   <texture name="Command_Move_Icon"         file_name="toolbar_icons/move.png"         preload="true" />
-  <texture name="Command_Outbox_Icon"       file_name="toolbar_icons/outbox.png"       preload="true" />
   <texture name="Command_People_Icon"       file_name="toolbar_icons/people.png"       preload="true" />
   <texture name="Command_Picks_Icon"        file_name="toolbar_icons/picks.png"        preload="true" />
   <texture name="Command_Places_Icon"       file_name="toolbar_icons/places.png"       preload="true" />
diff --git a/indra/newview/skins/default/xui/de/floater_about_land.xml b/indra/newview/skins/default/xui/de/floater_about_land.xml
index 4dd64cba2ae0b3f29428270db4d151baa5dec74e..8f55b3297f57ca1c5fceee9c70055fcd761ecb57 100644
--- a/indra/newview/skins/default/xui/de/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/de/floater_about_land.xml
@@ -30,7 +30,7 @@
 	<floater.string name="Always">
 		Immer
 	</floater.string>
-	<tab_container name="landtab" tab_min_width="40" width="489">
+	<tab_container name="landtab" tab_min_width="40">
 		<panel label="ALLGEMEIN" name="land_general_panel">
 			<panel.string name="new users only">
 				Nur neue Benutzer
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_chat.xml b/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
index 550a99fe0a5aff8c0e233bddfb4b13a65ba11fd2..51c82c97f88cfc1793d4a1740102fe246b8bcbee 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
@@ -13,7 +13,7 @@
 			<item label="Mittel" name="Medium" value="1"/>
 			<item label="Groß" name="Large" value="2"/>
 		</combo_box>
-		<check_box label="Blasen-Chat" name="bubble_text_chat"/>
+		<check_box label="Blasen-Chat" name="bubble_text_chat" left_delta="8"/>
 	</panel>
 	<panel name="im_notification_settings">
 		<text name="friend_ims">
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml
index ff0a6614bd9bd5f2cc5bc838c468f08e608c9c61..e0aa9fe4a97ab2fe765ba8405772a537fa44ae35 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml
@@ -3,10 +3,10 @@
 	<text name="preset_text">
 		(Keine)
 	</text>
-	<text name="QualitySpeed">
+	<text name="QualitySpeed" top_delta="20">
 		Qualität und Geschwindigkeit:
 	</text>
-	<text name="ShadersPrefText">
+	<text name="ShadersPrefText" top_delta="15">
 		Niedrig
 	</text>
 	<text name="ShadersPrefText2">
diff --git a/indra/newview/skins/default/xui/en/control_table_contents.xml b/indra/newview/skins/default/xui/en/control_table_contents.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7b777befeef631c77b6a76e33fb21ecb609e858f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/control_table_contents.xml
@@ -0,0 +1,625 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<contents>
+    <columns
+     relative_width="0.34"
+     label="Action"
+     name="lst_action" />
+    <columns
+     relative_width="0.22"
+     label="Primary Control"
+     name="lst_ctrl1" />
+    <columns
+     relative_width="0.22"
+     label="Alternate 1"
+     name="lst_ctrl2" />
+    <columns
+     relative_width="0.22"
+     label="Alternate 2"
+     name="lst_ctrl3" />
+    <rows
+     enabled="false"
+     name="move_actions"
+     value="">
+        <columns
+         type="icontext"
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         label="Move Actions"
+         name="lst_action"
+         value="Move_Walk_Off" />
+    </rows>
+    <rows
+     name="walk_to"
+     value="walk_to">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         tool_tip="Walk to location mouse cursor points to"
+         value="Walk to" />
+    </rows>
+    <rows
+     name="teleport_to"
+     value="teleport_to">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         tool_tip="Teleport to location mouse cursor points to, but not all locations allow direct teleportation so you might be teleported closer to destination instead"
+         value="Teleport to" />
+    </rows>
+    <rows
+     name="push_forward"
+     value="push_forward">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Move Forward" />
+    </rows>
+    <rows
+     name="push_backward"
+     value="push_backward">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Move Backward" />
+    </rows>
+    <rows
+     name="turn_left"
+     value="turn_left">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Left" />
+    </rows>
+    <rows
+     name="turn_right"
+     value="turn_right">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Right" />
+    </rows>
+    <rows
+     name="slide_left"
+     value="slide_left">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Strafe left" />
+    </rows>
+    <rows
+     name="slide_right"
+     value="slide_right">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Strafe right" />
+    </rows>
+    <rows
+     name="jump"
+     value="jump">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Jump/Up" />
+    </rows>
+    <rows
+     name="push_down"
+     value="push_down">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Down" />
+    </rows>
+    <rows
+     name="run_forward"
+     value="run_forward">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Run Forward" />
+    </rows>
+    <rows
+     name="run_backward"
+     value="run_backward">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Run Backward" />
+    </rows>
+    <rows
+     name="run_left"
+     value="run_left">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Run Left" />
+    </rows>
+    <rows
+     name="run_right"
+     value="run_right">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Run Right" />
+    </rows>
+    <rows
+     name="toggle_run"
+     value="toggle_run">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Toggle Run" />
+    </rows>
+    <rows
+     name="toggle_fly"
+     value="toggle_fly">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Fly/Stop flying" />
+    </rows>
+    <rows
+     name="toggle_sit"
+     value="toggle_sit">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Sit/Stand" />
+    </rows>
+    <rows
+     name="stop_moving"
+     value="stop_moving">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Stop Moving" />
+    </rows>
+    <rows
+     enabled="false">
+        <columns
+         type="icon"
+         color="0 0 0 0.7"
+         halign="center"
+         value="menu_separator" />
+    </rows>
+    <rows
+     enabled="false"
+     name="camera_actions"
+     value="">
+        <columns
+         type="icontext"
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         label="Camera"
+         name="lst_action"
+         value="Cam_FreeCam_Off" />
+    </rows>
+    <rows
+     name="look_up"
+     value="look_up">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Look Up" />
+    </rows>
+    <rows
+     name="look_down"
+     value="look_down">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Look Down" />
+    </rows>
+    <rows
+     name="move_forward"
+     value="move_forward">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Forward" />
+    </rows>
+    <rows
+     name="move_backward"
+     value="move_backward">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Backward" />
+    </rows>
+    <rows
+     name="move_forward_fast"
+     value="move_forward_fast">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Forward Fast" />
+    </rows>
+    <rows
+     name="move_backward_fast"
+     value="move_backward_fast">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Backward Fast" />
+    </rows>
+    <rows
+     name="move_forward_sitting"
+     value="move_forward_sitting">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Forward Sitting" />
+    </rows>
+    <rows
+     name="move_backward_sitting"
+     value="move_backward_sitting">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Backward Sitting" />
+    </rows>
+    <rows
+     name="spin_over"
+     value="spin_over">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Spin Over" />
+    </rows>
+    <rows
+     name="spin_under"
+     value="spin_under">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Spin Under" />
+    </rows>
+    <rows
+     name="spin_over_sitting"
+     value="spin_over_sitting">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Spin Over" />
+    </rows>
+    <rows
+     name="spin_under_sitting"
+     value="spin_under_sitting">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Spin Under" />
+    </rows>
+    <rows
+     name="pan_up"
+     value="pan_up">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Pan Up" />
+    </rows>
+    <rows
+     name="pan_down"
+     value="pan_down">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Pan Down" />
+    </rows>
+    <rows
+     name="pan_left"
+     value="pan_left">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Pan Left" />
+    </rows>
+    <rows
+     name="pan_right"
+     value="pan_right">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Pan Right" />
+    </rows>
+    <rows
+     name="pan_in"
+     value="pan_in">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Pan In" />
+    </rows>
+    <rows
+     name="pan_out"
+     value="pan_out">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Pan Out" />
+    </rows>
+    <rows
+     name="spin_around_ccw"
+     value="spin_around_ccw">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         tool_tip="Camera spin around counterclockwise"
+         value="Counterclockwise" />
+    </rows>
+    <rows
+     name="spin_around_cw"
+     value="spin_around_cw">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         tool_tip="Camera spin around clockwise"
+         value="Clockwise" />
+    </rows>
+    <rows
+     name="spin_around_ccw_sitting"
+     value="spin_around_ccw_sitting">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         tool_tip="Camera spin around counterclockwise sitting"
+         value="Counterclockwise Sitting" />
+    </rows>
+    <rows
+     name="spin_around_cw_sitting"
+     value="spin_around_cw_sitting">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         tool_tip="Camera spin around clockwise sitting"
+         value="Clockwise Sitting" />
+    </rows>
+    <rows
+     enabled="false">
+        <columns
+         type="icon"
+         color="0 0 0 0.7"
+         halign="center"
+         value="menu_separator" />
+    </rows>
+    <rows
+     enabled="false"
+     name="editing_actions"
+     value="">
+        <columns
+         type="icontext"
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         label="Editing"
+         name="lst_action"
+         value="Tool_Dozer" />
+    </rows>
+    <rows
+     name="edit_avatar_spin_ccw"
+     value="edit_avatar_spin_ccw">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         tool_tip="Camera spin around avatar counterclockwise"
+         value="Counterclockwise" />
+    </rows>
+    <rows
+     name="edit_avatar_spin_cw"
+     value="edit_avatar_spin_cw">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         tool_tip="Camera spin around avatar clockwise"
+         value="Clockwise" />
+    </rows>
+    <rows
+     name="edit_avatar_spin_over"
+     value="edit_avatar_spin_over">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         tool_tip="Camera spin over avatar"
+         value="Camera Spin Over" />
+    </rows>
+    <rows
+     name="edit_avatar_spin_under"
+     value="edit_avatar_spin_under">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         tool_tip="Camera spin under avatar"
+         value="Camera Spin Under" />
+    </rows>
+    <rows
+     name="edit_avatar_move_forward"
+     value="edit_avatar_move_forward">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Forward" />
+    </rows>
+    <rows
+     name="edit_avatar_move_backward"
+     value="edit_avatar_move_backward">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Camera Backward" />
+    </rows>
+    <rows
+     enabled="false">
+        <columns
+         type="icon"
+         color="0 0 0 0.7"
+         halign="center"
+         value="menu_separator" />
+    </rows>
+    <rows
+     enabled="false"
+     name="media_actions"
+     value="">
+        <columns
+         type="icontext"
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         label="Sound and Media"
+         name="lst_action"
+         value="Audio_Press" />
+    </rows>
+    <rows
+     name="toggle_pause_media"
+     value="toggle_pause_media">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Play/Pause Media" />
+    </rows>
+    <rows
+     name="toggle_enable_media"
+     value="toggle_enable_media">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Play/Stop All Media" />
+    </rows>
+    <rows
+     name="voice_follow_key"
+     value="voice_follow_key">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Voice" />
+    </rows>
+    <rows
+     name="toggle_voice"
+     value="toggle_voice">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Toggle Voice" />
+    </rows>
+    <rows
+     name="start_chat"
+     value="start_chat">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Start Chat" />
+    </rows>
+    <rows
+     name="start_gesture"
+     value="start_gesture">
+        <columns
+         column="lst_action"
+         font="SansSerif"
+         halign="left"
+         name="lst_action"
+         value="Start Gesture" />
+    </rows>
+</contents>
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 9f853fd960032489b51aa10169fd5cff2818da9b..a143adfa0633dacff99563e04d2ab849941fa685 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -1800,7 +1800,7 @@ Only large parcels can be listed in search.
                 Music URL:
             </text>
             <line_editor
-             follows="left|top"
+             follows="left|top|right"
              height="23"
              layout="topleft"
              left="100"
diff --git a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
index bac3ea86f1fa7a59f7ecb4acea6585e3903f082d..6540f5e3488726c8a77b958d081dd54e10650ebe 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
@@ -28,11 +28,13 @@
      name="scroll_content_panel"
      follows="left|top"
      min_height="300"
+     min_width="300"
      layout="topleft"
      top="0"
      background_visible="false"
      left="0"
-	 height="680">
+     height="1165"
+     width="1015">
     <text
      type="string"
      length="1"
@@ -102,6 +104,14 @@ Textures
      name="hair_alpha"
      top_delta="0"
      width="92" />
+    <texture_picker
+     height="103"
+     label="Hair Tattoo"
+     layout="topleft"
+     left_pad="7"
+     name="hair_tattoo"
+     top_delta="0"
+     width="92" />
 
     <texture_picker
      height="103"
@@ -135,6 +145,14 @@ Textures
      name="head_tattoo"
      top_delta="0"
      width="92" />
+    <texture_picker
+     height="103"
+     label="Head Unv Tattoo"
+     layout="topleft"
+     left_pad="7"
+     name="head_universal_tattoo"
+     top_delta="0"
+     width="92" />
 
     <texture_picker
      height="103"
@@ -160,6 +178,14 @@ Textures
      name="eyes_alpha"
      top_delta="0"
      width="92" />
+    <texture_picker
+     height="103"
+     label="Eyes Tattoo"
+     layout="topleft"
+     left_pad="7"
+     name="eyes_tattoo"
+     top_delta="0"
+     width="92" />
 
     <texture_picker
      height="103"
@@ -225,6 +251,14 @@ Textures
      name="upper_tattoo"
      top_delta="0"
      width="92" />
+    <texture_picker
+     height="103"
+     label="Upper Unv Tattoo"
+     layout="topleft"
+     left_pad="7"
+     name="upper_universal_tattoo"
+     top_delta="0"
+     width="92" />
 
     <texture_picker
      height="103"
@@ -298,6 +332,14 @@ Textures
      name="lower_tattoo"
      top_delta="0"
      width="92" />
+    <texture_picker
+     height="103"
+     label="Lower Unv Tattoo"
+     layout="topleft"
+     left_pad="7"
+     name="lower_universal_tattoo"
+     top_delta="0"
+     width="92" />
 
     <texture_picker
      height="103"
@@ -315,6 +357,99 @@ Textures
      name="skirt"
      top_delta="0"
      width="92" />
+    <texture_picker
+     height="103"
+     label="Skirt Tattoo"
+     layout="topleft"
+     left_pad="7"
+     name="skirt_tattoo"
+     top_delta="0"
+     width="92" />
+
+    <texture_picker
+     height="103"
+     label="Left Arm"
+     layout="topleft"
+     left="10"
+     name="leftarm-baked"
+     top_delta="100"
+     width="92" />
+    <texture_picker
+     height="103"
+     label="Left Arm Tattoo"
+     layout="topleft"
+     left_pad="21"
+     name="leftarm_tattoo"
+     top_delta="0"
+     width="92" />
+
+    <texture_picker
+     height="103"
+     label="Left Leg"
+     layout="topleft"
+     left="10"
+     name="leftleg-baked"
+     top_delta="100"
+     width="92" />
+    <texture_picker
+     height="103"
+     label="Left Leg Tattoo"
+     layout="topleft"
+     left_pad="21"
+     name="leftleg_tattoo"
+     top_delta="0"
+     width="92" />
+
+    <texture_picker
+     height="103"
+     label="AUX 1"
+     layout="topleft"
+     left="10"
+     name="aux1-baked"
+     top_delta="100"
+     width="92" />
+    <texture_picker
+     height="103"
+     label="AUX 1 Tattoo"
+     layout="topleft"
+     left_pad="21"
+     name="aux1_tattoo"
+     top_delta="0"
+     width="92" />
+
+    <texture_picker
+     height="103"
+     label="AUX 2"
+     layout="topleft"
+     left="10"
+     name="aux2-baked"
+     top_delta="100"
+     width="92" />
+    <texture_picker
+     height="103"
+     label="AUX 2 Tattoo"
+     layout="topleft"
+     left_pad="21"
+     name="aux2_tattoo"
+     top_delta="0"
+     width="92" />
+
+    <texture_picker
+     height="103"
+     label="AUX 3"
+     layout="topleft"
+     left="10"
+     name="aux3-baked"
+     top_delta="100"
+     width="92" />
+    <texture_picker
+     height="103"
+     label="AUX 3 Tattoo"
+     layout="topleft"
+     left_pad="21"
+     name="aux3_tattoo"
+     top_delta="0"
+     width="92" />
 </panel>
 </panel>
 </scroll_container>
diff --git a/indra/newview/skins/default/xui/en/floater_forget_user.xml b/indra/newview/skins/default/xui/en/floater_forget_user.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f2e894733fced87a59d0b4a3d7ccd3b22093c666
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_forget_user.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="258"
+ layout="topleft"
+ name="groups"
+ help_topic="forget_username"
+ title="REMEMBERED USERNAMES"
+ width="280">
+    <scroll_list
+     height="173"
+     layout="topleft"
+     left="12"
+     name="user_list"
+     top="24"
+     width="256">
+        <scroll_list.columns
+         name="user"
+         width="248" />
+    </scroll_list>
+    <button
+     height="20"
+     label="Forget"
+     label_selected="Forget"
+     layout="topleft"
+     left_delta="90"
+     name="forget"
+     top_pad="8"
+     width="80" />
+    <check_box
+     height="20"
+     label="Also delete local data for this username"
+     layout="topleft"
+     left="15"
+     name="delete_data"
+     top_pad="5"
+     width="260"
+     initial_value="1"
+     tooltip="Deletes local files: chat history, last session screenshot, browser cookies, teleport history, toolbar settings, e t c"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
deleted file mode 100644
index 7802f65902e5f4452ec1a37112ad5ef0a66ce712..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<floater
-    positioning="cascading"
-    can_close="true"
-    can_resize="true"
-    height="440"
-    help_topic="floater_merchant_outbox"
-    min_width="300"
-    min_height="200"
-    name="floater_merchant_outbox"
-    save_rect="true"
-    save_visibility="false"
-    reuse_instance="true"
-    title="MERCHANT OUTBOX"
-    width="333">
-  <string name="OutboxFolderCount0"></string>
-  <string name="OutboxFolderCount1">1 folder</string>
-  <string name="OutboxFolderCountN">[NUM] folders</string>
-  <string name="OutboxImporting">Sending folders...</string>
-  <string name="OutboxInitializing">Initializing...</string>
-  <panel
-      name="panel_1"
-      follows="all"
-      layout="topleft"
-      left="0"
-      top="0"
-      label=""
-      height="440"
-      width="333">
-    <panel
-        name="panel_2"
-        follows="all"
-        left="10"
-        bottom="370"
-        width="313"
-        top="0"
-        bg_opaque_color="InventoryBackgroundColor">
-      <panel
-          name="outbox_inventory_placeholder_panel"
-          follows="all"
-          layout="topleft"
-          top="0"
-          left="0"
-          width="308"
-          height="370"
-          bg_opaque_color="InventoryBackgroundColor">
-        <text
-            name="outbox_inventory_placeholder_title"
-            type="string"
-            follows="top|left|right"
-            layout="topleft"
-            top="10"
-            left="0"
-            width="308"
-            height="25"
-            wrap="true"
-            halign="center"
-            font="SansSerifBold">
-          Loading...
-        </text>
-        <text
-            name="outbox_inventory_placeholder_text"
-            type="string"
-            follows="top|left|right"
-            layout="topleft"
-            top="35"
-            left="0"
-            width="308"
-            height="130"
-            wrap="true"
-            halign="left" />
-      </panel>
-    </panel>
-    <panel
-        name="panel_3"
-        follows="bottom|left|right"
-        left="10"
-        bottom="435"
-        width="313"
-        top="370">
-      <panel
-          name="outbox_generic_drag_target"
-          mouse_opaque="false"
-          follows="all"
-          top="5"
-          left="5"
-          width="303"
-          height="25"
-          background_visible="false"
-          bg_alpha_color="EmphasisColor_35"
-          border="true"
-          bevel_style="in"
-          visible="true">
-        <text
-            name="text_1"
-            type="string"
-            follows="all"
-            layout="topleft"
-            top="6"
-            height="20"
-            left="5"
-            width="293"
-            halign="center"
-            font="SansSerifMedium"
-            font_shadow="hard"
-            valign="top">
-          Drag items here to create folders
-        </text>
-      </panel>
-      <text
-          name="outbox_folder_count"
-          type="string"
-          follows="all"
-          layout="topleft"
-          top="40"
-          left="5"
-          width="150"
-          height="20"
-          wrap="true"
-          halign="left"
-          valign="center"
-          font="SansSerif"/>
-      <button
-          label="Send to Marketplace"
-          tool_tip="Push to my Marketplace Storefront"
-          is_toggle="false"
-          name="outbox_import_btn"
-          follows="bottom|right"
-          tab_stop="false"
-          halign="center"
-          top="37"
-          left="160"
-          height="25"
-          width="150"
-          enabled="false" />
-    </panel>
-    <layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false">
-      <layout_panel />
-      <layout_panel height="24" auto_resize="false">
-        <layout_stack orientation="horizontal" left="0" height="24" top="0" width="333" follows="all">
-          <layout_panel width="0" />
-          <layout_panel width="24" auto_resize="false">
-            <loading_indicator
-                height="24"
-                layout="topleft"
-                left="0"
-                top="0"
-                width="24" />
-          </layout_panel>
-          <layout_panel width="0" />
-        </layout_stack>
-      </layout_panel>
-      <layout_panel />
-    </layout_stack>
-  </panel>
-</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml
index 0e62d50072eb1940726e1c00a3fa296340d97419..ee730dcb013e1339b6cb5637a9e56d8356c7b3c1 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences.xml
@@ -169,6 +169,13 @@ https://accounts.secondlife.com/change_email/
          layout="topleft"
          help_topic="preferences_uploads_tab"
          name="uploads" />
+        <panel
+         class="panel_preference_controls"
+         filename="panel_preferences_controls.xml"
+         label="Controls"
+         layout="topleft"
+         help_topic="preferences_controls_tab"
+         name="controls" />
     </tab_container>
 
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_trash.xml b/indra/newview/skins/default/xui/en/floater_preview_trash.xml
index 9e50e89ac953b556d4c18aaca44e52247be10dea..3fa71e7bfe024c7f44358481d1c42f48ba48d405 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_trash.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_trash.xml
@@ -14,7 +14,7 @@
  reuse_instance="true"
  can_minimize="false">
   <inventory_panel
-      name="inventory_outbox"
+      name="inventory_trash"
       start_folder.name="Trash"
       show_empty_message="false"
       start_folder.type="trash"
diff --git a/indra/newview/skins/default/xui/en/floater_select_key.xml b/indra/newview/skins/default/xui/en/floater_select_key.xml
index 4e89df5a7352f7770c5058f564e03aa922a0061d..48d9eee4cd456039c4dc1e304f30bc2d2ff7a4d2 100644
--- a/indra/newview/skins/default/xui/en/floater_select_key.xml
+++ b/indra/newview/skins/default/xui/en/floater_select_key.xml
@@ -4,10 +4,27 @@
  border="false"
  can_close="false"
  can_minimize="false"
- height="90"
+ height="116"
  layout="topleft"
  name="modal container"
- width="240">
+ width="272">
+  <floater.string
+   name="keyboard">
+    Keyboard
+  </floater.string>
+  <floater.string
+   name="mouse">
+    Mouse Buttons
+  </floater.string>
+  <floater.string
+   name="basic_description">
+Press a key to set your trigger.
+Allowed input: [INPUT].
+  </floater.string>
+  <floater.string
+   name="reserved_by_menu">
+Combination [KEYSTR] is reserved by menu.
+  </floater.string>
     <text
      type="string"
      halign="center"
@@ -16,19 +33,47 @@
      height="30"
      layout="topleft"
      left="30"
-     name="Save item as:"
+     name="descritption"
      top="25"
      word_wrap="true"
-     width="180">
-        Press a key to set your Speak button trigger.
+     width="212">
+Press a key to set your trigger.
+Allowed input: [INPUT].
     </text>
+    <check_box
+     follows="top|left"
+     height="20"
+     initial_value="false"
+     label="Apply to all"
+     layout="topleft"
+     left="90"
+     name="apply_all"
+     tool_tip="Viewer uses different control combinations depending on what you are doing in world, setting this will apply your change to all combinations"
+     top_pad="8"
+     width="160" />
+  
+    <button
+     height="23"
+     label="Set Empty"
+     layout="topleft"
+     left="8"
+     name="SetEmpty"
+     top_pad="6"
+     width="80" />
+    <button
+     height="23"
+     label="Default"
+     layout="topleft"
+     left_pad="8"
+     name="Default"
+     top_delta="0"
+     width="80" />
     <button
      height="23"
      label="Cancel"
-     label_selected="Cancel"
      layout="topleft"
-     right="-10"
+     left_pad="8"
      name="Cancel"
-     top_pad="8"
-     width="100" />
+     top_delta="0"
+     width="80" />
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
index d122d7491cfaa83e4d725743afff349054c78623..c2af4f54d0e58e2f03c0531a2238efb302f01904 100644
--- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
@@ -93,11 +93,22 @@
      height="14"
      layout="topleft"
      left_delta="12"
+     name="size_lbl"
+     top_pad="4">
+        Size:
+    </text>
+
+    <text
+     type="string"
+     length="1"
+     follows="left|top"
+     height="14"
+     layout="topleft"
+     left_delta="0"
      name="unknown"
      top_pad="4">
-        Size: [DIMENSIONS]
+        [DIMENSIONS]
     </text>
-    
 <!--  middle: inventory mode -->
 
     <button
@@ -139,19 +150,20 @@
      image_unselected="eye_button_inactive.tga"
      layout="topleft"
      left_delta="-80"
-     top_delta="-25"
+     top_delta="-10"
      name="Pipette"
      width="28" />
    <text
      follows="left|bottom"
-     height="20"
+     height="40"
      layout="topleft"
      left="8"
      name="preview_disabled"
-     top="266"
+     top="285"
      value="Preview Disabled"
+     word_wrap="true"
      visible="false"
-     width="120" />
+     width="87" />
     <filter_editor
      follows="left|top|right"
      height="23"
diff --git a/indra/newview/skins/default/xui/en/menu_gesture_gear.xml b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml
index c1458977ca15713a98265f44ca65e8ee015003a0..5cae643e44f5dc9475c354705d7cc08a7c47d0f5 100644
--- a/indra/newview/skins/default/xui/en/menu_gesture_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml
@@ -11,6 +11,16 @@
         <on_click
          function="Gesture.Action.ToogleActiveState" />
     </menu_item_call>
+    <menu_item_call
+     label="Rename"
+     layout="topleft"
+     name="rename">
+        <on_click
+         function="Gesture.Action.Rename" />
+        <on_enable
+         function="Gesture.EnableAction"
+         parameter="rename_gesture" />
+    </menu_item_call>
     <menu_item_call
      label="Copy"
      layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 7bb7b5d62cf2f0b2aa13be6aac1934435420cb65..af185d43b0edca0d0b3c75941851de378d7fa331 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -17,9 +17,11 @@
       </menu_item_call>
       <menu_item_call
        label="Appearance..."
-       name="ChangeOutfit">
+       name="ChangeOutfit"
+       shortcut="control|O">
         <menu_item_call.on_click
-         function="CustomizeAvatar" />
+         function="Floater.ToggleOrBringToFront"
+         parameter="appearance" />
         <menu_item_call.on_enable
          function="Edit.EnableCustomizeAvatar" />
       </menu_item_call>
@@ -152,13 +154,16 @@
           <menu_item_call.on_click
            function="Tools.StopAllAnimations" />
         </menu_item_call>
-        <menu_item_call
+        <menu_item_check
          label="Walk / run / fly..."
          name="WalkRunFly">
-          <menu_item_call.on_click
+          <menu_item_check.on_check
+           function="Floater.Visible"
+           parameter="moveview" />
+          <menu_item_check.on_click
            function="Floater.ToggleOrBringToFront"
            parameter="moveview" />
-        </menu_item_call>
+        </menu_item_check>
       </menu>
 
       <menu
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index f72767ccebe513740db1c1f8d5ea9e75acf472d8..92711d4397055d0988d062f72157f49c230aee3b 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2180,7 +2180,7 @@ Wrong chunk size in WAV file:
    icon="alertmodal.tga"
    name="SoundFileInvalidTooLong"
    type="alertmodal">
-Audio file is too long (10 second maximum):
+Audio file is too long (30 second maximum):
 [FILE]
   <tag>fail</tag>
   </notification>
@@ -2259,6 +2259,7 @@ Unable to create output file: [FILE]
    icon="alertmodal.tga"
    name="DoNotSupportBulkAnimationUpload"
    type="alertmodal">
+    <unique/>
 [APP_NAME] does not currently support bulk upload of BVH format animation files.
   <tag>fail</tag>
   </notification>
@@ -2477,6 +2478,13 @@ Sorry, but the system was unable to complete your teleport request in a timely f
    type="alertmodal">
    <tag>fail</tag>
 Sorry, but the system was unable to complete your region crossing in a timely fashion. Please try again in a few minutes.
+  </notification>
+  <notification
+   icon="alertmodal.tga"
+   name="preexisting_tport"
+   type="alertmodal">
+   <tag>fail</tag>
+Sorry, but the system was unable to start your teleport. Please try again in a few minutes.
   </notification>
   <notification
    icon="alertmodal.tga"
@@ -3091,6 +3099,29 @@ See https://wiki.secondlife.com/wiki/Adding_Spelling_Dictionaries
     </form>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   label="Rename Gesture"
+   name="RenameGesture"
+   type="alertmodal">
+    New gesture name:
+    <tag>confirm</tag>
+    <form name="form">
+      <input name="new_name" type="text" width="300">
+        [NAME]
+      </input>
+      <button
+       default="true"
+       index="0"
+       name="OK"
+       text="OK"/>
+      <button
+       index="1"
+       name="Cancel"
+       text="Cancel"/>
+    </form>
+  </notification>
+  
   <notification
    icon="alertmodal.tga"
    name="RemoveFromFriends"
@@ -3410,6 +3441,9 @@ Display settings have been set to recommended levels because of a change to the
    icon="alertmodal.tga"
    name="ErrorMessage"
    type="alertmodal">
+    <unique>
+      <context>ERROR_MESSAGE</context>
+    </unique>
 [ERROR_MESSAGE]
   <tag>fail</tag>
     <usetemplate
@@ -3545,6 +3579,30 @@ You can either check your Internet connection and try again in a few minutes, cl
     </form>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="LoginPacketNeverReceivedNoTP"
+   type="alertmodal">
+    <tag>fail</tag>
+We&apos;re having trouble connecting. There may be a problem with your Internet connection or the [SECOND_LIFE_GRID].
+
+You can either check your Internet connection and try again in a few minutes or click Help to view the [SUPPORT_SITE].
+    <url option="1" name="url">
+			http://secondlife.com/support/
+    </url>
+    <form name="form">
+      <button
+       default="true"
+       index="0"
+       name="OK"
+       text="OK"/>
+      <button
+       index="1"
+       name="Help"
+       text="Help"/>
+    </form>
+  </notification>
+
   <notification
    icon="alertmodal.tga"
    name="WelcomeChooseSex"
@@ -5998,6 +6056,34 @@ Would you like to turn off Do Not Disturb before completing this transaction?
     </form>
   </notification>
 
+  <notification
+   icon="notify.tga"
+   label="Parcel is Playing Media"
+   name="ParcelPlayingMedia"   
+   persist="false"
+   type="notify">
+This land has media:
+[URL]
+Would you like to play it?
+    <tag>confirm</tag>
+    <form name="form">
+      <ignore name="ignore"
+       checkbox_only="true"
+       text="Always choose this option for this land."/>
+      <button
+       ignore="Play Media"
+       index="1"
+       name="Yes"
+       text="Play"/>
+      <button
+       default="true"
+       ignore="Ignore Media"
+       index="0"
+       name="No"
+       text="Ignore"/>
+    </form>
+  </notification>
+
   <notification
    icon="alertmodal.tga"
    name="ConfirmDeleteProtectedCategory"
@@ -6108,6 +6194,20 @@ Are you sure you want to permanently delete the contents of your Lost And Found?
      yestext="Yes"/>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="ConfirmReplaceLink"
+   type="alertmodal">
+You're about to replace '[TYPE]' body part link with the item which doesn't match the type.
+Are you sure you want to proceed?
+    <tag>confirm</tag>
+    <usetemplate
+     ignoretext="Confirm before I replace link"
+     name="okcancelignore"
+     notext="No"
+     yestext="Yes"/>
+  </notification>
+  
   <notification
    icon="alertmodal.tga"
    name="CopySLURL"
@@ -7026,12 +7126,14 @@ You can only claim public land in the Region you&apos;re in.
   </notification>
 
   <notification
-   icon="notify.tga"
+   icon="alertmodal.tga"
    name="RegionTPAccessBlocked"
-   persist="false"
-   type="notify">
+   type="alertmodal">
    <tag>fail</tag>
     The region you're trying to visit contains content exceeding your current preferences.  You can change your preferences using Me &gt; Preferences &gt; General.
+   <usetemplate
+      name="okbutton"
+      yestext="OK"/>
   </notification>
 
   <notification
@@ -11175,6 +11277,19 @@ Cannot create large prims that intersect other residents.  Please re-try when ot
      notext="Cancel"
      yestext="OK"/>
   </notification>
+  
+  <notification
+   icon="alertmodal.tga"
+   name="PreferenceControlsDefaults"
+   type="alertmodal">
+    Do you want to restore default values for controls?
+    <tag>confirm</tag>
+    <usetemplate
+       canceltext="Cancel"
+       name="yesnocancelbuttons"
+       notext="Current mode"
+       yestext="All modes"/>
+  </notification>
     
   <notification
    icon="alertmodal.tga"
diff --git a/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml b/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml
index 27c653bc354ae3b8ef83f3ab34e83e88051fa716..d1175a9fe18926a444a102af31cbaa8440efead3 100644
--- a/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml
@@ -32,7 +32,6 @@
      width="308"/>
     <texture_picker
      allow_no_texture="true"
-     border_enabled="true"
      fallback_image="default_land_picture.j2c"
      enabled="false"
      follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
index 3509eaa2851f63c77565e724a185bab1e1a9f31a..e846edf1d4b9f7beaa958c135816d3dc75277f3a 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
@@ -144,7 +144,6 @@
          follows="left|top|right"
          height="100"
          width="273"
-         hide_scrollbar="false"
          layout="topleft"
          left="10"
          top_pad="2"
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index 7759d4fdb2975cadfc31b9bf6d426da8a54526a9..d601b36ce55b6ce1f4fc58b17e7f4a7d85ae89f9 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -57,19 +57,15 @@
     combo_editor.prevalidate_callback="ascii"
     tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
     name="username_combo"
-    width="232">
+    width="206">
     <combo_box.combo_editor
       text_pad_left="8" 
       bg_image_always_focused="true"/>
-    <combo_box.combo_button
-      visible="false" />
-    <combo_box.drop_down_button
-      visible="false" />
   </combo_box>
   <line_editor
     follows="left|top"
     height="32"
-    left_pad="-11"
+    left_pad="15"
     max_length_chars="16"
     text_pad_left="8"
     name="password_edit"
@@ -119,36 +115,49 @@
     width="120"
     height="32"
   	left_pad="15"
-    bottom_delta="0" />  
+    bottom_delta="0" />
+  <text
+    follows="left|top"
+    font="SansSerifLarge"
+    font.style="BOLD"
+    text_color="EmphasisColor"
+    height="34"
+    name="sign_up_text"
+    left_pad="10"
+    width="200"
+    valign="center">
+    Sign up
+  </text>
   <check_box
-    control_name="RememberPassword"
     follows="left|top"
     font="SansSerifMedium"
     left="185"
-    bottom_delta="21"  	
+    bottom_delta="21"
     height="24"
     label="Remember me"
     check_button.bottom="3"
-    name="remember_check"
+    name="remember_name"
+    tooltip="Already recorded user can be forgotten from preferences."
     width="145" />
-  <text
+  <check_box
+    control_name="RememberPassword"
     follows="left|top"
     font="SansSerifMedium"
     text_color="EmphasisColor"
     height="16"
-    name="forgot_password_text"
-    left="408"    
+    left="408"
     bottom_delta="0"
-    width="200">
-    Forgotten password
-  </text> 
+    label="Remember password"
+    check_button.bottom="3"
+    name="remember_check"
+    width="145" />
   <combo_box
     allow_text_entry="false"
     font="SansSerifTiny"
     follows="left|top"
     height="26"
   	left="588"
-  	bottom_delta="10"
+  	bottom_delta="8"
     max_chars="128"
     label="Select grid"    
     layout="topleft"
@@ -159,12 +168,13 @@
     font="SansSerifMedium"
     text_color="EmphasisColor"
     height="16"
-    name="sign_up_text"
+    name="forgot_password_text"
     left="778"
-    bottom_delta="-10"
-    width="200">
-    Sign up
-  </text> 
+    bottom_delta="-8"
+    width="120"
+    halign="center">
+    Password help
+  </text>
   </layout_panel>
   <layout_panel
       height="172"
diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
deleted file mode 100644
index b2d8bb874b642b845130c0d444aab27ee63f1589..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<inventory_panel
-    name="inventory_outbox"
-    start_folder.name="Outbox"
-    show_empty_message="false"
-    start_folder.type="outbox"
-    follows="all" layout="topleft"
-    top="0" left="0" height="165" width="308"
-    top_pad="0"
-    bg_opaque_color="DkGray2"
-    bg_alpha_color="DkGray2"
-    background_visible="true"
-    border="false"
-    bevel_style="none"
-    show_item_link_overlays="true"
-    tool_tip="Drag and drop items here to prepare them for sale on your storefront"
-    scroll.reserve_scroll_corner="false">
-      <folder folder_arrow_image="Folder_Arrow"
-              folder_indentation="8"
-              item_height="20"
-              item_top_pad="4"
-              selection_image="Rounded_Square"
-              left_pad="5"
-              icon_pad="2"
-              icon_width="16"
-              text_pad="1"
-              text_pad_right="4"
-              arrow_size="12"
-              max_folder_item_overlap="2"/>
-      <item allow_wear="false"/>
-</inventory_panel>
diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml
index 79d190e1e09a0e6dea7ae3d190080c2dc6cc333e..99c47eb8257efaf0d6f189b4d17a15c0ff01aa11 100644
--- a/indra/newview/skins/default/xui/en/panel_pick_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml
@@ -103,7 +103,6 @@
          height="100"
          width="280"
          parse_urls="true"	
-         hide_scrollbar="false"
          layout="topleft"
          left="10"
          top_pad="2"
diff --git a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
index 43d580844fb9f61d49abd5403c1c31bf47d6e597..4c0cdd321e16f2879d8d90c2ad3919b288813e77 100644
--- a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
@@ -32,7 +32,6 @@
      width="308" />
     <texture_picker
      allow_no_texture="true"
-     border_enabled="true"
      fallback_image="default_land_picture.j2c"
      enabled="false"
      follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 4f0bb9d3b775cfa3af90215367d6ab7635e803f2..d0518aa2450ebf9ae95267ca7193a090cf0897f6 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -142,6 +142,32 @@
    min_val="0.75"
    name="ui_scale_slider"
    top_pad="-14"
+   width="250" />
+  <text
+  type="string"
+  length="1"
+  follows="left|top"
+  height="12"
+  layout="topleft"
+  left="33"
+  name="HUD Size:"
+  top_pad="20"
+  width="100">
+    HUD Scale:
+  </text>
+  <slider
+   control_name="HUDScaleFactor"
+   decimal_digits="2"
+   follows="left|top"
+   height="17"
+   increment="0.1"
+   initial_value="1"
+   layout="topleft"
+   left_pad="0"
+   max_val="2.0"
+   min_val="1.0"
+   name="ui_scale_slider"
+   top_pad="-14"
    width="250" />
     <check_box
      control_name="ShowScriptErrors"
@@ -222,14 +248,27 @@
      top_pad="5"
      width="237"/>
     <button
+     follows="top|left"
+     layout="topleft"
+     label="Remembered Usernames"
+     name="remembered_usernames"
      height="20"
-     label="Default Creation Permissions"
+     left="30"
+     top_pad="16"
+     width="200">
+    <button.commit_callback
+     function="Pref.RememberedUsernames" />
+  </button>
+  <button
+     follows="top|left"
      layout="topleft"
+     label="Default Creation Permissions"
      name="default_creation_permissions"
+     height="20"
      left="30"
-     top_pad = "20"
-     width="250">
-	<button.commit_callback
-	 function="Pref.PermsDefault" />
+     top_pad="16"
+     width="200">
+    <button.commit_callback
+     function="Pref.PermsDefault" />
   </button>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
index 9e7023d2f2507b123af9137dace39e8516dbaf24..ece6c95080e22da18c5c46f97fb2d33648341f61 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
@@ -99,6 +99,7 @@
         label="Bubble Chat"
         layout="topleft"
         top_pad="4"
+        left_delta="0"
         name="bubble_text_chat"
         width="330">
     </check_box>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_controls.xml b/indra/newview/skins/default/xui/en/panel_preferences_controls.xml
new file mode 100644
index 0000000000000000000000000000000000000000..904387909eef5fb5d599a085b63eef256209cdc0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_controls.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<panel
+ border="true"
+ follows="all"
+ height="408"
+ label="Controls"
+ layout="topleft"
+ left="102"
+ name="controls"
+ top="1"
+ width="517">
+  <combo_box
+   follows="top|left"
+   layout="topleft"
+   top="6"
+   left="10"
+   height="23"
+   width="140"
+   name="key_mode">
+    <combo_box.item
+     label="Third Person "
+     name="third_person"
+     value="1"/>
+    <combo_box.item
+     label="First Person (Mouselook)"
+     name="first_person"
+     value="0"/>
+    <combo_box.item
+     label="Edit Avatar"
+     name="edit_avatar"
+     value="2"/>
+    <combo_box.item
+     label="Sitting"
+     name="sitting"
+     value="3"/>
+  </combo_box>
+
+  <button
+   follows="top|left"
+   layout="topleft"
+   top="6"
+   right="-10"
+   height="23"
+   width="140"
+   label="Restore Defaults"
+   tool_tip="Restores default values for all control modes."
+   name="restore_defaults"/>
+
+  <scroll_list
+   draw_heading="true"
+   follows="all"
+   layout="topleft"
+   column_padding="0"
+   selection_type="header"
+   top="31"
+   left="3"
+   bottom="-3"
+   right="-3"
+   can_sort="false"
+   multi_select="false"
+   name="controls_list"
+   fg_disable_color="ScrollUnselectedColor"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_move.xml b/indra/newview/skins/default/xui/en/panel_preferences_move.xml
index 8794e3bf95ac9d54e4084203b16433e6b5a72208..d106456b31731e972afaa8f7063ba851c8601baf 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_move.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_move.xml
@@ -195,70 +195,6 @@
    name="invert_mouse"
    top_delta="0"
    width="128" />
-  <text
-   follows="left|top"
-   type="string"
-   length="1"
-   height="10"
-   layout="topleft"
-   left="86"
-   name="single_click_action_lbl"
-   width="150"
-   top_pad="20">
-    Single click on land:
-  </text>
-  <combo_box
-   height="23"
-   layout="topleft"
-   left_pad="10"
-   top_delta="-6"
-   name="single_click_action_combo"
-   width="200">
-    <combo_box.item
-     label="No action"
-     name="0"
-     value="0"/>
-    <combo_box.item
-     label="Move to clicked point"
-     name="1"
-     value="1"/>
-    <combo_box.commit_callback
-     function="Pref.ClickActionChange"/>
-  </combo_box>
-  <text
-   follows="left|top"
-   type="string"
-   length="1"
-   height="10"
-   layout="topleft"
-   left="86"
-   name="double_click_action_lbl"
-   width="150"
-   top_pad="12">
-    Double click on land:
-  </text>
-  <combo_box
-   height="23"
-   layout="topleft"
-   left_pad="10"
-   top_delta="-6"
-   name="double_click_action_combo"
-   width="200">
-    <combo_box.item
-     label="No action"
-     name="0"
-     value="0"/>
-    <combo_box.item
-     label="Move to clicked point"
-     name="1"
-     value="1"/>
-    <combo_box.item
-     label="Teleport to clicked point"
-     name="2"
-     value="2"/>
-    <combo_box.commit_callback
-     function="Pref.ClickActionChange"/>
-  </combo_box>
   <button
    height="23"
    label="Other Devices"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index 8f2e81b9f7481538d2a1f607925ec85ad2971eea..c2995393fd78dc00b397936729a00ba9655c1440 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -13,6 +13,14 @@
      name="middle_mouse">
      Middle Mouse
     </panel.string>
+    <panel.string
+     name="button4_mouse">
+     Mouse Button 4
+    </panel.string>
+    <panel.string
+     name="button5_mouse">
+     Mouse Button 5
+    </panel.string>
     <slider
      control_name="AudioLevelMaster"
      follows="left|top"
@@ -314,17 +322,40 @@
 		name="enable_voice_check"
 		width="110"/>
 	<!-- -->
-	<check_box
-		name="media_auto_play_btn"
-		control_name="ParcelMediaAutoPlayEnable"
-		enabled_control="AudioStreamingMedia"
-		value="true"
-		follows="left|bottom|right"
-		height="15"
-		tool_tip="Check this to let media auto-play if it wants"
-		label="Allow Media to auto-play"
-		top_pad="1"
-		left="25"/>
+    <text
+        follows="left|top"
+        layout="topleft"
+        height="15"
+        left="0"
+        top_pad="3"
+        width="120"
+        halign="right"
+        name="media_autoplay_label">
+         Media auto-play
+    </text>
+    <combo_box
+        control_name="ParcelMediaAutoPlayEnable"
+        enabled_control="AudioStreamingMedia"
+        follows="left|top"
+        layout="topleft"
+        height="23"
+        left_pad="7"
+        top_delta="-4"
+        name="media_auto_play_combo"
+        width="100">
+      <item
+          label="Disabled"
+          name="autoplay_disabled"
+          value="0"/>      
+      <item
+          label="Enabled"
+          name="autoplay_enabled"
+          value="1"/>
+      <item
+          label="Ask"
+          name="autoplay_ask"
+          value="2"/>
+    </combo_box>
  	<check_box
 		name="media_show_on_others_btn"
 		control_name="MediaShowOnOthers"
@@ -432,52 +463,13 @@
   enabled_control="EnableVoiceChat"
   control_name="PushToTalkToggle"
   height="15"
-  label="Toggle speak on/off when I press:"
+  label="Toggle speak on/off when I press button in toolbar"
   layout="topleft"
   left="44"
   name="push_to_talk_toggle_check"
   width="237"
   tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down."
   top_pad="3"/>
-  <line_editor
-   follows="top|left"
-   control_name="PushToTalkButton"
-   enabled="false"
-   enabled_control="EnableVoiceChat"
-   height="23"
-   left="80"
-   max_length_bytes="200"
-   name="modifier_combo"
-   label="Push-to-Speak trigger"
-   top_pad="3"
-   width="200" />
-  <button
-   layout="topleft"
-   follows="top|left"
-   enabled_control="EnableVoiceChat"
-   height="23"
-   label="Set Key"
-   left_pad="5"
-   name="set_voice_hotkey_button"
-   width="100">
-    <button.commit_callback
-    function="Pref.VoiceSetKey" />
-  </button>
-  <button
-     enabled_control="EnableVoiceChat"
-     follows="top|left"
-     halign="center"
-     height="23"
-     image_overlay="Refresh_Off"
-     layout="topleft"
-     tool_tip="Reset to Middle Mouse Button"
-     mouse_opaque="true"
-     name="set_voice_middlemouse_button"
-     left_pad="5"
-     width="25">
-    <button.commit_callback
-    function="Pref.VoiceSetMiddleMouse" />
-  </button>
   <button
    control_name="ShowDeviceSettings"
    follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 9eedc45aa9d4533c153c790493661bc396c83577..0594e18c96728de023743c48aa6a57c5fbf23bd9 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2637,6 +2637,7 @@ If you continue to receive this message, please contact Second Life support for
 	<string name="Debits">Debits</string>
 	<string name="Total">Total</string>
 	<string name="NoGroupDataFound">No group data found for group </string>
+	<string name="AlreadyInGroup">You are already in this group </string>
 
 	<!-- floater IM bonus_info: When a Linden with Admin/god status receives a new IM this displays the estate (Mainland vs. teen grid) of the source avatar.
 		This is to help Lindens when answering questions. -->
@@ -2820,7 +2821,7 @@ If you continue to receive this message, please contact Second Life support for
 	<string name="BuyingCosts">Buying this costs L$ [AMOUNT]</string>
 	<string name="UnknownFileExtension">
 		Unknown file extension .%s
-Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh
+Expected .wav, .tga, .bmp, .jpg, .jpeg, or .anim
 	</string>
   <string name="MuteObject2">Block</string>
   <string name="MuteAvatar">Block</string>
@@ -4068,6 +4069,15 @@ Try enclosing path to the editor with double quotes.
   <string name="Z">Z</string>
   <!-- Key names end -->
 
+  <!-- Mouse button names (short) begin -->
+  <string name="LMB">LMB</string>
+  <string name="MMB">MMB</string>
+  <string name="RMB">RMB</string>
+  <string name="MB4">MB4</string>
+  <string name="MB5">MB5</string>
+  <string name="Double LMB">Double LMB</string>
+  <!-- Mouse button names end -->
+
   <!-- llviewerwindow -->
   <string name="BeaconParticle">Viewing particle beacons (blue)</string>
   <string name="BeaconPhysical">Viewing physical object beacons (green)</string>
@@ -4097,7 +4107,6 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_MarketplaceListings_Label">Marketplace</string>
   <string name="Command_MiniMap_Label">Mini-map</string>
   <string name="Command_Move_Label">Walk / run / fly</string>
-  <string name="Command_Outbox_Label">Merchant outbox</string>
   <string name="Command_People_Label">People</string>
   <string name="Command_Picks_Label">Picks</string>
   <string name="Command_Places_Label">Places</string>
@@ -4129,7 +4138,6 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_MarketplaceListings_Tooltip">Sell your creation</string>
   <string name="Command_MiniMap_Tooltip">Show nearby people</string>
   <string name="Command_Move_Tooltip">Moving your avatar</string>
-  <string name="Command_Outbox_Tooltip">Transfer items to your marketplace for sale</string>
   <string name="Command_People_Tooltip">Friends, groups, and nearby people</string>
   <string name="Command_Picks_Tooltip">Places to show as favorites in your profile</string>
   <string name="Command_Places_Tooltip">Places you've saved</string>
diff --git a/indra/newview/skins/default/xui/en/teleport_strings.xml b/indra/newview/skins/default/xui/en/teleport_strings.xml
index 5a9a16d3448d91d8102e3bf421242a6d5d21a095..57f8bb542de1fbde1d87885bc8471be964b50020 100644
--- a/indra/newview/skins/default/xui/en/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/en/teleport_strings.xml
@@ -39,6 +39,9 @@ Go to &apos;Welcome Island Public&apos; to repeat the tutorial.
 		<message name="expired_region_handoff">
 			Sorry, but the system was unable to complete your region crossing in a timely fashion. Please try again in a few minutes.
 		</message>
+		<message name="preexisting_tport">
+			Sorry, but the system was unable to start your teleport. Please try again in a few minutes.
+		</message>
 		<message name="no_host">
 			Unable to find teleport destination. The destination may be temporarily unavailable or no longer exists. Please try again in a few minutes.
 		</message>
diff --git a/indra/newview/skins/default/xui/es/floater_about_land.xml b/indra/newview/skins/default/xui/es/floater_about_land.xml
index 998d2a8863939958c867e549c0ee778ef52a84a1..57a1b2ec1e466291001489bfa6e70a8f223b04ac 100644
--- a/indra/newview/skins/default/xui/es/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/es/floater_about_land.xml
@@ -362,7 +362,7 @@ Sólo las parcelas más grandes pueden listarse en la búsqueda.
 				Foto:
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Pulse para elegir una imagen"/>
-			<text name="allow_see_label">
+			<text name="allow_see_label" top="170">
 				Los avatares de otras parcelas pueden ver a los avatares de esta parcela y chatear con ellos
 			</text>
 			<check_box label="Ver los avatares" name="SeeAvatarsCheck" tool_tip="Permite que los avatares de otras parcelas vean a los avatares de ésta y chateen con ellos, y también que tú puedas verles y chatear con ellos." top="170"/>
@@ -444,7 +444,7 @@ los media:
 			<panel.string name="estate_override">
 				Una o más de esta opciones está configurada a nivel del estado
 			</panel.string>
-			<check_box label="Cualquiera puede visitar (Si no seleccionas esta opción, se crearán líneas de prohibición)" name="public_access"/>
+			<check_box label="Cualquiera puede visitar" name="public_access" tool_tip="Si no seleccionas esta opción, se crearán líneas de prohibición"/>
 			<check_box label="Debe ser mayor de 18 [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Para poder acceder a esta parcela los Residentes deben ser mayores de 18 años. Para más información, consulta [SUPPORT_SITE]."/>
 			<check_box label="Debe haber información archivada sobre el pago [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Para poder acceder a esta parcela los Residentes deben haber aportado información de pago en su cuenta. Para más información, ver [SUPPORT_SITE]."/>
 			<check_box label="Permitir grupo [GROUP] sin restricciones" name="GroupCheck" tool_tip="Elija el grupo en la pestaña General."/>
diff --git a/indra/newview/skins/default/xui/es/floater_buy_currency.xml b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
index 2c8848265f481a62e66c56a6e3a34b29c4b5ddc8..dbff3fcf0e6a5935d8a34ff8b4386048268ab102 100644
--- a/indra/newview/skins/default/xui/es/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
@@ -60,7 +60,7 @@ no el objeto.
 	</text>
 	<button label="Comprar ahora" name="buy_btn"/>
 	<button label="Cancelar" name="cancel_btn"/>
-	<text left="5" name="info_cannot_buy" right="-5">
+	<text name="info_cannot_buy" left="150" font="SansSerifBig">
 		No se pudo hacer la compra
 	</text>
 	<button label="Ir a la web" name="error_web"/>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_chat.xml b/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
index f7e036efd7471e9685a18085a80bdafe5b933b06..388a5d84d28b9eea7fef894a914f19c401e5697c 100644
--- a/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
@@ -13,7 +13,7 @@
 			<item label="Medio" name="Medium" value="1"/>
 			<item label="Grande" name="Large" value="2"/>
 		</combo_box>
-		<check_box label="Bocadillos del chat" name="bubble_text_chat"/>
+		<check_box label="Bocadillos del chat" name="bubble_text_chat" left_delta="30"/>
 	</panel>
 	<panel name="im_notification_settings">
 		<text name="friend_ims">
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_setup.xml b/indra/newview/skins/default/xui/es/panel_preferences_setup.xml
index 1b191d3e46b84f1fd6ae8fce7e0b2a093b270cf1..36888850c4e8ec5c475ff1d6eb0de97501bcddd5 100644
--- a/indra/newview/skins/default/xui/es/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_setup.xml
@@ -30,7 +30,7 @@
 		<combo_box.item label="Preguntarme cuando una actualización opcional está disponible para instalar" name="Install_ask"/>
 		<combo_box.item label="Instalar sólo actualizaciones obligatorias" name="Install_manual"/>
 	</combo_box>
-	<check_box label="Admitir candidatos a la versión comercial a la hora de realizar actualizaciones" name="update_willing_to_test"/>
+	<check_box label="Admitir candidatos a la versión comercial a la hora de realizar actualizaciones" name="update_willing_to_test" left_delta="-20"/>
 	<check_box label="Mostrar las notas de la versión después de la actualización" name="update_show_release_notes"/>
 	<text name="Proxy Settings:">
 		Configuración de proxy:
diff --git a/indra/newview/skins/default/xui/fr/floater_about_land.xml b/indra/newview/skins/default/xui/fr/floater_about_land.xml
index 219857eb992633ce94d0be0132733c3a417ae5ff..fb65e71ee1bbf2e6886f0791b21513002c177b7e 100644
--- a/indra/newview/skins/default/xui/fr/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about_land.xml
@@ -366,10 +366,10 @@ Seules les parcelles de grande taille peuvent apparaître dans la recherche.
 				Photo :
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Cliquez pour sélectionner une image"/>
-			<text name="allow_see_label">
+			<text name="allow_see_label" top="170">
 				Les avatars sur d&apos;autres parcelles peuvent voir et chatter avec les avatars sur cette parcelle.
 			</text>
-			<check_box label="Voir les avatars" name="SeeAvatarsCheck" tool_tip="Permettre aux avatars présents sur d&apos;autres parcelles de voir et chatter avec les avatars présents sur cette parcelle et à vous de les voir et de chatter avec eux."/>
+			<check_box label="Voir les avatars" name="SeeAvatarsCheck" top="170" tool_tip="Permettre aux avatars présents sur d&apos;autres parcelles de voir et chatter avec les avatars présents sur cette parcelle et à vous de les voir et de chatter avec eux."/>
 			<text name="landing_point">
 				Lieu d&apos;arrivée : [LANDING]
 			</text>
@@ -449,7 +449,7 @@ musique :
 			<panel.string name="estate_override">
 				Au moins une de ces options est définie au niveau du domaine.
 			</panel.string>
-			<check_box label="Tout le monde peut rendre visite (Des lignes d&apos;interdiction seront créées si cette case n&apos;est pas cochée)" name="public_access"/>
+			<check_box label="Tout le monde peut rendre visite" tool_tip="Des lignes d&apos;interdiction seront créées si cette case n&apos;est pas cochée" name="public_access"/>
 			<check_box label="Doit avoir plus de 18 ans [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Pour accéder à cette parcelle, les résidents doivent avoir au moins 18 ans. Consultez le [SUPPORT_SITE] pour plus d&apos;informations."/>
 			<check_box label="Les infos de paiement doivent être enregistrées dans le dossier  [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Pour pouvoir accéder à cette parcelle, les résidents doivent avoir enregistré des informations de paiement. Consultez le [SUPPORT_SITE] pour plus d&apos;informations."/>
 			<check_box label="Autoriser le groupe [GROUP] sans restrictions" name="GroupCheck" tool_tip="Définir le groupe à l&apos;onglet Général."/>
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
index 148a5a35d23b5bd33ca08bf0bf52e651e2f65167..c295172abf03620a3479c30c5a44d37fb821f406 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
@@ -60,7 +60,7 @@ le Lindex...
 	</text>
 	<button label="Acheter" name="buy_btn"/>
 	<button label="Annuler" name="cancel_btn"/>
-	<text left="5" name="info_cannot_buy" right="-5" width="200">
+	<text name="info_cannot_buy" left="160" width="200">
 		Achat impossible
 	</text>
 	<button label="Accéder au Web" name="error_web"/>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
index 422243445be9d466a12d64b00a1bdd4f1fb74a72..a0f2e0eba7ae70496d6b9d38de1ed4463cc99111 100644
--- a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
@@ -13,7 +13,7 @@
 			<item label="Moyenne" name="Medium" value="1"/>
 			<item label="Grande" name="Large" value="2"/>
 		</combo_box>
-		<check_box label="Bulles de chat" name="bubble_text_chat"/>
+		<check_box label="Bulles de chat" name="bubble_text_chat" left_delta="45"/>
 	</panel>
 	<panel name="im_notification_settings">
 		<text name="friend_ims">
diff --git a/indra/newview/skins/default/xui/it/floater_about_land.xml b/indra/newview/skins/default/xui/it/floater_about_land.xml
index 0a7837e12212c56c06b326ed19c0e1b9a0222df2..50e2d1a8de539ec5c3dd57a71ed4dfad6667880d 100644
--- a/indra/newview/skins/default/xui/it/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/it/floater_about_land.xml
@@ -367,10 +367,10 @@ Solamente terreni più grandi possono essere abilitati nella ricerca.
 				Fotografia:
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Clicca per scegliere una immagine"/>
-			<text name="allow_see_label">
+			<text name="allow_see_label" top="170">
 				Gli avatar di altri lotti possono vedere gli avatar che si trovano in questo lotto e chattare con loro
 			</text>
-			<check_box label="Vedi avatar" name="SeeAvatarsCheck" tool_tip="Consente ad avatar in altri lotti di vedere e chattare con avatar in questo lotto e viceversa."/>
+			<check_box label="Vedi avatar" top="170" name="SeeAvatarsCheck" tool_tip="Consente ad avatar in altri lotti di vedere e chattare con avatar in questo lotto e viceversa."/>
 			<text name="landing_point">
 				Punto di atterraggio: [LANDING]
 			</text>
@@ -449,7 +449,7 @@ Media:
 			<panel.string name="estate_override">
 				Una o più di queste impostazioni sono già impostate a livello regionale
 			</panel.string>
-			<check_box label="Chiunque può visitare (Se si rimuove la selezione vengono create linee di espulsione)" name="public_access"/>
+			<check_box label="Chiunque può visitare" tool_tip="Se si rimuove la selezione vengono create linee di espulsione" name="public_access"/>
 			<check_box label="È necessario avere più di 18 anni [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Per poter visitare questo lotto i Residenti devono avere almeno 18 anni. Vedi [SUPPORT_SITE] per maggiori informazioni."/>
 			<check_box label="È necessario aver registrato le informazioni di pagamento [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Per poter visitare questo lotto i Residenti devono aver fornito informazioni di pagamento a Linden Lab.  Vedi [SUPPORT_SITE] per maggiori informazioni."/>
 			<check_box label="Consenti gruppo [GRUPPO] senza restrizioni" name="GroupCheck" tool_tip="Imposta il gruppo nel pannello generale."/>
diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
index 743969f557147272de279dfea872257c402f775e..53a2057455e1c31618cb13c78ab65467133b306a 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
@@ -60,7 +60,7 @@ l&apos;oggetto.
 	</text>
 	<button label="Acquista" name="buy_btn"/>
 	<button label="Annulla" name="cancel_btn"/>
-	<text left="5" name="info_cannot_buy" right="-5">
+	<text name="info_cannot_buy" left="160" font="SansSerifBig">
 		Non in grado di acquistare
 	</text>
 	<button label="Continua sul Web" name="error_web"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_about_land.xml b/indra/newview/skins/default/xui/pt/floater_about_land.xml
index ef71baa0b6287fd1c7d52405df5bc701e300ad59..96e54bb9bcbb6a55ba5deec74652e42f9ababe96 100644
--- a/indra/newview/skins/default/xui/pt/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/pt/floater_about_land.xml
@@ -362,10 +362,10 @@ Apenas lotes maiores podem ser listados na busca.
 				Foto:
 			</text>
 			<texture_picker label="" name="snapshot_ctrl" tool_tip="Clique para escolher uma imagem"/>
-			<text name="allow_see_label">
+			<text name="allow_see_label" top="170">
 				Avatares em outros lotes podem ver e conversar com avatares neste lote
 			</text>
-			<check_box label="Ver avatares" name="SeeAvatarsCheck" tool_tip="Permite que os avatares em outros lotes vejam e batam papo com avatares neste lote. Você poderá vê-los e conversar com eles."/>
+			<check_box label="Ver avatares" name="SeeAvatarsCheck" top="170" tool_tip="Permite que os avatares em outros lotes vejam e batam papo com avatares neste lote. Você poderá vê-los e conversar com eles."/>
 			<text name="landing_point">
 				Ponto de Aterrissagem: [LANDING]
 			</text>
diff --git a/indra/newview/skins/default/xui/ru/floater_about_land.xml b/indra/newview/skins/default/xui/ru/floater_about_land.xml
index 1ae6df76d920663583f23952d2f353236c49d1e4..222572b4bf68e359b86b90045978e19043bc2fe0 100644
--- a/indra/newview/skins/default/xui/ru/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/ru/floater_about_land.xml
@@ -338,7 +338,7 @@
 			<check_box label="Все" name="check other scripts" tool_tip="Если установлен флажок, то жители могут выполнять скрипты на вашем участке, включая приложения."/>
 			<check_box label="Группа" name="check group scripts" tool_tip="Если установлен флажок, то члены группы могут выполнять скрипты на вашем участке, включая приложения."/>
 			<check_box label="Безопасно (нет повреждений)" name="check safe" tool_tip="Если отмечено, то земля считается безопасной, отключены боевые повреждения. Если не отмечено, то боевые повреждения включены."/>
-			<check_box label="Не толкать" name="PushRestrictCheck" tool_tip="Запрещает скриптам функцию толкания. Этот параметр может оказаться полезным для предотвращения нежелательного поведения на вашей земле."/>
+			<check_box label="Не толкать" name="PushRestrictCheck" left_pad="44" tool_tip="Запрещает скриптам функцию толкания. Этот параметр может оказаться полезным для предотвращения нежелательного поведения на вашей земле."/>
 			<check_box label="Показать место в поиске (L$30/неделя)" name="ShowDirectoryCheck" tool_tip="Позволить людям видеть участок в результатах поиска"/>
 			<combo_box name="land category">
 				<combo_box.item label="Любая категория" name="item0"/>
@@ -360,10 +360,10 @@
 				Снимок:
 			</text>
 			<texture_picker name="snapshot_ctrl" tool_tip="Щелкните для выбора изображения"/>
-			<text name="allow_see_label">
+			<text name="allow_see_label" left="283">
 				Аватары с других участков могут видеть аватары на этом участке и общаться с ними
 			</text>
-			<check_box label="Видны аватары" name="SeeAvatarsCheck" tool_tip="Аватары с других участков смогут видеть аватары на этом участке и общаться с ними в чате, а вы также сможете видеть их и общаться с ними."/>
+			<check_box label="Видны аватары" left="262" name="SeeAvatarsCheck" tool_tip="Аватары с других участков смогут видеть аватары на этом участке и общаться с ними в чате, а вы также сможете видеть их и общаться с ними."/>
 			<text name="landing_point">
 				В точку телепортации: [LANDING]
 			</text>
@@ -372,7 +372,7 @@
 			<text name="Teleport Routing: ">
 				Вариант телепортации:
 			</text>
-			<combo_box name="landing type" tool_tip="Вариант телепортации – выберите, каким образом будет производиться телепортация на вашу землю">
+			<combo_box name="landing type" width="150" tool_tip="Вариант телепортации – выберите, каким образом будет производиться телепортация на вашу землю">
 				<combo_box.item label="В черном списке" name="Blocked"/>
 				<combo_box.item label="В точку телепортации" name="LandingPoint"/>
 				<combo_box.item label="В любое место" name="Anywhere"/>
@@ -439,7 +439,7 @@
 			<panel.string name="estate_override">
 				Часть этих параметров установлена на уровне землевладения
 			</panel.string>
-			<check_box label="Доступ открыт для всех (При снятия выделения будет создана запись в строке запрета)" name="public_access"/>
+			<check_box label="Доступ открыт для всех" tool_tip="При снятия выделения будет создана запись в строке запрета" name="public_access"/>
 			<check_box label="Должен быть 18 и старше [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Доступ к этому участку имеют только жители 18 лет и старше. Более подробная информация находится здесь: [SUPPORT_SITE]."/>
 			<check_box label="Информация о платежах должна быть в файле [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Для доступа к этому участку у жителя должна быть зарегистрирована информация об оплате.  Более подробная информация находится здесь: [SUPPORT_SITE]."/>
 			<check_box label="Разрешить группе [GROUP] без всяких ограничений" name="GroupCheck" tool_tip="Группа устанавливается на основной вкладке."/>
diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml
index 08accc39fe949d6663fddd941776a76e1656176e..1e4f9e9abbb35c997a359ac813dfaa809e03dc81 100644
--- a/indra/newview/skins/default/xui/ru/notifications.xml
+++ b/indra/newview/skins/default/xui/ru/notifications.xml
@@ -1436,9 +1436,9 @@
 		<usetemplate name="okcancelbuttons" notext="Продолжить" yestext="Создать аккаунт..."/>
 	</notification>
 	<notification name="LoginPacketNeverReceived">
-		Возникли неполадки при подключении. Возможно, проблема с вашим подключением к интернету или [SECOND_LIFE_GRID].
+		Возникли неполадки при подключении. Возможно, проблема с вашим подключением к интернету или [SECOND_LIFE_GRID] временно недоступна.
 
-Варианты ваших действий: проверьте подключение к интернету и повторите попытку через несколько минут, нажмите кнопку «Справка» для перехода к [SUPPORT_SITE] или кнопку «Телепортация», чтобы телепортироваться домой.
+Вы можете проверить подключение к интернету, повторить попытку через несколько минут, нажать кнопку «Справка» для перехода на [SUPPORT_SITE] или нажать кнопку «Телепортация», чтобы телепортироваться домой.
 		<url name="url">
 			http://secondlife.com/support/
 		</url>
diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_chat.xml b/indra/newview/skins/default/xui/ru/panel_preferences_chat.xml
index c2fcac8840420d44f94f7600e84a3d12c0723bab..03a714f266e3c35e8445df6afc53e186c70f44da 100644
--- a/indra/newview/skins/default/xui/ru/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/ru/panel_preferences_chat.xml
@@ -5,15 +5,15 @@
 		<check_box initial_value="true" label="Воспроизводить анимацию ввода текста при общении" name="play_typing_animation"/>
 		<check_box label="Отправлять мне сообщения по почте, когда меня нет в сети" name="send_im_to_email"/>
 		<check_box label="Только друзья и группы могут звонить мне и отправлять IM" name="voice_call_friends_only_check"/>
-		<text name="font_size">
+		<text name="font_size" left="361">
 			Размер шрифта:
 		</text>
-		<combo_box name="chat_font_size">
+		<combo_box name="chat_font_size" left="361">
 			<item label="Мелкий" name="Small" value="0"/>
 			<item label="Средний" name="Medium" value="1"/>
 			<item label="Крупный" name="Large" value="2"/>
 		</combo_box>
-		<check_box label="Чат в пузырьках" name="bubble_text_chat"/>
+		<check_box label="Чат в пузырьках" name="bubble_text_chat" left_delta="19"/>
 	</panel>
 	<panel name="im_notification_settings">
 		<text name="friend_ims">
diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml b/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml
index d4d0ef9e7ca84bbac88ea1f422caf3d576fa4b17..137e047d977a7753656a459cefaa2a1c3977c925 100644
--- a/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml
@@ -14,7 +14,7 @@
 	<text name="Web:">
 		Браузер:
 	</text>
-	<radio_group name="preferred_browser_behavior">
+	<radio_group name="preferred_browser_behavior" left_delta="30">
 		<radio_item label="Используйте встроенный браузер для всех ссылок" name="internal" tool_tip="Будет использоваться браузер, заданный в системе по умолчанию. Не рекомендуется, если [APP_NAME] работает в полноэкранном режиме." value="0"/>
 		<radio_item label="Для ссылок Second Life следует использовать только встроенный браузер" name="external" tool_tip="Используйте встроенный браузер для справки, веб-ссылок и т.д. Для ссылок LindenLab/Second Life следует использовать только встроенный браузер." value="1"/>
 		<radio_item label="Для всех ссылок следует использовать встроенный браузер" name="external_all" tool_tip="Для просмотра справки, ссылок на веб-страницы и т. д. будет использоваться встроенный браузер. Этот браузер открывается как новое окно в [APP_NAME]." value="2"/>
diff --git a/indra/newview/skins/default/xui/tr/floater_about_land.xml b/indra/newview/skins/default/xui/tr/floater_about_land.xml
index 48b16e2fdea5d08ee2fb766bfd18e823a0adb689..1101e5055a95101328a65de736007ee51f879aa1 100644
--- a/indra/newview/skins/default/xui/tr/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/tr/floater_about_land.xml
@@ -360,10 +360,10 @@ Sadece büyük parseller aramada görünür.
 				Anlık Görüntü:
 			</text>
 			<texture_picker name="snapshot_ctrl" tool_tip="Bir resim seçmek için tıklayın"/>
-			<text name="allow_see_label">
+			<text name="allow_see_label" top="170">
 				Diğer parsellerdeki avatarlar bu parseldeki avatarları görebilir ve onlarla sohbet edebilir
 			</text>
-			<check_box label="Avatarları Gör" name="SeeAvatarsCheck" tool_tip="Diğer parsellerdeki avatarların bu parseldeki avatarları görmesine ve onlarla sohbet etmesine, sizin de onları görüp, onlarla sohbet etmenize imkan tanır."/>
+			<check_box label="Avatarları Gör" name="SeeAvatarsCheck" top="170" tool_tip="Diğer parsellerdeki avatarların bu parseldeki avatarları görmesine ve onlarla sohbet etmesine, sizin de onları görüp, onlarla sohbet etmenize imkan tanır."/>
 			<text name="landing_point">
 				İniş Noktası: [LANDING]
 			</text>
diff --git a/indra/newview/tests/llsecapi_test.cpp b/indra/newview/tests/llsecapi_test.cpp
index d7e87ed52ea5dc0c1a8d9c9853a358774c1fd180..a1005c654cde01744661dba4f99285c805be73f2 100644
--- a/indra/newview/tests/llsecapi_test.cpp
+++ b/indra/newview/tests/llsecapi_test.cpp
@@ -60,12 +60,21 @@ LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(X509* openssl_cert
 LLPointer<LLCertificateChain> LLSecAPIBasicHandler::getCertificateChain(const X509_STORE_CTX* chain) { return NULL; }
 LLPointer<LLCertificateStore> LLSecAPIBasicHandler::getCertificateStore(const std::string& store_id) { return NULL; }
 void LLSecAPIBasicHandler::setProtectedData(const std::string& data_type, const std::string& data_id, const LLSD& data) {}
+void LLSecAPIBasicHandler::addToProtectedMap(const std::string& data_type, const std::string& data_id, const std::string& map_elem, const LLSD& data) {}
+void LLSecAPIBasicHandler::removeFromProtectedMap(const std::string& data_type, const std::string& data_id, const std::string& map_elem) {}
 LLSD LLSecAPIBasicHandler::getProtectedData(const std::string& data_type, const std::string& data_id) { return LLSD(); }
 void LLSecAPIBasicHandler::deleteProtectedData(const std::string& data_type, const std::string& data_id) {}
 LLPointer<LLCredential> LLSecAPIBasicHandler::createCredential(const std::string& grid, const LLSD& identifier, const LLSD& authenticator) { return NULL; }
 LLPointer<LLCredential> LLSecAPIBasicHandler::loadCredential(const std::string& grid) { return NULL; }
 void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool save_authenticator) {}
 void LLSecAPIBasicHandler::deleteCredential(LLPointer<LLCredential> cred) {}
+bool LLSecAPIBasicHandler::hasCredentialMap(const std::string& storage, const std::string& grid) { return false; }
+void LLSecAPIBasicHandler::loadCredentialMap(const std::string& storage, const std::string& grid, credential_map_t& credential_map) {}
+LLPointer<LLCredential> LLSecAPIBasicHandler::loadFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userkey) { return NULL; }
+void LLSecAPIBasicHandler::addToCredentialMap(const std::string& storage, LLPointer<LLCredential> cred, bool save_authenticator) {}
+void LLSecAPIBasicHandler::removeFromCredentialMap(const std::string& storage, LLPointer<LLCredential> cred) {}
+void LLSecAPIBasicHandler::removeFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userkey) {}
+void LLSecAPIBasicHandler::removeCredentialMap(const std::string& storage, const std::string& grid) {}
 
 // -------------------------------------------------------------------------------------------
 // TUT
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index a4cda0ba78cfe196acbc22fe004ec3fa6bd48453..a403760670eeff299cf61d3b389e8fc5a054955e 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1332,7 +1332,6 @@ def package_finish(self):
         print "Converting temp disk image to final disk image"
         self.run_command(['hdiutil', 'convert', sparsename, '-format', 'UDZO',
                           '-imagekey', 'zlib-level=9', '-o', finalname])
-        self.run_command(['hdiutil', 'internet-enable', '-yes', finalname])
         # get rid of the temp file
         self.package_file = finalname
         self.remove(sparsename)