diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index 22fad792da32c6fb4974bf3d3d7c1c0dcb73ddad..a86bbbffff3b65ce0aa3248852adb232f3216fe2 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -270,6 +270,14 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const
 	return (F32)mFontBitmapCachep->getMaxCharWidth();
 }
 
+F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const
+{
+	if (mFTFace == NULL)
+		return 0.0;
+
+	return glyph->mXAdvance;
+}
+
 F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
 {
 	if (mFTFace == NULL)
@@ -289,6 +297,21 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
 	return delta.x*(1.f/64.f);
 }
 
+F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const
+{
+	if (mFTFace == NULL)
+		return 0.0;
+
+	U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
+	U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
+
+	FT_Vector  delta;
+
+	llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
+
+	return delta.x*(1.f/64.f);
+}
+
 BOOL LLFontFreetype::hasGlyph(llwchar wch) const
 {
 	llassert(!mIsFallback);
diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h
index 7a5d029038e60908843f93074f36353d971a7ffc..f60d09316dcca849bfa33486a02ef1308e3b6b2a 100644
--- a/indra/llrender/llfontfreetype.h
+++ b/indra/llrender/llfontfreetype.h
@@ -128,7 +128,9 @@ class LLFontFreetype : public LLRefCount
 	};
 
 	F32 getXAdvance(llwchar wc) const;
+	F32 getXAdvance(const LLFontGlyphInfo* glyph) const;
 	F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters
+	F32 getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const; // Get the kerning between the two characters
 
 	LLFontGlyphInfo* getGlyphInfo(llwchar wch) const;
 
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index b6a6b448eee7cbe9c13f022104366dac07618d3e..f1f86fd638f8e12f38722fb5ccb02330af6b6401 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -249,11 +249,18 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
 	// Remember last-used texture to avoid unnecesssary bind calls.
 	LLImageGL *last_bound_texture = NULL;
 
+	const LLFontGlyphInfo* next_glyph = NULL;
+
 	for (i = begin_offset; i < begin_offset + length; i++)
 	{
 		llwchar wch = wstr[i];
 
-		const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
+		const LLFontGlyphInfo* fgi = next_glyph;
+		next_glyph = NULL;
+		if(!fgi)
+		{
+			fgi = mFontFreetype->getGlyphInfo(wch);
+		}
 		if (!fgi)
 		{
 			llerrs << "Missing Glyph Info" << llendl;
@@ -295,7 +302,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
 		if (next_char && (next_char < LAST_CHARACTER))
 		{
 			// Kern this puppy.
-			cur_x += mFontFreetype->getXKerning(wch, next_char);
+			next_glyph = mFontFreetype->getGlyphInfo(next_char);
+			cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
 		}
 
 		// Round after kerning.
@@ -435,14 +443,21 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
 	F32 cur_x = 0;
 	const S32 max_index = begin_offset + max_chars;
 
+	const LLFontGlyphInfo* next_glyph = NULL;
+
 	F32 width_padding = 0.f;
 	for (S32 i = begin_offset; i < max_index && wchars[i] != 0; i++)
 	{
 		llwchar wch = wchars[i];
 
-		const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
+		const LLFontGlyphInfo* fgi = next_glyph;
+		next_glyph = NULL;
+		if(!fgi)
+		{
+			fgi = mFontFreetype->getGlyphInfo(wch);
+		}
 
-		F32 advance = mFontFreetype->getXAdvance(wch);
+		F32 advance = mFontFreetype->getXAdvance(fgi);
 
 		// for the last character we want to measure the greater of its width and xadvance values
 		// so keep track of the difference between these values for the each character we measure
@@ -459,7 +474,8 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
 			&& (next_char < LAST_CHARACTER))
 		{
 			// Kern this puppy.
-			cur_x += mFontFreetype->getXKerning(wch, next_char);
+			next_glyph = mFontFreetype->getGlyphInfo(next_char);
+			cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
 		}
 		// Round after kerning.
 		cur_x = (F32)llround(cur_x);
@@ -492,6 +508,8 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
 	// avoid S32 overflow when max_pixels == S32_MAX by staying in floating point
 	F32 scaled_max_pixels =	ceil(max_pixels * sScaleX);
 	F32 width_padding = 0.f;
+	
+	LLFontGlyphInfo* next_glyph = NULL;
 
 	S32 i;
 	for (i=0; (i < max_chars); i++)
@@ -534,8 +552,13 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
 				in_word = TRUE;
 			}
 		}
-
-		LLFontGlyphInfo* fgi = mFontFreetype->getGlyphInfo(wch);
+		
+		LLFontGlyphInfo* fgi = next_glyph;
+		next_glyph = NULL;
+		if(!fgi)
+		{
+			fgi = mFontFreetype->getGlyphInfo(wch);
+		}
 
 		// account for glyphs that run beyond the starting point for the next glyphs
 		width_padding = llmax(	0.f,													// always use positive padding amount
@@ -554,7 +577,8 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
 		if (((i+1) < max_chars) && wchars[i+1])
 		{
 			// Kern this puppy.
-			cur_x += mFontFreetype->getXKerning(wch, wchars[i+1]);
+			next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1]);
+			cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
 		}
 
 		// Round after kerning.
