diff options
| -rw-r--r-- | indra/llrender/llfontfreetype.cpp | 23 | ||||
| -rw-r--r-- | indra/llrender/llfontfreetype.h | 2 | ||||
| -rw-r--r-- | indra/llrender/llfontgl.cpp | 57 | ||||
| -rw-r--r-- | indra/llui/llfloater.cpp | 13 | ||||
| -rw-r--r-- | indra/llui/llkeywords.cpp | 82 | ||||
| -rw-r--r-- | indra/llui/llkeywords.h | 29 | ||||
| -rw-r--r-- | indra/llui/llmenugl.cpp | 40 | ||||
| -rw-r--r-- | indra/llui/llmenugl.h | 10 | ||||
| -rw-r--r-- | indra/llui/llresizehandle.cpp | 86 | ||||
| -rw-r--r-- | indra/llui/lltextbase.cpp | 40 | ||||
| -rw-r--r-- | indra/llui/lltextbase.h | 8 | ||||
| -rw-r--r-- | indra/newview/app_settings/settings.xml | 13 | ||||
| -rw-r--r-- | indra/newview/llagentwearables.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/llbottomtray.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llfloaterpreference.cpp | 26 | ||||
| -rw-r--r-- | indra/newview/llpanelnearbymedia.cpp | 31 | ||||
| -rw-r--r-- | indra/newview/llpanelnearbymedia.h | 10 | ||||
| -rw-r--r-- | indra/newview/lltexlayer.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llvieweraudio.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llviewermedia.cpp | 3 | ||||
| -rw-r--r-- | indra/newview/llvoiceclient.cpp | 15 | 
21 files changed, 350 insertions, 147 deletions
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 22fad792da..a86bbbffff 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 7a5d029038..f60d09316d 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -128,7 +128,9 @@ public:  	};  	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 b6a6b448ee..f1f86fd638 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 a55915af35..f3cd112b9a 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 ede32084d0..75342afbe2 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 53377869ca..e5b66dfa56 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -92,8 +92,33 @@ public:  					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 d18abbfb2f..0d56c5ed31 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 8441aaadd4..39d1986461 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 @@ public:  	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 @@ private:  	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 @@ public:  	};  	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 3df09d124a..00214d451c 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 b84e6f45fb..851fb966ec 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 3dda6f4cc8..5b24c63557 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 @@ public:  	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 @@ protected:  	// 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 8beff26654..f58f4ac594 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 68ee9cd612..f4bc35002b 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 95a946cee8..459a61dec3 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 f20ef76bed..c6719a3092 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 6a88c916d7..8ad5389566 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 eedfd447de..6fe724266b 100644 --- a/indra/newview/llpanelnearbymedia.h +++ b/indra/newview/llpanelnearbymedia.h @@ -174,11 +174,11 @@ private:  	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 ddb6405c41..662e6dcabe 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 934981b0ad..1d935f5ab8 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 642f672faf..395467dffb 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 3d153db733..59606f17b2 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -1115,10 +1115,9 @@ public:  	 * 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;  	}  | 