@@ -660,6 +684,8 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
 	const S32 max_index = begin_offset + llmin(S32_MAX - begin_offset, max_chars);
 
 	F32 scaled_max_pixels =	max_pixels * sScaleX;
+	
+	const LLFontGlyphInfo* next_glyph = NULL;
 
 	S32 pos;
 	for (pos = begin_offset; pos < max_index; pos++)
@@ -669,7 +695,15 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
 		{
 			break; // done
 		}
-		F32 char_width = mFontFreetype->getXAdvance(wch);
+		
+		const LLFontGlyphInfo* glyph = next_glyph;
+		next_glyph = NULL;
+		if(!glyph)
+		{
+			glyph = mFontFreetype->getGlyphInfo(wch);
+		}
+		
+		F32 char_width = mFontFreetype->getXAdvance(glyph);
 
 		if (round)
 		{
@@ -695,11 +729,12 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
 		if (((pos + 1) < max_index)
 			&& (wchars[(pos + 1)]))
 		{
-			llwchar next_char = wchars[pos + 1];
 			// Kern this puppy.
-			cur_x += mFontFreetype->getXKerning(wch, next_char);
+			next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1]);
+			cur_x += mFontFreetype->getXKerning(glyph, next_glyph);
 		}
 
+
 		// Round after kerning.
 		cur_x = llround(cur_x);
 	}
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index a55915af359ac77e973b74d4cdb5d9fe26b25180..f3cd112b9a5cc05d47076ef17330f7c679b04f93 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -2376,10 +2376,17 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
 			LLRect new_rect;
 			new_rect.setLeftTopAndSize(view_rect.mLeft,view_rect.mTop,new_width, new_height);
 
-			floater->reshape( new_width, new_height, TRUE );
-			floater->setRect(new_rect);
+			floater->setShape(new_rect);
 
-			floater->translateIntoRect( getLocalRect(), false );
+			if (floater->followsRight())
+			{
+				floater->translate(old_width - new_width, 0);
+			}
+
+			if (floater->followsTop())
+			{
+				floater->translate(0, old_height - new_height);
+			}
 		}
 	}
 
diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp
index ede32084d0c0c58101ce3c7069f292570dabad47..75342afbe269b1ee5189394f394a5dda717791ae 100644
--- a/indra/llui/llkeywords.cpp
+++ b/indra/llui/llkeywords.cpp
@@ -218,6 +218,86 @@ void LLKeywords::addToken(LLKeywordToken::TOKEN_TYPE type,
 		llassert(0);
 	}
 }
+LLKeywords::WStringMapIndex::WStringMapIndex(const WStringMapIndex& other)
+{
+	if(other.mOwner)
+	{
+		copyData(other.mData, other.mLength);
+	}
+	else
+	{
+		mOwner = false;
+		mLength = other.mLength;
+		mData = other.mData;
+	}
+}
+
+LLKeywords::WStringMapIndex::WStringMapIndex(const LLWString& str)
+{
+	copyData(str.data(), str.size());
+}
+
+LLKeywords::WStringMapIndex::WStringMapIndex(const llwchar *start, size_t length):
+mData(start), mLength(length), mOwner(false)
+{
+}
+
+LLKeywords::WStringMapIndex::~WStringMapIndex()
+{
+	if(mOwner)
+		delete[] mData;
+}
+
+void LLKeywords::WStringMapIndex::copyData(const llwchar *start, size_t length)
+{
+	llwchar *data = new llwchar[length];
+	memcpy((void*)data, (const void*)start, length * sizeof(llwchar));
+
+	mOwner = true;
+	mLength = length;
+	mData = data;
+}
+
+bool LLKeywords::WStringMapIndex::operator<(const LLKeywords::WStringMapIndex &other) const
+{
+	// NOTE: Since this is only used to organize a std::map, it doesn't matter if it uses correct collate order or not.
+	// The comparison only needs to strictly order all possible strings, and be stable.
+	
+	bool result = false;
+	const llwchar* self_iter = mData;
+	const llwchar* self_end = mData + mLength;
+	const llwchar* other_iter = other.mData;
+	const llwchar* other_end = other.mData + other.mLength;
+	
+	while(true)
+	{
+		if(other_iter >= other_end)
+		{
+			// We've hit the end of other.
+			// This covers two cases: other being shorter than self, or the strings being equal.
+			// In either case, we want to return false.
+			result = false;
+			break;
+		}
+		else if(self_iter >= self_end)
+		{
+			// self is shorter than other.
+			result = true;
+			break; 
+		}
+		else if(*self_iter != *other_iter)
+		{
+			// The current character differs.  The strings are not equal.
+			result = *self_iter < *other_iter;
+			break;
+		}
+
+		self_iter++;
+		other_iter++;
+	}
+	
+	return result;
+}
 
 LLColor3 LLKeywords::readColor( const std::string& s )
 {
@@ -429,7 +509,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
 				S32 seg_len = p - cur;
 				if( seg_len > 0 )
 				{
-					LLWString word( cur, 0, seg_len );
+					WStringMapIndex word( cur, seg_len );
 					word_token_map_t::iterator map_iter = mWordTokenMap.find(word);
 					if( map_iter != mWordTokenMap.end() )
 					{
diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h
index 53377869ca4c3588853fa602a83d17c4efa20d7b..e5b66dfa56d44414259931d32c4c58ad59dbe569 100644
--- a/indra/llui/llkeywords.h
+++ b/indra/llui/llkeywords.h
@@ -92,8 +92,33 @@ class LLKeywords
 					const std::string& key,
 					const LLColor3& color,
 					const std::string& tool_tip = LLStringUtil::null);
-
-	typedef std::map<LLWString, LLKeywordToken*> word_token_map_t;
+	
+	// This class is here as a performance optimization.
+	// The word token map used to be defined as std::map<LLWString, LLKeywordToken*>.
+	// This worked, but caused a performance bottleneck due to memory allocation and string copies
+	//  because it's not possible to search such a map without creating an LLWString.
+	// Using this class as the map index instead allows us to search using segments of an existing
+	//  text run without copying them first, which greatly reduces overhead in LLKeywords::findSegments().
+	class WStringMapIndex
+	{
+	public:
+		// copy constructor
+		WStringMapIndex(const WStringMapIndex& other);
+		// constructor from a string (copies the string's data into the new object)
+		WStringMapIndex(const LLWString& str);
+		// constructor from pointer and length
+		// NOTE: does NOT copy data, caller must ensure that the lifetime of the pointer exceeds that of the new object!
+		WStringMapIndex(const llwchar *start, size_t length);
+		~WStringMapIndex();
+		bool operator<(const WStringMapIndex &other) const;
+	private:
+		void copyData(const llwchar *start, size_t length);
+		const llwchar *mData;
+		size_t mLength;
+		bool mOwner;
+	};
+
+	typedef std::map<WStringMapIndex, LLKeywordToken*> word_token_map_t;
 	typedef word_token_map_t::const_iterator keyword_iterator_t;
 	keyword_iterator_t begin() const { return mWordTokenMap.begin(); }
 	keyword_iterator_t end() const { return mWordTokenMap.end(); }
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index d18abbfb2fc04732d969da2c51d79f1b1c0a7c54..0d56c5ed3131b2cfa6b9449e45fb834649fc42fc 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -657,11 +657,38 @@ LLMenuItemVerticalSeparatorGL::LLMenuItemVerticalSeparatorGL( void )
 // Class LLMenuItemTearOffGL
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 LLMenuItemTearOffGL::LLMenuItemTearOffGL(const LLMenuItemTearOffGL::Params& p) 
-:	LLMenuItemGL(p), 
-	mParentHandle(p.parent_floater_handle)
+:	LLMenuItemGL(p)
 {
 }
 
+// Returns the first floater ancestor if there is one
+LLFloater* LLMenuItemTearOffGL::getParentFloater()
+{
+	LLView* parent_view = getMenu();
+
+	while (parent_view)
+	{
+		if (dynamic_cast<LLFloater*>(parent_view))
+		{
+			return dynamic_cast<LLFloater*>(parent_view);
+		}
+
+		bool parent_is_menu = dynamic_cast<LLMenuGL*>(parent_view) && !dynamic_cast<LLMenuBarGL*>(parent_view);
+
+		if (parent_is_menu)
+		{
+			// use menu parent
+			parent_view =  dynamic_cast<LLMenuGL*>(parent_view)->getParentMenuItem();
+		}
+		else
+		{
+			// just use regular view parent
+			parent_view = parent_view->getParent();
+		}
+	}
+
+	return NULL;
+}
 
 void LLMenuItemTearOffGL::onCommit()
 {
@@ -680,7 +707,7 @@ void LLMenuItemTearOffGL::onCommit()
 
 		getMenu()->needsArrange();
 
-		LLFloater* parent_floater = mParentHandle.get();
+		LLFloater* parent_floater = getParentFloater();
 		LLFloater* tear_off_menu = LLTearOffMenu::create(getMenu());
 
 		if (tear_off_menu)
@@ -1671,7 +1698,6 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p)
 	mSpilloverMenu(NULL),
 	mJumpKey(p.jump_key),
 	mCreateJumpKeys(p.create_jump_keys),
-	mParentFloaterHandle(p.parent_floater),
 	mNeedsArrange(FALSE), 
 	mShortcutPad(p.shortcut_pad)
 {
@@ -1699,7 +1725,7 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p)
 void LLMenuGL::initFromParams(const LLMenuGL::Params& p)
 {
 	LLUICtrl::initFromParams(p);
-	setCanTearOff(p.can_tear_off, p.parent_floater);
+	setCanTearOff(p.can_tear_off);
 }
 
 // Destroys the object
@@ -1711,12 +1737,11 @@ LLMenuGL::~LLMenuGL( void )
 	mJumpKeys.clear();
 }
 
-void LLMenuGL::setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_handle )
+void LLMenuGL::setCanTearOff(BOOL tear_off)
 {
 	if (tear_off && mTearOffItem == NULL)
 	{
 		LLMenuItemTearOffGL::Params p;
-		p.parent_floater_handle = parent_floater_handle;
 		mTearOffItem = LLUICtrlFactory::create<LLMenuItemTearOffGL>(p);
 		addChildInBack(mTearOffItem);
 	}
@@ -2233,7 +2258,6 @@ void LLMenuGL::createSpilloverBranch()
 		LLMenuGL::Params p;
 		p.name("More");
 		p.label("More"); // *TODO: Translate
-		p.parent_floater(mParentFloaterHandle);
 		p.bg_color(mBackgroundColor);
 		p.bg_visible(true);
 		p.can_tear_off(false);
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 8441aaadd49ef419d870648691fc01279eaf2b2e..39d1986461aa7c51a9f34fb8be607b3bd9c8b676 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -355,7 +355,6 @@ class LLMenuGL
 public:
 	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
 	{
-		Optional<LLHandle<LLFloater> >	parent_floater;
 		Optional<KEY>					jump_key;
 		Optional<bool>					horizontal_layout,
 										can_tear_off,
@@ -430,7 +429,7 @@ class LLMenuGL
 	void setBackgroundColor( const LLUIColor& color ) { mBackgroundColor = color; }
 	const LLUIColor& getBackgroundColor() const { return mBackgroundColor; }
 	void setBackgroundVisible( BOOL b )	{ mBgVisible = b; }
-	void setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_handle = LLHandle<LLFloater>());
+	void setCanTearOff(BOOL tear_off);
 
 	// add a separator to this menu
 	virtual BOOL addSeparator();
@@ -553,7 +552,6 @@ class LLMenuGL
 	class LLMenuItemTearOffGL* mTearOffItem;
 	class LLMenuItemBranchGL* mSpilloverBranch;
 	LLMenuGL*		mSpilloverMenu;
-	LLHandle<LLFloater>	mParentFloaterHandle;
 	KEY				mJumpKey;
 	BOOL			mCreateJumpKeys;
 	S32				mShortcutPad;
@@ -814,7 +812,6 @@ class LLMenuItemTearOffGL : public LLMenuItemGL
 public:
 	struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
 	{
-		Optional<LLHandle<LLFloater> > parent_floater_handle;
 		Params()
 		{
 			name = "tear off";
@@ -823,13 +820,12 @@ class LLMenuItemTearOffGL : public LLMenuItemGL
 	};
 
 	LLMenuItemTearOffGL( const Params& );
-
+	
 	virtual void onCommit(void);
 	virtual void draw(void);
 	virtual U32 getNominalHeight() const;
 
-private:
-	LLHandle<LLFloater> mParentHandle;
+	LLFloater* getParentFloater();
 };
 
 
diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp
index 3df09d124abea9aa5855f095fb803ae93b4113da..00214d451cd0590c0623a303021d041cfcd1a7aa 100644
--- a/indra/llui/llresizehandle.cpp
+++ b/indra/llui/llresizehandle.cpp
@@ -124,7 +124,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
 	{
 		// Make sure the mouse in still over the application.  We don't want to make the parent
 		// so big that we can't see the resize handle any more.
-
+	
 		S32 screen_x;
 		S32 screen_y;
 		localPointToScreen(x, y, &screen_x, &screen_y);
@@ -136,9 +136,10 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
 		if( resizing_view )
 		{
 			// undock floater when user resize it
-			if (((LLFloater*)getParent())->isDocked())
+			LLFloater* floater_parent = dynamic_cast<LLFloater*>(getParent());
+			if (floater_parent && floater_parent->isDocked()) 
 			{
-				((LLFloater*)getParent())->setDocked(false, false);
+				floater_parent->setDocked(false, false);
 			}
 
 			// Resize the parent
@@ -146,61 +147,68 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
 			LLRect scaled_rect = orig_rect;
 			S32 delta_x = screen_x - mDragLastScreenX;
 			S32 delta_y = screen_y - mDragLastScreenY;
-
-			if(delta_x == 0 && delta_y == 0)
-				return FALSE;
-
 			LLCoordGL mouse_dir;
 			// use hysteresis on mouse motion to preserve user intent when mouse stops moving
 			mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
 			mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY;
-			
 			mLastMouseScreenX = screen_x;
 			mLastMouseScreenY = screen_y;
 			mLastMouseDir = mouse_dir;
 
-			S32 new_width = orig_rect.getWidth();
-			S32 new_height = orig_rect.getHeight();
+			S32 x_multiple = 1;
+			S32 y_multiple = 1;
+			switch( mCorner )
+			{
+			case LEFT_TOP:
+				x_multiple = -1; 
+				y_multiple =  1;	
+				break;
+			case LEFT_BOTTOM:	
+				x_multiple = -1; 
+				y_multiple = -1;	
+				break;
+			case RIGHT_TOP:		
+				x_multiple =  1; 
+				y_multiple =  1;	
+				break;
+			case RIGHT_BOTTOM:	
+				x_multiple =  1; 
+				y_multiple = -1;	
+				break;
+			}
 
-			S32 new_pos_x = orig_rect.mLeft;
-			S32 new_pos_y = orig_rect.mTop;
+			S32 new_width = orig_rect.getWidth() + x_multiple * delta_x;
+			if( new_width < mMinWidth )
+			{
+				new_width = mMinWidth;
+				delta_x = x_multiple * (mMinWidth - orig_rect.getWidth());
+			}
+
+			S32 new_height = orig_rect.getHeight() + y_multiple * delta_y;
+			if( new_height < mMinHeight )
+			{
+				new_height = mMinHeight;
+				delta_y = y_multiple * (mMinHeight - orig_rect.getHeight());
+			}
 
 			switch( mCorner )
 			{
-			case LEFT_TOP:
-				new_width-=delta_x;
-				new_height+=delta_y;
-				new_pos_x+=delta_x;
-				new_pos_y+=delta_y;
+			case LEFT_TOP:		
+				scaled_rect.translate(delta_x, 0);			
 				break;
 			case LEFT_BOTTOM:	
-				new_width-=delta_x;
-				new_height-=delta_y;
-				new_pos_x+=delta_x;
+				scaled_rect.translate(delta_x, delta_y);	
 				break;
 			case RIGHT_TOP:		
-				new_width+=delta_x;
-				new_height+=delta_y;
-				new_pos_y+=delta_y;
 				break;
 			case RIGHT_BOTTOM:	
-				new_width+=delta_x;
-				new_height-=delta_y;
+				scaled_rect.translate(0, delta_y);			
 				break;
 			}
 
-			new_width = llmax(new_width,mMinWidth);
-			new_height = llmax(new_height,mMinHeight);
-			
-			LLRect::tCoordType screen_width = resizing_view->getParent()->getSnapRect().getWidth();
-			LLRect::tCoordType screen_height = resizing_view->getParent()->getSnapRect().getHeight();
-			
-			new_width = llmin(new_width, screen_width);
-			new_height = llmin(new_height, screen_height);
-			
 			// temporarily set new parent rect
-			scaled_rect.setLeftTopAndSize(new_pos_x,new_pos_y,new_width,new_height);
-				
+			scaled_rect.mRight = scaled_rect.mLeft + new_width;
+			scaled_rect.mTop = scaled_rect.mBottom + new_height;
 			resizing_view->setRect(scaled_rect);
 
 			LLView* snap_view = NULL;
@@ -251,11 +259,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
 			resizing_view->setRect(orig_rect);
 
 			// translate and scale to new shape
-			resizing_view->reshape(scaled_rect.getWidth(),scaled_rect.getHeight());
-			resizing_view->setRect(scaled_rect);
-			//set shape to handle dependent floaters...
-			resizing_view->handleReshape(scaled_rect, false);
-			
+			resizing_view->setShape(scaled_rect, true);
 			
 			// update last valid mouse cursor position based on resized view's actual size
 			LLRect new_rect = resizing_view->getRect();
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index b84e6f45fb8a9363a9f7132c75837f346965e7bf..851fb966ecea130fb4d5c6dea8020ae717608d3d 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1445,10 +1445,10 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i
 }
 
 // Finds the text segment (if any) at the give local screen position
-LLTextSegmentPtr LLTextBase::getSegmentAtLocalPos( S32 x, S32 y )
+LLTextSegmentPtr LLTextBase::getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line)
 {
 	// Find the cursor position at the requested local screen position
-	S32 offset = getDocIndexFromLocalCoord( x, y, FALSE );
+	S32 offset = getDocIndexFromLocalCoord( x, y, FALSE, hit_past_end_of_line);
 	segment_set_t::iterator seg_iter = getSegIterContaining(offset);
 	if (seg_iter != mSegments.end())
 	{
@@ -1788,7 +1788,7 @@ const LLWString& LLTextBase::getWText() const
 // will be put to its right.  If round is false, the cursor will always be put to the
 // character's left.
 
-S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const
+S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line) const
 {
 	// Figure out which line we're nearest to.
 	LLRect visible_region = getVisibleDocumentRect();
@@ -1817,7 +1817,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round
 		S32 text_width, text_height;
 		segmentp->getDimensions(line_seg_offset, segment_line_length, text_width, text_height);
 		if (local_x < start_x + text_width						// cursor to left of right edge of text
-			|| segmentp->getEnd() >= line_iter->mDocIndexEnd - 1)	// or this segment wraps to next line
+			|| (hit_past_end_of_line && (segmentp->getEnd() >= line_iter->mDocIndexEnd - 1)))	// or this segment wraps to next line
 		{
 			// Figure out which character we're nearest to.
 			S32 offset;
@@ -2402,8 +2402,12 @@ BOOL LLNormalTextSegment::handleHover(S32 x, S32 y, MASK mask)
 {
 	if (getStyle() && getStyle()->isLink())
 	{
-		LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
-		return TRUE;
+		// Only process the click if it's actually in this segment, not to the right of the end-of-line.
+		if(mEditor.getSegmentAtLocalPos(x, y, false) == this)
+		{
+			LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
+			return TRUE;
+		}
 	}
 	return FALSE;
 }
@@ -2412,8 +2416,12 @@ BOOL LLNormalTextSegment::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
 	if (getStyle() && getStyle()->isLink())
 	{
-		mEditor.createUrlContextMenu(x, y, getStyle()->getLinkHREF());
-		return TRUE;
+		// Only process the click if it's actually in this segment, not to the right of the end-of-line.
+		if(mEditor.getSegmentAtLocalPos(x, y, false) == this)
+		{
+			mEditor.createUrlContextMenu(x, y, getStyle()->getLinkHREF());
+			return TRUE;
+		}
 	}
 	return FALSE;
 }
@@ -2422,8 +2430,12 @@ BOOL LLNormalTextSegment::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 	if (getStyle() && getStyle()->isLink())
 	{
-		// eat mouse down event on hyperlinks, so we get the mouse up
-		return TRUE;
+		// Only process the click if it's actually in this segment, not to the right of the end-of-line.
+		if(mEditor.getSegmentAtLocalPos(x, y, false) == this)
+		{
+			// eat mouse down event on hyperlinks, so we get the mouse up
+			return TRUE;
+		}
 	}
 
 	return FALSE;
@@ -2433,8 +2445,12 @@ BOOL LLNormalTextSegment::handleMouseUp(S32 x, S32 y, MASK mask)
 {
 	if (getStyle() && getStyle()->isLink())
 	{
-		LLUrlAction::clickAction(getStyle()->getLinkHREF());
-		return TRUE;
+		// Only process the click if it's actually in this segment, not to the right of the end-of-line.
+		if(mEditor.getSegmentAtLocalPos(x, y, false) == this)
+		{
+			LLUrlAction::clickAction(getStyle()->getLinkHREF());
+			return TRUE;
+		}
 	}
 
 	return FALSE;
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 3dda6f4cc889bef0ab50129c310d3088a1b32ea4..5b24c635577b643d5015251a8fc1977ec16ae4e4 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -48,6 +48,7 @@
 
 class LLContextMenu;
 class LLTextSegment;
+class LLNormalTextSegment;
 
 typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
 
@@ -61,6 +62,9 @@ class LLTextBase
 	protected LLEditMenuHandler
 {
 public:
+	friend class LLTextSegment;
+	friend class LLNormalTextSegment;
+
 	struct LineSpacingParams : public LLInitParam::Choice<LineSpacingParams>
 	{
 		Alternative<F32>	multiple;
@@ -165,7 +169,7 @@ class LLTextBase
 	S32						getVPad() { return mVPad; }
 	S32						getHPad() { return mHPad; }
 
-	S32						getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
+	S32						getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line = true) const;
 	LLRect					getLocalRectFromDocIndex(S32 pos) const;
 	LLRect					getDocRectFromDocIndex(S32 pos) const;
 
@@ -275,7 +279,7 @@ class LLTextBase
 	// manage segments 
 	void                			getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const;
 	void                			getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp );
-	LLTextSegmentPtr    			getSegmentAtLocalPos( S32 x, S32 y );
+	LLTextSegmentPtr    			getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line = true);
 	segment_set_t::iterator			getSegIterContaining(S32 index);
 	segment_set_t::const_iterator	getSegIterContaining(S32 index) const;
 	void                			clearSegments();
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 8beff26654bae402cee4a5815925c6b9bd58c83e..f58f4ac594cdc1d57eb57dceb9384a8da629dec2 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4598,7 +4598,7 @@
     <key>Type</key>
     <string>Boolean</string>
     <key>Value</key>
-    <integer>0</integer>
+    <integer>1</integer>
   </map>
   <key>MediaShowWithinParcel</key>
   <map>
@@ -10393,17 +10393,6 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
-    <key>VoiceDefaultInternalLevel</key>
-    <map>
-      <key>Comment</key>
-      <string>Internal level of voice set by default. Is equivalent to 0.5 (from 0.0-1.0 range) external voice level (internal = 400 * external^2).</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>S32</string>
-      <key>Value</key>
-      <integer>100</integer>
-    </map>
     <key>VoiceEarLocation</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 68ee9cd612626e853c178beb4926f9d9f2143d53..f4bc35002bf7abd02fa34859e79eecc7a3979140 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1673,6 +1673,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
 	if (mAvatarObject)
 	{
 		mAvatarObject->updateVisualParams();
+		mAvatarObject->invalidateAll();
 	}
 
 	// Start rendering & update the server
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 95a946cee84c75659fffecdc8a75b53e17e509c2..459a61dec3f5ed5b9ba957aa11d286c6db50375b 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -350,7 +350,7 @@ void LLBottomTray::setVisible(BOOL visible)
 	{
 		mBottomTrayLite->setVisible(visible);
 	}
-	else
+	else 
 	{
 		LLPanel::setVisible(visible);
 	}
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index f20ef76bedcf2bc5e46cb11233dd950336e058ee..c6719a3092a9576daef5f695dbc6be389503bf46 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -321,9 +321,6 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	mCommitCallbackRegistrar.add("Pref.VertexShaderEnable",     boost::bind(&LLFloaterPreference::onVertexShaderEnable, this));	
 	mCommitCallbackRegistrar.add("Pref.WindowedMod",            boost::bind(&LLFloaterPreference::onCommitWindowedMode, this));	
 	mCommitCallbackRegistrar.add("Pref.UpdateSliderText",       boost::bind(&LLFloaterPreference::onUpdateSliderText,this, _1,_2));	
-	mCommitCallbackRegistrar.add("Pref.ParcelMediaAutoPlayEnable",       boost::bind(&LLFloaterPreference::onCommitParcelMediaAutoPlayEnable, this));	
-	mCommitCallbackRegistrar.add("Pref.MediaEnabled",           boost::bind(&LLFloaterPreference::onCommitMediaEnabled, this));	
-	mCommitCallbackRegistrar.add("Pref.MusicEnabled",           boost::bind(&LLFloaterPreference::onCommitMusicEnabled, this));	
 	mCommitCallbackRegistrar.add("Pref.QualityPerformance",     boost::bind(&LLFloaterPreference::onChangeQuality, this, _2));	
 	mCommitCallbackRegistrar.add("Pref.applyUIColor",			boost::bind(&LLFloaterPreference::applyUIColor, this ,_1, _2));
 	mCommitCallbackRegistrar.add("Pref.getUIColor",				boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2));
@@ -957,29 +954,6 @@ void LLFloaterPreference::disableUnavailableSettings()
 	}
 }
 
-void LLFloaterPreference::onCommitParcelMediaAutoPlayEnable()
-{
-	BOOL autoplay = getChild<LLCheckBoxCtrl>("autoplay_enabled")->get();
-		
-	gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, autoplay);
-
-	lldebugs << "autoplay now = " << int(autoplay) << llendl;
-}
-
-void LLFloaterPreference::onCommitMediaEnabled()
-{
-	LLCheckBoxCtrl *media_enabled_ctrl = getChild<LLCheckBoxCtrl>("media_enabled");
-	bool enabled = media_enabled_ctrl->get();
-	gSavedSettings.setBOOL("AudioStreamingMedia", enabled);
-}
-
-void LLFloaterPreference::onCommitMusicEnabled()
-{
-	LLCheckBoxCtrl *music_enabled_ctrl = getChild<LLCheckBoxCtrl>("music_enabled");
-	bool enabled = music_enabled_ctrl->get();
-	gSavedSettings.setBOOL("AudioStreamingMusic", enabled);
-}
-
 void LLFloaterPreference::refresh()
 {
 	LLPanel::refresh();
diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp
index 6a88c916d78ed051fec82ee760e9c737c162e0ef..8ad5389566a675f2e68225cd472783d3e0321b98 100644
--- a/indra/newview/llpanelnearbymedia.cpp
+++ b/indra/newview/llpanelnearbymedia.cpp
@@ -38,6 +38,7 @@
 #include "llcheckboxctrl.h"
 #include "llcombobox.h"
 #include "llresizebar.h"
+#include "llresizehandle.h"
 #include "llscrolllistctrl.h"
 #include "llscrolllistitem.h"
 #include "llscrolllistcell.h"
@@ -116,6 +117,20 @@ BOOL LLPanelNearByMedia::postBuild()
 	p.resizing_view = this;
 	addChild( LLUICtrlFactory::create<LLResizeBar>(p) );
 
+	p.rect = LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0);
+	p.name = "resizebar_left";
+	p.min_size = getRect().getWidth();
+	p.side = LLResizeBar::LEFT;
+	addChild( LLUICtrlFactory::create<LLResizeBar>(p) );
+	
+	LLResizeHandle::Params resize_handle_p;
+	resize_handle_p.rect = LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 );
+	resize_handle_p.mouse_opaque(false);
+	resize_handle_p.min_width(getRect().getWidth());
+	resize_handle_p.min_height(getRect().getHeight());
+	resize_handle_p.corner(LLResizeHandle::LEFT_BOTTOM);
+	addChild(LLUICtrlFactory::create<LLResizeHandle>(resize_handle_p));
+
 	mNearbyMediaPanel = getChild<LLUICtrl>("nearby_media_panel");
 	mMediaList = getChild<LLScrollListCtrl>("media_list");
 	mEnableAllCtrl = getChild<LLUICtrl>("all_nearby_media_enable_btn");
@@ -148,8 +163,10 @@ BOOL LLPanelNearByMedia::postBuild()
 	updateColumns();
 	
 	LLView* minimized_controls = getChildView("minimized_controls");
-	mMoreHeight = getRect().getHeight();
-	mLessHeight = getRect().getHeight() - minimized_controls->getRect().mBottom;
+	mMoreRect = getRect();
+	mLessRect = getRect();
+	mLessRect.mBottom = minimized_controls->getRect().mBottom;
+
 	getChild<LLUICtrl>("more_less_btn")->setValue(false);
 	onMoreLess();
 	
@@ -207,7 +224,7 @@ void LLPanelNearByMedia::reshape(S32 width, S32 height, BOOL called_from_parent)
 	LLButton* more_less_btn = getChild<LLButton>("more_less_btn");
 	if (more_less_btn->getValue().asBoolean())
 	{
-		mMoreHeight = getRect().getHeight();
+		mMoreRect = getRect();
 	}
 
 }
@@ -614,6 +631,8 @@ void LLPanelNearByMedia::refreshList()
 
 		// Clear all items so the list gets regenerated.
 		mMediaList->deleteAllItems();
+		mParcelAudioItem = NULL;
+		mParcelMediaItem = NULL;
 		all_items_deleted = true;
 		
 		updateColumns();
@@ -926,10 +945,8 @@ void LLPanelNearByMedia::onMoreLess()
 	// enable resizing when expanded
 	getChildView("resizebar_bottom")->setEnabled(is_more);
 
-	S32 new_height = is_more ? mMoreHeight : mLessHeight;
-
-	LLRect new_rect = getRect();
-	new_rect.mBottom = new_rect.mTop - new_height;
+	LLRect new_rect = is_more ? mMoreRect : mLessRect;
+	new_rect.translate(getRect().mRight - new_rect.mRight, getRect().mTop - new_rect.mTop);
 
 	setShape(new_rect);
 }
diff --git a/indra/newview/llpanelnearbymedia.h b/indra/newview/llpanelnearbymedia.h
index eedfd447de943df5dd5d2a4a7020d38160c8d244..6fe724266b48dc0f74feb7c71eac7a0761598f45 100644
--- a/indra/newview/llpanelnearbymedia.h
+++ b/indra/newview/llpanelnearbymedia.h
@@ -174,11 +174,11 @@ class LLPanelNearByMedia : public LLPanel
 	std::string			mParcelMediaName;
 	std::string			mParcelAudioName;
 	
-	S32				mMoreHeight;
-	S32				mLessHeight;
-	LLFrameTimer			mHoverTimer;
-	LLScrollListItem*		mParcelMediaItem;
-	LLScrollListItem*		mParcelAudioItem;
+	LLRect				mMoreRect;
+	LLRect				mLessRect;
+	LLFrameTimer		mHoverTimer;
+	LLScrollListItem*	mParcelMediaItem;
+	LLScrollListItem*	mParcelAudioItem;
 };
 
 
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index ddb6405c41252f7998cae37ad3f5af1ebf1fb95a..662e6dcabe998737b7c1c2113dfeab62f34dd0cd 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -167,8 +167,8 @@ void LLTexLayerSetBuffer::popProjection() const
 BOOL LLTexLayerSetBuffer::needsRender()
 {
 	const LLVOAvatarSelf* avatar = mTexLayerSet->getAvatar();
-	BOOL upload_now = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal();
-	BOOL needs_update = gAgentQueryManager.hasNoPendingQueries() && (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating;
+	BOOL upload_now = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal() && gAgentQueryManager.hasNoPendingQueries();
+	BOOL needs_update = (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating;
 	if (needs_update)
 	{
 		BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT);
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index 934981b0ad806bf0e12b0334e1cccc2ae45522e2..1d935f5ab8e06fd1bd6987b02ddf2fde6c856ab5 100644
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -251,7 +251,7 @@ void audio_update_wind(bool force_update)
 		{
 			// initialize wind volume (force_update) by using large volume_delta
 			// which is sufficient to completely turn off or turn on wind noise
-			volume_delta = max_wind_volume;
+			volume_delta = 1.f;
 		}
 
 		// mute wind when not flying
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 642f672fafbaaf75863c952d6453c2b5db857139..395467dffb73ab6a45403cd5e88f044729e06156 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1318,6 +1318,9 @@ void LLViewerMediaImpl::loadURI()
 {
 	if(mMediaSource)
 	{
+		// trim whitespace from front and back of URL - fixes EXT-5363
+		LLStringUtil::trim( mMediaURL );
+
 		// *HACK: we don't know if the URI coming in is properly escaped
 		// (the contract doesn't specify whether it is escaped or not.
 		// but LLQtWebKit expects it to be, so we do our best to encode
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 3d153db7338b52791df07926dc7ae74e2f8a0d75..59606f17b2ca4e64556b00f901ff154f16220e2f 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -1115,10 +1115,9 @@ class LLSpeakerVolumeStorage : public LLSingleton<LLSpeakerVolumeStorage>
 	 * Gets stored external (vivox) volume level for specified speaker and
 	 * transforms it into internal (viewer) level.
 	 *
-	 * If specified user is not found default level will be returned. It is equivalent of 
-	 * external level 0.5 from the 0.0..1.0 range.
+	 * If specified user is not found -1 will be returned.
 	 * Internal level is calculated as: internal = 400 * external^2
-	 * Maps 0.0 to 1.0 to internal values 0-400 with default 0.5 == 100
+	 * Maps 0.0 to 1.0 to internal values 0-400
 	 *
 	 * @param[in] speaker_id - LLUUID of user to get his volume level
 	 */
@@ -1157,9 +1156,8 @@ void LLSpeakerVolumeStorage::storeSpeakerVolume(const LLUUID& speaker_id, F32 vo
 
 S32 LLSpeakerVolumeStorage::getSpeakerVolume(const LLUUID& speaker_id)
 {
-	// default internal level of user voice.
-	const static LLUICachedControl<S32> DEFAULT_INTERNAL_VOLUME_LEVEL("VoiceDefaultInternalLevel", 100);
-	S32 ret_val = DEFAULT_INTERNAL_VOLUME_LEVEL;
+	// Return value of -1 indicates no level is stored for this speaker
+	S32 ret_val = -1;
 	speaker_data_map_t::const_iterator it = mSpeakersData.find(speaker_id);
 	
 	if (it != mSpeakersData.end())
@@ -5045,6 +5043,11 @@ LLVoiceClient::participantState *LLVoiceClient::sessionState::addParticipant(con
 		mParticipantsByUUID.insert(participantUUIDMap::value_type(&(result->mAvatarID), result));
 
 		result->mUserVolume = LLSpeakerVolumeStorage::getInstance()->getSpeakerVolume(result->mAvatarID);
+		if (result->mUserVolume != -1)
+		{
+			result->mVolumeDirty = true;
+			mVolumeDirty = true;
+		}
 
 		LL_DEBUGS("Voice") << "participant \"" << result->mURI << "\" added." << LL_ENDL;
 	}