diff options
| author | Callum Prentice <callum@lindenlab.com> | 2010-03-19 09:46:24 -0700 | 
|---|---|---|
| committer | Callum Prentice <callum@lindenlab.com> | 2010-03-19 09:46:24 -0700 | 
| commit | 40e04fdb3b416a686c66989ee5d44c5eaf97b9fd (patch) | |
| tree | 537b95c75bdb4a96a9f663895f89cb73f54c8f67 | |
| parent | 70df3c1fa72ae8ecddf144452b4fe032ad48182e (diff) | |
| parent | 1a28e325c4d148d2322bc9becb672abf99315a96 (diff) | |
Merge with tip
90 files changed, 1202 insertions, 654 deletions
| diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index f1dda1b2e2..c2c45bec9a 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -122,6 +122,7 @@ public:  	U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes  }; +  LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLOSInfo& info);  LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info);  LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info); diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp index a9e1ee77ef..57e8a22546 100644 --- a/indra/llmessage/llinstantmessage.cpp +++ b/indra/llmessage/llinstantmessage.cpp @@ -61,6 +61,7 @@ const char EMPTY_BINARY_BUCKET[] = "";  const S32 EMPTY_BINARY_BUCKET_SIZE = 1;  const U32 NO_TIMESTAMP = 0;  const std::string SYSTEM_FROM("Second Life"); +const std::string INTERACTIVE_SYSTEM_FROM("F387446C-37C4-45f2-A438-D99CBDBB563B");  const S32 IM_TTL = 1; diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index 272e753f3c..f11b649f78 100644 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -226,6 +226,7 @@ extern const S32 EMPTY_BINARY_BUCKET_SIZE;  extern const U32 NO_TIMESTAMP;  extern const std::string SYSTEM_FROM; +extern const std::string INTERACTIVE_SYSTEM_FROM;  // Number of retry attempts on sending the im.  extern const S32 IM_TTL; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 656f690db5..c3540a717c 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -121,6 +121,8 @@ void LLTexUnit::refreshState(void)  	// We set dirty to true so that the tex unit knows to ignore caching  	// and we reset the cached tex unit state +	gGL.flush(); +	  	glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);  	if (mCurrTexType != TT_NONE)  	{ @@ -150,6 +152,7 @@ void LLTexUnit::activate(void)  	if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)  	{ +		gGL.flush();  		glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);  		gGL.mCurrTextureUnitIndex = mIndex;  	} @@ -181,6 +184,7 @@ void LLTexUnit::disable(void)  	{  		activate();  		unbind(mCurrTexType); +		gGL.flush();  		glDisable(sGLTextureType[mCurrTexType]);  		mCurrTexType = TT_NONE;  	} @@ -386,6 +390,8 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)  {  	if (mIndex < 0 || mCurrTexture == 0) return; +	gGL.flush(); +  	activate();  	glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); @@ -400,6 +406,8 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio  {  	if (mIndex < 0 || mCurrTexture == 0) return; +	gGL.flush(); +  	if (option == TFO_POINT)  	{  		glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -567,6 +575,7 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT  	if (mCurrBlendType != TB_COMBINE || gGL.mDirty)  	{  		mCurrBlendType = TB_COMBINE; +		gGL.flush();  		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);  	} @@ -577,6 +586,8 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT  		return;  	} +	gGL.flush(); +  	// Get the gl source enums according to the eTextureBlendSrc sources passed in  	GLint source1 = getTextureSource(src1);  	GLint source2 = getTextureSource(src2); @@ -709,6 +720,7 @@ void LLTexUnit::setColorScale(S32 scale)  	if (mCurrColorScale != scale || gGL.mDirty)  	{  		mCurrColorScale = scale; +		gGL.flush();  		glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale );  	}  } @@ -718,6 +730,7 @@ void LLTexUnit::setAlphaScale(S32 scale)  	if (mCurrAlphaScale != scale || gGL.mDirty)  	{  		mCurrAlphaScale = scale; +		gGL.flush();  		glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale );  	}  } @@ -853,7 +866,15 @@ void LLRender::scaleUI(F32 x, F32 y, F32 z)  void LLRender::pushUIMatrix()  { -	mUIOffset.push_front(mUIOffset.front()); +	if (mUIOffset.empty()) +	{ +		mUIOffset.push_front(LLVector3(0,0,0)); +	} +	else +	{ +		mUIOffset.push_front(mUIOffset.front()); +	} +	  	if (mUIScale.empty())  	{  		mUIScale.push_front(LLVector3(1,1,1)); @@ -1105,6 +1126,33 @@ void LLRender::flush()  			sUICalls++;  			sUIVerts += mCount;  		} +		 +		if (gDebugGL) +		{ +			if (mMode == LLRender::QUADS) +			{ +				if (mCount%4 != 0) +				{ +					llerrs << "Incomplete quad rendered." << llendl; +				} +			} +			 +			if (mMode == LLRender::TRIANGLES) +			{ +				if (mCount%3 != 0) +				{ +					llerrs << "Incomplete triangle rendered." << llendl; +				} +			} +			 +			if (mMode == LLRender::LINES) +			{ +				if (mCount%2 != 0) +				{ +					llerrs << "Incomplete line rendered." << llendl; +				} +			} +		}  		mBuffer->setBuffer(immediate_mask);  		mBuffer->drawArrays(mMode, 0, mCount); diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 1067c3f1d5..e12776f83a 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -826,9 +826,6 @@ void LLAccordionCtrlTab::draw()  			LLLocalClipRect clip(child_rect);  			drawChild(root_rect,mContainerPanel);  		} -		 - -		gGL.getTexUnit(0)->disable();  	}  } diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 59b551a16d..6a1e3a9425 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -217,7 +217,7 @@ public:  	void 			setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);  	LLPointer<LLUIImage> getImageOverlay() { return mImageOverlay; }  	LLFontGL::HAlign getImageOverlayHAlign() const	{ return mImageOverlayAlignment; } - +	  	void            autoResize();	// resize with label of current btn state   	void            resize(LLUIString label); // resize with label input  	void			setLabel( const LLStringExplicit& label); diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index c1d512e148..3a8efadaa4 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -706,14 +706,17 @@ void LLComboBox::onListMouseUp()  void LLComboBox::onItemSelected(const LLSD& data)  { -	setValue(data); - -	if (mAllowTextEntry && mLastSelectedIndex != -1) +	mLastSelectedIndex = getCurrentIndex(); +	if (mLastSelectedIndex != -1)  	{ -		gFocusMgr.setKeyboardFocus(mTextEntry); -		mTextEntry->selectAll(); -	} +		setLabel(getSelectedItemLabel()); +		if (mAllowTextEntry) +		{ +			gFocusMgr.setKeyboardFocus(mTextEntry); +			mTextEntry->selectAll(); +		} +	}  	// hiding the list reasserts the old value stored in the text editor/dropdown button  	hideList(); @@ -1080,24 +1083,6 @@ LLIconsComboBox::LLIconsComboBox(const LLIconsComboBox::Params& p)  	mLabelColumnIndex(p.label_column)  {} -void LLIconsComboBox::setValue(const LLSD& value) -{ -	BOOL found = mList->selectByValue(value); -	if (found) -	{ -		LLScrollListItem* item = mList->getFirstSelected(); -		if (item) -		{ -			setLabel(getSelectedItemLabel()); -		} -		mLastSelectedIndex = mList->getFirstSelectedIndex(); -	} -	else -	{ -		mLastSelectedIndex = -1; -	} -} -  const std::string LLIconsComboBox::getSelectedItemLabel(S32 column) const  {  	mButton->setImageOverlay(LLComboBox::getSelectedItemLabel(mIconColumnIndex), mButton->getImageOverlayHAlign()); diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 965061ead2..f0bd432f3a 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -221,7 +221,6 @@ protected:  	LLPointer<LLUIImage>	mArrowImage;  	LLUIString			mLabel;  	BOOL				mHasAutocompletedText; -	S32                 mLastSelectedIndex;  private:  	BOOL				mAllowTextEntry; @@ -232,6 +231,7 @@ private:  	commit_callback_t	mTextEntryCallback;  	commit_callback_t	mSelectionCallback;          boost::signals2::connection mTopLostSignalConnection; +    S32					mLastSelectedIndex;  };  // A combo box with icons for the list of items. @@ -247,7 +247,6 @@ public:  		Params();  	}; -	/*virtual*/ void setValue(const LLSD& value);  	/*virtual*/ const std::string getSelectedItemLabel(S32 column = 0) const;  private: diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 4cb336f7ea..ab14c08948 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1354,7 +1354,6 @@ void LLFloater::bringToFront( S32 x, S32 y )  // virtual  void LLFloater::setVisibleAndFrontmost(BOOL take_focus)  { -	LLUI::clearPopups();  	setVisible(TRUE);  	setFrontmost(take_focus);  } diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 0d56c5ed31..fb4a9d032d 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3455,7 +3455,7 @@ LLView* const LLMenuHolderGL::getVisibleMenu() const  	for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)  	{  		LLView* viewp = *child_it; -		if (viewp->getVisible() && dynamic_cast<LLMenuBarGL*>(viewp) == NULL) +		if (viewp->getVisible() && dynamic_cast<LLMenuGL*>(viewp) != NULL)  		{  			return viewp;  		} @@ -3478,8 +3478,7 @@ BOOL LLMenuHolderGL::hideMenus()  		for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)  		{  			LLView* viewp = *child_it; -			// clicks off of menu do not hide menu bar -			if (dynamic_cast<LLMenuBarGL*>(viewp) == NULL && viewp->getVisible()) +			if (dynamic_cast<LLMenuGL*>(viewp) != NULL && viewp->getVisible())  			{  				viewp->setVisible(FALSE);  			} diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 5816cef6af..d7424cf05a 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -402,7 +402,9 @@ LLNotification::LLNotification(const LLNotification::Params& p) :  	mRespondedTo(false),  	mPriority(p.priority),  	mCancelled(false), -	mIgnored(false) +	mIgnored(false), +	mResponderObj(NULL), +	mIsReusable(false)  {  	if (p.functor.name.isChosen())  	{ @@ -416,6 +418,11 @@ LLNotification::LLNotification(const LLNotification::Params& p) :  		mTemporaryResponder = true;  	} +	if(p.responder.isProvided()) +	{ +		mResponderObj = p.responder; +	} +  	mId.generate();  	init(p.name, p.form_elements);  } @@ -425,7 +432,9 @@ LLNotification::LLNotification(const LLSD& sd) :  	mTemporaryResponder(false),  	mRespondedTo(false),  	mCancelled(false), -	mIgnored(false) +	mIgnored(false), +	mResponderObj(NULL), +	mIsReusable(false)  {   	mId.generate();  	mSubstitutions = sd["substitutions"]; @@ -452,6 +461,7 @@ LLSD LLNotification::asLLSD()  	output["expiry"] = mExpiresAt;  	output["priority"] = (S32)mPriority;  	output["responseFunctor"] = mResponseFunctorName; +	output["reusable"] = mIsReusable;  	return output;  } @@ -479,7 +489,9 @@ void LLNotification::updateFrom(LLNotificationPtr other)  	mForm = other->mForm;  	mResponseFunctorName = other->mResponseFunctorName;  	mRespondedTo = other->mRespondedTo; +	mResponse = other->mResponse;  	mTemporaryResponder = other->mTemporaryResponder; +	mIsReusable = other->isReusable();  	update();  } @@ -556,14 +568,16 @@ std::string LLNotification::getSelectedOptionName(const LLSD& response)  void LLNotification::respond(const LLSD& response)  { +	// *TODO may remove mRespondedTo and use mResponce.isDefined() in isRespondedTo()  	mRespondedTo = true; +	mResponse = response;  	// look up the functor  	LLNotificationFunctorRegistry::ResponseFunctor functor =   		LLNotificationFunctorRegistry::instance().getFunctor(mResponseFunctorName);  	// and then call it  	functor(asLLSD(), response); -	if (mTemporaryResponder) +	if (mTemporaryResponder && !isReusable())  	{  		LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);  		mResponseFunctorName = ""; @@ -597,6 +611,16 @@ void LLNotification::setResponseFunctor(std::string const &responseFunctorName)  	mTemporaryResponder = false;  } +void LLNotification::setResponseFunctor(const LLNotificationFunctorRegistry::ResponseFunctor& cb) +{ +	if(mTemporaryResponder) +	{ +		LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); +	} + +	LLNotificationFunctorRegistry::instance().registerFunctor(mResponseFunctorName, cb); +} +  bool LLNotification::payloadContainsAll(const std::vector<std::string>& required_fields) const  {  	for(std::vector<std::string>::const_iterator required_fields_it = required_fields.begin();  @@ -856,8 +880,12 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  		if (wasFound)  		{  			abortProcessing = mChanged(payload); -			mItems.erase(pNotification); -			onDelete(pNotification); +			// do not delete the notification to make LLChatHistory::appendMessage add notification panel to IM window +			if( ! pNotification->isReusable() ) +			{ +				mItems.erase(pNotification); +				onDelete(pNotification); +			}  		}  	}  	return abortProcessing; diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 8d993b71d7..400491a154 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -296,6 +296,7 @@ public:  		Optional<LLSD>							form_elements;  		Optional<LLDate>						time_stamp;  		Optional<LLNotificationContext*>		context; +		Optional<void*>							responder;  		struct Functor : public LLInitParam::Choice<Functor>  		{ @@ -317,6 +318,7 @@ public:  			form_elements("form_elements")  		{  			time_stamp = LLDate::now(); +			responder = NULL;  		}  		Params(const std::string& _name)  @@ -329,6 +331,7 @@ public:  			functor.name = _name;  			name = _name;  			time_stamp = LLDate::now(); +			responder = NULL;  		}  	}; @@ -341,9 +344,12 @@ private:  	LLDate mExpiresAt;  	bool mCancelled;  	bool mRespondedTo; 	// once the notification has been responded to, this becomes true +	LLSD mResponse;  	bool mIgnored;  	ENotificationPriority mPriority;  	LLNotificationFormPtr mForm; +	void* mResponderObj; +	bool mIsReusable;  	// a reference to the template  	LLNotificationTemplatePtr mTemplatep; @@ -384,6 +390,8 @@ public:  	void setResponseFunctor(std::string const &responseFunctorName); +	void setResponseFunctor(const LLNotificationFunctorRegistry::ResponseFunctor& cb); +  	typedef enum e_response_template_type  	{  		WITHOUT_DEFAULT_BUTTON, @@ -423,6 +431,10 @@ public:  	void respond(const LLSD& sd); +	void* getResponder() { return mResponderObj; } + +	void setResponder(void* responder) { mResponderObj = responder; } +  	void setIgnored(bool ignore);  	bool isCancelled() const @@ -435,6 +447,8 @@ public:  		return mRespondedTo;  	} +	const LLSD& getResponse() { return mResponse; } +  	bool isIgnored() const  	{  		return mIgnored; @@ -504,6 +518,10 @@ public:  	{  		return mId;  	} + +	bool isReusable() { return mIsReusable; } + +	void setReusable(bool reusable) { mIsReusable = reusable; }  	// comparing two notifications normally means comparing them by UUID (so we can look them  	// up quickly this way) diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 18ec5b51dd..77caaaa425 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -630,9 +630,7 @@ void LLScrollListCtrl::calcColumnWidths()  			LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex);  			if (!cellp) continue; -			// get text value width only for text cells -			column->mMaxContentWidth = cellp->isText() ? -					llmax(LLFontGL::getFontSansSerifSmall()->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth) : column->mMaxContentWidth; +			column->mMaxContentWidth = llmax(LLFontGL::getFontSansSerifSmall()->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);  		}  		max_item_width += column->mMaxContentWidth; diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h index 714aca9337..785d0633dc 100644 --- a/indra/llui/llsearcheditor.h +++ b/indra/llui/llsearcheditor.h @@ -66,6 +66,8 @@ public:  		}  	}; +	void setCommitOnFocusLost(BOOL b)	{ if (mSearchEditor) mSearchEditor->setCommitOnFocusLost(b); } +  protected:  	LLSearchEditor(const Params&);  	friend class LLUICtrlFactory; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 851fb966ec..633135382e 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -246,7 +246,7 @@ LLTextBase::~LLTextBase()  {  	// Menu, like any other LLUICtrl, is deleted by its parent - gMenuHolder -	clearSegments(); +	mSegments.clear();  }  void LLTextBase::initFromParams(const LLTextBase::Params& p) diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 5121ef5351..b049895526 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -207,7 +207,7 @@ void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )  	// Counterclockwise quad will face the viewer  	if( filled ) -	{ +	{   		gGL.begin( LLRender::QUADS );  			gGL.vertex2i(left, top);  			gGL.vertex2i(left, bottom); diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 57beb71a01..781c111474 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1325,7 +1325,6 @@ void LLView::drawChildren()  				localRectToScreen(viewp->getRect(),&screenRect);  				if ( rootRect.overlaps(screenRect)  && LLUI::sDirtyRect.overlaps(screenRect))  				{ -					glMatrixMode(GL_MODELVIEW);  					LLUI::pushMatrix();  					{  						LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f); @@ -1349,8 +1348,6 @@ void LLView::drawChildren()  		}  		--sDepth;  	} - -	gGL.getTexUnit(0)->disable();  }  void LLView::dirtyRect() diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index b77deb003f..1c6c9e6e9d 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -407,30 +407,3 @@ BOOL LLWindowManager::isWindowValid(LLWindow *window)  {  	return sWindowList.find(window) != sWindowList.end();  } - -S32 LLDisplayInfo::getDisplayWidth() const -{ -#if LL_WINDOWS -	return LLWindowWin32::getDisplayWidth(); -#elif LL_DARWIN -	return LLWindowMacOSX::getDisplayWidth(); -#elif LL_SDL -	return LLWindowSDL::getDisplayWidth(); -#else -	return 1024; //*FIXME -#endif -} - -S32 LLDisplayInfo::getDisplayHeight() const -{ -#if LL_WINDOWS -	return LLWindowWin32::getDisplayHeight(); -#elif LL_DARWIN -	return LLWindowMacOSX::getDisplayHeight(); -#elif LL_SDL -	return LLWindowSDL::getDisplayHeight(); -#else -	return 768; //*FIXME -#endif -} - diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index b769f5071b..55b221e716 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -281,19 +281,4 @@ extern const std::string gURLProtocolWhitelistHandler[];  void simpleEscapeString ( std::string& stringIn  ); -//============================================================================= -// -//	CLASS		LLDisplayInfo -class LLDisplayInfo - -/*!	@brief		Class to query the information about some display settings -*/ -{ -public: -	LLDisplayInfo(){}; ///< Default constructor - -	S32 getDisplayWidth() const; ///< display width -	S32 getDisplayHeight() const; ///< display height -}; -  #endif // _LL_window_h_ diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index ed8c874dcb..ed5d7b1e74 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -40,5 +40,4 @@ void setupCocoa();  CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY);  OSErr releaseImageCursor(CursorRef ref);  OSErr setImageCursor(CursorRef ref); -void getScreenSize(int* width, int* height); -void getVisibleScreen(int *x, int *y, int* width, int* height); + diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 5cab2619fd..59b25e1726 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -116,22 +116,3 @@ OSErr setImageCursor(CursorRef ref)  	return noErr;  } -void getScreenSize(int* width, int* height) -{ -	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; -	NSRect screen_rect = [[NSScreen mainScreen] frame]; -	if (width)  *width  = (int)(screen_rect.size.width); -	if (height) *height = (int)(screen_rect.size.height); -	[pool release]; -} - -void getVisibleScreen(int *x, int *y, int* width, int* height) -{ -	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; -	NSRect visible_rect = [[NSScreen mainScreen] visibleFrame]; -	if (width)  *width = (int)(visible_rect.size.width); -	if (height) *height = (int)(visible_rect.size.height); -	if (x) *x = (int)(visible_rect.origin.x); -	if (y) *y = (int)(visible_rect.origin.y); -	[pool release]; -} diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 224314a490..022b97f481 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1122,33 +1122,7 @@ BOOL LLWindowMacOSX::getMaximized()  BOOL LLWindowMacOSX::maximize()  { -	if (mWindow) -	{ -		// *HACK: Because Mac OSX doesn't have a concept of a "maximized" window, we just -		// stretch it out to the visible screen size. -		Rect win_rect; - -		int visible_x; -		int visible_y; -		int visible_width; -		int visible_height; -		int screen_width; -		int screen_height; - -		getScreenSize(&screen_width, &screen_height); -		getVisibleScreen(&visible_x, &visible_y, &visible_width, &visible_height); - -		int mac_os_menu_bar_height = screen_height - (visible_height + visible_y); -		::SetRect(&win_rect, -				  visible_x, -				  mac_os_menu_bar_height, -				  visible_width + visible_x, -				  visible_height + mac_os_menu_bar_height); - -		::SetWindowBounds(mWindow, kWindowStructureRgn, &win_rect); - -		return TRUE; -	} +	// TODO  	return FALSE;  } @@ -3499,26 +3473,6 @@ MASK LLWindowMacOSX::modifiersToMask(SInt16 modifiers)  	return mask;  }	 -// static -S32 LLWindowMacOSX::getDisplayWidth() -{ -	S32 width = 1024; -	// Need to invoke cocoa before use getScreenSize() -	setupCocoa(); -	getScreenSize(&width, NULL); -	return width; -} - -// static -S32 LLWindowMacOSX::getDisplayHeight() -{ -	S32 height = 768; -	// Need to invoke cocoa before use getScreenSize() -	setupCocoa(); -	getScreenSize(NULL, &height); -	return height; -} -  #if LL_OS_DRAGDROP_ENABLED  OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index 86036a261c..7c6b324029 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -123,8 +123,6 @@ public:  	// Provide native key event data  	/*virtual*/ LLSD getNativeKeyData(); -	static S32 getDisplayWidth(); -	static S32 getDisplayHeight();  protected:  	LLWindowMacOSX(LLWindowCallbacks* callbacks, diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index cb4e04511c..1f705f9e60 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -187,47 +187,6 @@ Display* LLWindowSDL::get_SDL_Display(void)  }  #endif // LL_X11 -// static -S32 LLWindowSDL::getDisplayWidth() -{ -#if LL_GTK -	if (LLWindowSDL::ll_try_gtk_init()) -	{ -		return gdk_screen_width(); -	} -#endif // LL_GTK - -#if LL_X11 -	Display *display = XOpenDisplay(NULL); -	int screen_num = DefaultScreen(display); -	S32 width = DisplayWidth(display, screen_num); -	XCloseDisplay(display); -	return width; -#endif //LL_X11 - -	return 1024; -} - -// static -S32 LLWindowSDL::getDisplayHeight() -{ -#if LL_GTK -	if (LLWindowSDL::ll_try_gtk_init()) -	{ -		return gdk_screen_height(); -	} -#endif // LL_GTK - -#if LL_X11 -	Display *display = XOpenDisplay(NULL); -	int screen_num = DefaultScreen(display); -	S32 height = DisplayHeight(display, screen_num); -	XCloseDisplay(display); -	return height; -#endif //LL_X11 - -	return 768; -}  LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,  			 const std::string& title, S32 x, S32 y, S32 width, @@ -950,68 +909,7 @@ BOOL LLWindowSDL::getMaximized()  	if (mWindow)  	{ -#if LL_X11 -		if (mSDL_Display) -		{ -			maybe_lock_display(); - -			// Return data in the specified format, XA_ATOM. -			U8*	prop; -			// Actual format of the property. -			int format; -			// Actual number of items stored in the prop return data. -			unsigned long nitems; -			// Number of bytes remaining to be read in the property if a partial read was performed. -			unsigned long bytes_after; -			// Atom identifier that defines the actual type of the property. -			Atom type; - -			// Atom used to obtain list of hints describing the window state. -			Atom wm_state = XInternAtom(mSDL_Display, "_NET_WM_STATE", False); - -			// Atoms indicates that the window is vertically/horizontally maximized.  -			Atom max_vert = XInternAtom(mSDL_Display, "_NET_WM_STATE_MAXIMIZED_VERT", False); -			Atom max_horz = XInternAtom(mSDL_Display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); - -			// How many atoms in which we interested are present in list of hints. -			U32 pass = 0; - -			do -			{ -				nitems = 0; -				bytes_after = 0; -				type = None; -				if ( (XGetWindowProperty (mSDL_Display, -										  mSDL_XWindowID, -										  wm_state, -										  0, UINT_MAX, -										  False, XA_ATOM, -										  &type, &format, -										  &nitems, &bytes_after, -										  &prop) == Success) -					 && type != None ) -				{ -					Atom *atoms = (Atom *)prop; -					for (unsigned long i=0; i<nitems; ++i) -					{ -						if (atoms[i] == max_horz) -							++pass; -						else if (atoms[i] == max_vert) -							++pass; -					} -					XFree (atoms); -				} -				else -				{ -					break; -				} -			} while (bytes_after > 0); - -			result = (pass == 2); - -			maybe_unlock_display(); -		} -#endif // LL_X11 +		// TODO  	}  	return(result); @@ -1019,103 +917,7 @@ BOOL LLWindowSDL::getMaximized()  BOOL LLWindowSDL::maximize()  { -#if LL_X11 -	if (mSDL_Display && !mFullscreen) -	{ -		maybe_lock_display(); - -		BOOL is_maximize_allowed = FALSE; - -		// Check if maximize is allowed -		{ -			// Return data in the specified format, XA_ATOM. -			U8*	prop; -			// Actual format of the property. -			int format; -			// Actual number of items stored in the prop return data. -			unsigned long nitems; -			// Number of bytes remaining to be read in the property if a partial read was performed. -			unsigned long bytes_after; -			// Atom identifier that defines the actual type of the property. -			Atom type; - -			// Atom used to obtain a list of atoms indicating user operations that the Window Manager supports for this window. -			Atom allowed_act  = XInternAtom(mSDL_Display, "_NET_WM_ALLOWED_ACTIONS", False); - -			// Atoms that indicates that the window may be vertically/horizontally maximized. -			Atom max_vert_act = XInternAtom(mSDL_Display, "_NET_WM_ACTION_MAXIMIZE_HORZ", False); -			Atom max_horz_act = XInternAtom(mSDL_Display, "_NET_WM_ACTION_MAXIMIZE_VERT", False); - -			// How many atoms in which we interested are present in list of hints. -			U32 pass = 0; - -			do -			{ -				nitems = 0; -				bytes_after = 0; -				type = None; -				if ( (XGetWindowProperty (mSDL_Display, -										  mSDL_XWindowID, -										  allowed_act, -										  0, UINT_MAX, -										  False, XA_ATOM, -										  &type, &format, -										  &nitems, &bytes_after, -										  &prop) == Success) -					 && type != None ) -				{ -					Atom *atoms = (Atom *)prop; -					for (unsigned long i=0; i<nitems; ++i) -					{ -						if (atoms[i] == max_vert_act) -							++pass; -						else if (atoms[i] == max_horz_act) -							++pass; -					} -					XFree (atoms); -				} -				else -				{ -					break; -				} -			} while (bytes_after > 0); - -			is_maximize_allowed = (pass == 2); -		} - -		// Send maximize event to X11 system -		if (is_maximize_allowed) -		{ -			XEvent xev; - -			// Atom describing the window state. -			Atom wm_state = XInternAtom(mSDL_Display, "_NET_WM_STATE", False); - -			// Atoms indicates that the window is vertically/horizontally maximized.  -			Atom max_vert = XInternAtom(mSDL_Display, "_NET_WM_STATE_MAXIMIZED_VERT", False); -			Atom max_horz = XInternAtom(mSDL_Display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); - -			memset(&xev, 0, sizeof(xev)); -			xev.type = ClientMessage; -			xev.xclient.window = mSDL_XWindowID; -			xev.xclient.message_type = wm_state; -			xev.xclient.format = 32; -			xev.xclient.data.l[0] = 1;  // add/set property -			xev.xclient.data.l[1] = max_vert; -			xev.xclient.data.l[2] = max_horz; -			xev.xclient.data.l[3] = 0; -			xev.xclient.data.l[4] = 0; - -			XSendEvent(mSDL_Display, -					   DefaultRootWindow(mSDL_Display), -					   False, -					   SubstructureNotifyMask, &xev); -		} - -		maybe_unlock_display(); -		return is_maximize_allowed; -	} -#endif // LL_X11 +	// TODO  	return FALSE;  } diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index 2311a361fa..e6bdd46a77 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -148,9 +148,6 @@ public:  	static Display* get_SDL_Display(void);  #endif // LL_X11	 -	static S32 getDisplayWidth(); -	static S32 getDisplayHeight(); -  protected:  	LLWindowSDL(LLWindowCallbacks* callbacks,  		const std::string& title, int x, int y, int width, int height, U32 flags, diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 5f778d6208..8df9dad581 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -3720,16 +3720,5 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()  	return std::vector<std::string>();  } -// static -S32 LLWindowWin32::getDisplayWidth() -{ -	return ::GetSystemMetrics(SM_CXVIRTUALSCREEN); -} - -// static -S32 LLWindowWin32::getDisplayHeight() -{ -	return ::GetSystemMetrics(SM_CYVIRTUALSCREEN); -}  #endif // LL_WINDOWS diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index c221ec0192..9d57735772 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -120,9 +120,6 @@ public:  	static std::vector<std::string> getDynamicFallbackFontList(); -	static S32 getDisplayWidth(); -	static S32 getDisplayHeight(); -  protected:  	LLWindowWin32(LLWindowCallbacks* callbacks,  		const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,  diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f8d556bb80..9f474a39bc 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10369,7 +10369,7 @@        <key>Type</key>        <string>Boolean</string>        <key>Value</key> -      <integer>0</integer> +      <integer>1</integer>      </map>      <key>VivoxDebugLevel</key>      <map> @@ -10677,7 +10677,7 @@        <key>Type</key>        <string>S32</string>        <key>Value</key> -      <integer>700</integer> +      <integer>738</integer>      </map>      <key>WindowMaximized</key>      <map> @@ -10699,7 +10699,7 @@        <key>Type</key>        <string>S32</string>        <key>Value</key> -      <integer>1000</integer> +      <integer>1024</integer>      </map>      <key>WindowX</key>      <map> diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 65503d4998..ebadd8a165 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -443,6 +443,11 @@ void LLAgentWearables::saveWearable(const EWearableType type, const U32 index, B  		new_wearable->setItemID(old_item_id); // should this be in LLWearable::copyDataFrom()?  		setWearable(type,index,new_wearable); +		// old_wearable may still be referred to by other inventory items. Revert +		// unsaved changes so other inventory items aren't affected by the changes +		// that were just saved. +		old_wearable->revertValues(); +  		LLInventoryItem* item = gInventory.getItem(old_item_id);  		if (item)  		{ @@ -545,6 +550,11 @@ void LLAgentWearables::saveWearableAs(const EWearableType type,  		category_id,  		new_name,  		cb); + +	// old_wearable may still be referred to by other inventory items. Revert +	// unsaved changes so other inventory items aren't affected by the changes +	// that were just saved. +	old_wearable->revertValues();  }  void LLAgentWearables::revertWearable(const EWearableType type, const U32 index) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index f2d15757c9..b3dfb8f141 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -399,7 +399,7 @@ bool LLWearableHoldingPattern::isFetchCompleted()  bool LLWearableHoldingPattern::isTimedOut()  { -	static F32 max_wait_time = 20.0;  // give up if wearable fetches haven't completed in max_wait_time seconds. +	static F32 max_wait_time = 60.0;  // give up if wearable fetches haven't completed in max_wait_time seconds.  	return mWaitTime.getElapsedTimeF32() > max_wait_time;   } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 2384e6c5ba..11c252406a 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -304,10 +304,7 @@ static std::string gLaunchFileOnQuit;  // Used on Win32 for other apps to identify our window (eg, win_setup)  const char* const VIEWER_WINDOW_CLASSNAME = "Second Life"; -static const S32 FIRST_RUN_WINDOW_WIDTH = 1024; -//should account for Windows task bar -static const S32 FIRST_RUN_WINDOW_HIGHT = 738;  //----------------------------------------------------------------------------  // List of entries from strings.xml to always replace @@ -2374,35 +2371,12 @@ bool LLAppViewer::initWindow()  	// store setting in a global for easy access and modification  	gNoRender = gSavedSettings.getBOOL("DisableRendering"); -	S32 window_x = gSavedSettings.getS32("WindowX"); -	S32 window_y = gSavedSettings.getS32("WindowY"); -	S32 window_width = gSavedSettings.getS32("WindowWidth"); -	S32 window_height = gSavedSettings.getS32("WindowHeight"); - -	bool show_maximized = gSavedSettings.getBOOL("WindowMaximized"); - -	bool first_run = gSavedSettings.getBOOL("FirstLoginThisInstall"); - -	if (first_run)//for first login  -	{ -		window_width = FIRST_RUN_WINDOW_WIDTH;//yep hardcoded -		window_height = FIRST_RUN_WINDOW_HIGHT; -		 -		//if screen resolution is lower then first run width/height then show maximized -		LLDisplayInfo display_info; -		if(display_info.getDisplayWidth() <= FIRST_RUN_WINDOW_WIDTH -			|| display_info.getDisplayHeight()<=FIRST_RUN_WINDOW_HIGHT) -		{ -			show_maximized = true; -		} -	} -  	// always start windowed  	BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth");  	gViewerWindow = new LLViewerWindow(gWindowTitle,   		VIEWER_WINDOW_CLASSNAME, -		window_x, window_y, -		window_width, window_height, +		gSavedSettings.getS32("WindowX"), gSavedSettings.getS32("WindowY"), +		gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"),  		FALSE, ignorePixelDepth);  	LLNotificationsUI::LLNotificationManager::getInstance(); @@ -2413,7 +2387,7 @@ bool LLAppViewer::initWindow()  		gViewerWindow->toggleFullscreen(FALSE);  	} -	if (show_maximized) +	if (gSavedSettings.getBOOL("WindowMaximized"))  	{  		gViewerWindow->mWindow->maximize();  		gViewerWindow->getWindow()->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio")); diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 80cf8f1d61..8441796219 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -182,7 +182,10 @@ void LLAssetUploadResponder::uploadFailure(const LLSD& content)  	// deal with L$ errors  	if (reason == "insufficient funds")  	{ -		LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("uploading_costs"), LLGlobalEconomy::Singleton::getInstance()->getPriceUpload()); +		S32 price = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); +		LLStringUtil::format_map_t args; +		args["AMOUNT"] = llformat("%d", price); +		LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("uploading_costs", args), price);  	}  	else  	{ diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index e1c96d4a16..ac60fe6ba6 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -447,6 +447,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)  :	LLUICtrl(p),  	mMessageHeaderFilename(p.message_header),  	mMessageSeparatorFilename(p.message_separator), +	mMessagePlaintextSeparatorFilename(p.message_plaintext_separator),  	mLeftTextPad(p.left_text_pad),  	mRightTextPad(p.right_text_pad),  	mLeftWidgetPad(p.left_widget_pad), @@ -534,6 +535,12 @@ LLView* LLChatHistory::getSeparator()  	return separator;  } +LLView* LLChatHistory::getPlaintextSeparator() +{ +	LLPanel* separator = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>(mMessagePlaintextSeparatorFilename, NULL, LLPanel::child_registry_t::instance()); +	return separator; +} +  LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style_params)  {  	LLChatHistoryHeader* header = LLChatHistoryHeader::createInstance(mMessageHeaderFilename); @@ -632,6 +639,15 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  	if (use_plain_text_chat_history)  	{ +		// append plaintext separator +		LLView* separator = getPlaintextSeparator(); +		LLInlineViewSegment::Params p; +		p.force_newline = true; +		p.left_pad = mLeftWidgetPad; +		p.right_pad = mRightWidgetPad; +		p.view = separator; +		mEditor->appendWidget(p, "\n", false); +  		mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, style_params);  		if (utf8str_trim(chat.mFromName).size() != 0) @@ -734,7 +750,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		LLNotificationPtr notification = LLNotificationsUtil::find(chat.mNotifId);  		if (notification != NULL)  		{ -			LLToastNotifyPanel* notify_box = new LLToastNotifyPanel( +			LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel(  					notification);  			//we can't set follows in xml since it broke toasts behavior  			notify_box->setFollowsLeft(); @@ -743,7 +759,9 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  			ctrl_list_t ctrls = notify_box->getControlPanel()->getCtrlList();  			S32 offset = 0; -			for (ctrl_list_t::iterator it = ctrls.begin(); it != ctrls.end(); it++) +			// Children were added by addChild() which uses push_front to insert them into list, +			// so to get buttons in correct order reverse iterator is used (EXT-5906)  +			for (ctrl_list_t::reverse_iterator it = ctrls.rbegin(); it != ctrls.rend(); it++)  			{  				LLButton * button = dynamic_cast<LLButton*> (*it);  				if (button != NULL) diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 950b32861b..dfe5ea98e6 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -47,6 +47,8 @@ class LLChatHistory : public LLUICtrl  			Optional<std::string>	message_header;  			//Message separator filename  			Optional<std::string>	message_separator; +			//Message plaintext  separator filename +			Optional<std::string>	message_plaintext_separator;  			//Text left padding from the scroll rect  			Optional<S32>			left_text_pad;  			//Text right padding from the scroll rect @@ -69,6 +71,7 @@ class LLChatHistory : public LLUICtrl  			Params()  			:	message_header("message_header"),  				message_separator("message_separator"), +				message_plaintext_separator("message_plaintext_separator"),  				left_text_pad("left_text_pad"),  				right_text_pad("right_text_pad"),  				left_widget_pad("left_widget_pad"), @@ -97,6 +100,11 @@ class LLChatHistory : public LLUICtrl  		 */  		LLView* getSeparator();  		/** +		 * Builds a message plaintext  separator. +		 * @return pointer to LLView separator object. +		 */ +		LLView* getPlaintextSeparator(); +		/**  		 * Builds a message header.  		 * @return pointer to LLView header object.  		 */ @@ -133,6 +141,7 @@ class LLChatHistory : public LLUICtrl  		std::string mMessageHeaderFilename;  		std::string mMessageSeparatorFilename; +		std::string mMessagePlaintextSeparatorFilename;  		S32 mLeftTextPad;  		S32 mRightTextPad; diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 8efa814a2e..1f92686a43 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -1137,7 +1137,7 @@ void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){  	S32 unread = data["participant_unread"].asInteger();  	LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); -	if (im_floater && im_floater->getVisible()) +	if (im_floater && im_floater->getVisible() && im_floater->hasFocus())  	{  		unread = 0;  	} diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp index fba557c656..589f570d96 100644 --- a/indra/newview/llfloaterbuy.cpp +++ b/indra/newview/llfloaterbuy.cpp @@ -246,7 +246,8 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj,  		// Compute icon for this item  		BOOL item_is_multi = FALSE; -		if ( inv_item->getFlags() & LLInventoryItem::II_FLAGS_LANDMARK_VISITED ) +		if ( inv_item->getFlags() & LLInventoryItem::II_FLAGS_LANDMARK_VISITED  +			|| inv_item->getFlags() & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS)  		{  			item_is_multi = TRUE;  		} diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp index 1642e6725e..7fddd1fc5f 100644 --- a/indra/newview/llfloaterbuycurrency.cpp +++ b/indra/newview/llfloaterbuycurrency.cpp @@ -234,8 +234,7 @@ void LLFloaterBuyCurrencyUI::updateUI()  			if (mHasTarget)  			{  				childSetVisible("buy_action", true); -				childSetTextArg("buy_action", "[NAME]", mTargetName); -				childSetTextArg("buy_action", "[PRICE]", llformat("%d",mTargetPrice)); +				childSetTextArg("buy_action", "[ACTION]", mTargetName);  			}  		} diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index e998d10fcc..3487f52f35 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -183,7 +183,6 @@ void LLVoiceSetKeyDialog::onCancel(void* user_data)  // a static member and update all our static callbacks  void handleNameTagOptionChanged(const LLSD& newvalue);	 -viewer_media_t get_web_media();  bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response);  //bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater); @@ -191,23 +190,14 @@ bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response  void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator); -viewer_media_t get_web_media() -{ -	viewer_media_t media_source = LLViewerMedia::newMediaImpl(LLUUID::null); -	media_source->initializeMedia("text/html"); -	return media_source; -} - -  bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response)  {  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);  	if ( option == 0 ) // YES  	{  		// clean web -		viewer_media_t media_source = get_web_media(); -		if (media_source && media_source->hasMedia()) -			media_source->getMediaPlugin()->clear_cache(); +		LLViewerMedia::clearAllCaches(); +		LLViewerMedia::clearAllCookies();  		// clean nav bar history  		LLNavigationBar::getInstance()->clearHistoryCache(); @@ -429,17 +419,14 @@ void LLFloaterPreference::apply()  	std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");  	childSetText("cache_location", cache_location);		 -	viewer_media_t media_source = get_web_media(); -	if (media_source && media_source->hasMedia()) +	LLViewerMedia::setCookiesEnabled(childGetValue("cookies_enabled")); +	 +	if(hasChild("web_proxy_enabled") &&hasChild("web_proxy_editor") && hasChild("web_proxy_port"))  	{ -		media_source->getMediaPlugin()->enable_cookies(childGetValue("cookies_enabled")); -		if(hasChild("web_proxy_enabled") &&hasChild("web_proxy_editor") && hasChild("web_proxy_port")) -		{ -			bool proxy_enable = childGetValue("web_proxy_enabled"); -			std::string proxy_address = childGetValue("web_proxy_editor"); -			int proxy_port = childGetValue("web_proxy_port"); -			media_source->getMediaPlugin()->proxy_setup(proxy_enable, proxy_address, proxy_port); -		} +		bool proxy_enable = childGetValue("web_proxy_enabled"); +		std::string proxy_address = childGetValue("web_proxy_editor"); +		int proxy_port = childGetValue("web_proxy_port"); +		LLViewerMedia::setProxyConfig(proxy_enable, proxy_address, proxy_port);  	}  //	LLWString busy_response = utf8str_to_wstring(getChild<LLUICtrl>("busy_response")->getValue().asString()); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 0f3c176cea..42a7eeff26 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -84,6 +84,8 @@  #include "llassetuploadresponders.h"  #include "llagentui.h" +#include "lltrans.h" +  const U32 INCLUDE_SCREENSHOT  = 0x01 << 0;  //----------------------------------------------------------------------------- @@ -372,8 +374,7 @@ void LLFloaterReporter::onClickSend(void *userdata)  				return;  			} - -		LLUploadDialog::modalUploadDialog("Uploading...\n\nReport"); +		LLUploadDialog::modalUploadDialog(LLTrans::getString("uploading_abuse_report"));  		// *TODO don't upload image if checkbox isn't checked  		std::string url = gAgent.getRegion()->getCapability("SendUserReport");  		std::string sshot_url = gAgent.getRegion()->getCapability("SendUserReportWithScreenshot"); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 77eaebb0bc..91f4f57e54 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -128,6 +128,11 @@ void LLIMFloater::onFocusReceived()  	LLIMModel::getInstance()->setActiveSessionID(mSessionID);  	LLBottomTray::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true); + +	if (getVisible()) +	{ +		LLIMModel::instance().sendNoUnreadMessages(mSessionID); +	}  }  // virtual @@ -454,7 +459,7 @@ void LLIMFloater::getAllowedRect(LLRect& rect)  void LLIMFloater::setDocked(bool docked, bool pop_on_undock)  {  	// update notification channel state -	LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*> +	LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>  		(LLNotificationsUI::LLChannelManager::getInstance()->  											findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); @@ -473,7 +478,7 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock)  void LLIMFloater::setVisible(BOOL visible)  { -	LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*> +	LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>  		(LLNotificationsUI::LLChannelManager::getInstance()->  											findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));  	LLTransientDockableFloater::setVisible(visible); @@ -609,7 +614,16 @@ void LLIMFloater::updateMessages()  	bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory");  	std::list<LLSD> messages; -	LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1); + +	// we shouldn't reset unread message counters if IM floater doesn't have focus +	if (hasFocus()) +	{ +		LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1); +	} +	else +	{ +		LLIMModel::instance().getMessagesSilently(mSessionID, messages, mLastMessageIndex+1); +	}  	if (messages.size())  	{ @@ -642,6 +656,24 @@ void LLIMFloater::updateMessages()  			if (msg.has("notification_id"))  			{  				chat.mNotifId = msg["notification_id"].asUUID(); +				// if notification exists - embed it +				if (LLNotificationsUtil::find(chat.mNotifId) != NULL) +				{ +					// remove embedded notification from channel +					LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> +							(LLNotificationsUI::LLChannelManager::getInstance()-> +																findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); +					if (getVisible()) +					{ +						// toast will be automatically closed since it is not storable toast +						channel->hideToast(chat.mNotifId); +					} +				} +				// if notification doesn't exist - try to use next message which should be log entry +				else +				{ +					continue; +				}  			}  			//process text message  			else @@ -651,6 +683,19 @@ void LLIMFloater::updateMessages()  			mChatHistory->appendMessage(chat, chat_args);  			mLastMessageIndex = msg["index"].asInteger(); + +			// if it is a notification - next message is a notification history log, so skip it +			if (chat.mNotifId.notNull() && LLNotificationsUtil::find(chat.mNotifId) != NULL) +			{ +				if (++iter == iter_end) +				{ +					break; +				} +				else +				{ +					mLastMessageIndex++; +				} +			}  		}  	}  } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index b3f085ef6d..7a4febec20 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -608,10 +608,10 @@ bool LLIMModel::clearSession(const LLUUID& session_id)  	return true;  } -void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index) +void LLIMModel::getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)  {  	LLIMSession* session = findIMSession(session_id); -	if (!session)  +	if (!session)  	{  		llwarns << "session " << session_id << "does not exist " << llendl;  		return; @@ -619,7 +619,7 @@ void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages,  	int i = session->mMsgs.size() - start_index; -	for (std::list<LLSD>::iterator iter = session->mMsgs.begin();  +	for (std::list<LLSD>::iterator iter = session->mMsgs.begin();  		iter != session->mMsgs.end() && i > 0;  		iter++)  	{ @@ -628,6 +628,16 @@ void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages,  		messages.push_back(*iter);  		i--;  	} +} + +void LLIMModel::sendNoUnreadMessages(const LLUUID& session_id) +{ +	LLIMSession* session = findIMSession(session_id); +	if (!session) +	{ +		llwarns << "session " << session_id << "does not exist " << llendl; +		return; +	}  	session->mNumUnread = 0;  	session->mParticipantUnreadMessageCount = 0; @@ -639,6 +649,13 @@ void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages,  	mNoUnreadMsgsSignal(arg);  } +void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index) +{ +	getMessagesSilently(session_id, messages, start_index); + +	sendNoUnreadMessages(session_id); +} +  bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) {  	LLIMSession* session = findIMSession(session_id); @@ -717,13 +734,22 @@ LLIMModel::LLIMSession* LLIMModel::addMessageSilently(const LLUUID& session_id,  		return NULL;  	} -	addToHistory(session_id, from, from_id, utf8_text); -	if (log2file) logToFile(session_id, from, from_id, utf8_text); +	// replace interactive system message marker with correct from string value +	std::string from_name = from; +	if (INTERACTIVE_SYSTEM_FROM == from) +	{ +		from_name = SYSTEM_FROM; +	} + +	addToHistory(session_id, from_name, from_id, utf8_text); +	if (log2file) logToFile(session_id, from_name, from_id, utf8_text);  	session->mNumUnread++;  	//update count of unread messages from real participant -	if (!(from_id.isNull() || from_id == gAgentID || SYSTEM_FROM == from)) +	if (!(from_id.isNull() || from_id == gAgentID || SYSTEM_FROM == from) +			// we should increment counter for interactive system messages() +			|| INTERACTIVE_SYSTEM_FROM == from)  	{  		++(session->mParticipantUnreadMessageCount);  	} diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index e7404074e0..f1693d0e17 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -178,6 +178,17 @@ public:  	bool clearSession(const LLUUID& session_id);  	/** +	 * Populate supplied std::list with messages starting from index specified by start_index without +	 * emitting no unread messages signal. +	 */ +	void getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); + +	/** +	 * Sends no unread messages signal. +	 */ +	void sendNoUnreadMessages(const LLUUID& session_id); + +	/**  	 * Populate supplied std::list with messages starting from index specified by start_index  	 */  	void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 1f918c72ea..6fedd9ac4d 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -103,7 +103,7 @@ std::string ICON_NAME[ICON_NAME_COUNT] =  	"Inv_Script",  	"Inv_Clothing",  	"Inv_Object", -	"Inv_Object", +	"Inv_Object_Multi",  	"Inv_Notecard",  	"Inv_Skin",  	"Inv_Snapshot", @@ -5358,7 +5358,10 @@ LLUIImagePtr LLLinkItemBridge::getIcon() const  {  	if (LLViewerInventoryItem *item = getItem())  	{ -		return get_item_icon(item->getActualType(), item->getInventoryType(), 0, FALSE); +		U32 attachment_point = (item->getFlags() & 0xff); // low byte of inventory flags +		bool is_multi =  LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS & item->getFlags(); + +		return get_item_icon(item->getActualType(), item->getInventoryType(), attachment_point, is_multi);  	}  	return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE);  } diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 2fb8aea4e9..62c2d80609 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -54,7 +54,6 @@  #include "llappviewer.h"  #include "lldbstrings.h"  #include "llviewerstats.h" -#include "llmutelist.h"  #include "llnotificationsutil.h"  #include "llcallbacklist.h"  #include "llpreview.h" diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 2d3c4b187e..95094f6b52 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -128,68 +128,26 @@ LLMute::LLMute(const LLUUID& id, const std::string& name, EType type, U32 flags)  } -std::string LLMute::getDisplayName() const +std::string LLMute::getDisplayType() const  { -	std::string name_with_suffix = mName;  	switch (mType)  	{  		case BY_NAME:  		default: -			name_with_suffix += " " + LLTrans::getString("MuteByName"); +			return LLTrans::getString("MuteByName");  			break;  		case AGENT: -			name_with_suffix += " " + LLTrans::getString("MuteAgent"); +			return LLTrans::getString("MuteAgent");  			break;  		case OBJECT: -			name_with_suffix += " " + LLTrans::getString("MuteObject"); +			return LLTrans::getString("MuteObject");  			break;  		case GROUP: -			name_with_suffix += " " + LLTrans::getString("MuteGroup"); +			return LLTrans::getString("MuteGroup");  			break;  	} -	return name_with_suffix;  } -void LLMute::setFromDisplayName(const std::string& display_name) -{ -	size_t pos = 0; -	mName = display_name; -	 -	pos = mName.rfind(" " + LLTrans::getString("MuteGroup")); -	if (pos != std::string::npos) -	{ -		mName.erase(pos); -		mType = GROUP; -		return; -	} -	 -	pos = mName.rfind(" " + LLTrans::getString("MuteObject")); -	if (pos != std::string::npos) -	{ -		mName.erase(pos); -		mType = OBJECT; -		return; -	} -	 -	pos = mName.rfind(" " + LLTrans::getString("MuteAgent")); -	if (pos != std::string::npos) -	{ -		mName.erase(pos); -		mType = AGENT; -		return; -	} -	 -	pos = mName.rfind(" " + LLTrans::getString("MuteByName")); -	if (pos != std::string::npos) -	{ -		mName.erase(pos); -		mType = BY_NAME; -		return; -	} -	 -	llwarns << "Unable to set mute from display name " << display_name << llendl; -	return; -}  /* static */  LLMuteList* LLMuteList::getInstance() diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index e1e81a24b4..7cb11e6031 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -63,14 +63,8 @@ public:  	LLMute(const LLUUID& id, const std::string& name = std::string(), EType type = BY_NAME, U32 flags = 0); -	// Returns name + suffix based on type -	// For example:  "James Tester (resident)" -	std::string getDisplayName() const; -	 -	// Converts a UI name into just the agent or object name -	// For example: "James Tester (resident)" sets the name to "James Tester" -	// and the type to AGENT. -	void setFromDisplayName(const std::string& display_name); +	// Returns localized type name of muted item +	std::string getDisplayType() const;  public:  	LLUUID		mID;	// agent or object id diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 08ae93c3a6..e199f9f180 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -268,24 +268,23 @@ void LLNearbyChatScreenChannel::showToastsBottom()  			}  			break;  		} -		else -		{ -			toast_rect = toast->getRect(); -			toast_rect.setLeftTopAndSize(getRect().mLeft , toast_top, toast_rect.getWidth() ,toast_rect.getHeight()); -		 -			toast->setRect(toast_rect); -			toast->setIsHidden(false); -			toast->setVisible(TRUE); +		bottom = toast_top - toast->getTopPad(); +	} -			if(!toast->hasFocus()) -			{ -				// Fixing Z-order of toasts (EXT-4862) -				// Next toast will be positioned under this one. -				gFloaterView->sendChildToBack(toast); -			} -			 -			bottom = toast->getRect().mTop - toast->getTopPad(); -		}		 +	// use reverse order to provide correct z-order and avoid toast blinking +	for(std::vector<LLToast*>::reverse_iterator it = m_active_toasts.rbegin(); it != m_active_toasts.rend(); ++it) +	{ +		LLToast* toast = (*it); +		S32 toast_top = bottom + toast->getTopPad(); + +		toast_rect = toast->getRect(); +		toast_rect.setLeftTopAndSize(getRect().mLeft , toast_top, toast_rect.getWidth() ,toast_rect.getHeight()); + +		toast->setRect(toast_rect); +		toast->setIsHidden(false); +		toast->setVisible(TRUE); + +		bottom = toast->getRect().mBottom - margin;  	}  } diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index a163b6fd62..1dc0e414a2 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -291,6 +291,11 @@ public:  	static bool canAddNotifPanelToIM(const LLNotificationPtr& notification);  	/** +	 * Checks whether notification can be used multiple times or not. +	 */ +	static bool isNotificationReusable(const LLNotificationPtr& notification); + +	/**  	 * Checks if passed notification can create IM session and be written into it.  	 *  	 * This method uses canLogToIM() & canSpawnIMSession(). @@ -298,6 +303,18 @@ public:  	static bool canSpawnSessionAndLogToIM(const LLNotificationPtr& notification);  	/** +	 * Checks if passed notification can create toast. +	 * +	 * It returns false only for inventory accepted/declined notifications if respective IM window is open (EXT-5909) +	 */ +	static bool canSpawnToast(const LLNotificationPtr& notification); + +	/** +	 * Determines whether IM floater is opened. +	 */ +	static bool isIMFloaterOpened(const LLNotificationPtr& notification); + +	/**  	 * Writes notification message to IM session.  	 */  	static void logToIM(const EInstantMessage& session_type, @@ -343,6 +360,21 @@ public:  	 * Adds notification panel to the IM floater.  	 */  	static void addNotifPanelToIM(const LLNotificationPtr& notification); + +	/** +	 * Updates messages of IM floater. +	 */ +	static void updateIMFLoaterMesages(const LLUUID& session_id); + +	/** +	 * Updates messages of visible IM floater. +	 */ +	static void updateVisibleIMFLoaterMesages(const LLNotificationPtr& notification); + +	/** +	 * Decrements counter of IM messages. +	 */ +	static void decIMMesageCounter(const LLNotificationPtr& notification);  };  } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 88bb769109..d3ad61128d 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -127,7 +127,9 @@ const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"),  						FRIENDSHIP_DECLINED_BYME("FriendshipDeclinedByMe"),  						FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"),  						SERVER_OBJECT_MESSAGE("ServerObjectMessage"), -						TELEPORT_OFFERED("TeleportOffered"); +						TELEPORT_OFFERED("TeleportOffered"), +						TELEPORT_OFFER_SENT("TeleportOfferSent"); +  // static  bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) @@ -137,11 +139,15 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification)  			|| PAYMENT_RECIVED == notification->getName()  			|| OFFER_FRIENDSHIP == notification->getName()  			|| FRIENDSHIP_OFFERED == notification->getName() +			|| FRIENDSHIP_ACCEPTED == notification->getName()  			|| FRIENDSHIP_ACCEPTED_BYME == notification->getName()  			|| FRIENDSHIP_DECLINED_BYME == notification->getName()  			|| SERVER_OBJECT_MESSAGE == notification->getName()  			|| INVENTORY_ACCEPTED == notification->getName() -			|| INVENTORY_DECLINED == notification->getName(); +			|| INVENTORY_DECLINED == notification->getName() +			|| USER_GIVE_ITEM == notification->getName() +			|| TELEPORT_OFFERED == notification->getName() +			|| TELEPORT_OFFER_SENT == notification->getName();  }  // static @@ -158,19 +164,25 @@ bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification)  bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification)  {  	return OFFER_FRIENDSHIP == notification->getName() -			|| FRIENDSHIP_ACCEPTED == notification->getName()  			|| USER_GIVE_ITEM == notification->getName() -			|| INVENTORY_ACCEPTED == notification->getName() -			|| INVENTORY_DECLINED == notification->getName(); +			|| TELEPORT_OFFERED == notification->getName();  }  // static  bool LLHandlerUtil::canAddNotifPanelToIM(const LLNotificationPtr& notification)  {  	return OFFER_FRIENDSHIP == notification->getName() -					|| USER_GIVE_ITEM == notification->getName(); +					|| USER_GIVE_ITEM == notification->getName() +					|| TELEPORT_OFFERED == notification->getName();  } +// static +bool LLHandlerUtil::isNotificationReusable(const LLNotificationPtr& notification) +{ +	return OFFER_FRIENDSHIP == notification->getName() +		|| USER_GIVE_ITEM == notification->getName() +		|| TELEPORT_OFFERED == notification->getName(); +}  // static  bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification) @@ -179,18 +191,57 @@ bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notificat  }  // static +bool LLHandlerUtil::canSpawnToast(const LLNotificationPtr& notification) +{ +	bool cannot_spawn = isIMFloaterOpened(notification) && (INVENTORY_DECLINED == notification->getName() +			|| INVENTORY_ACCEPTED == notification->getName()); +	 +	return !cannot_spawn; +} + +// static +bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) +{ +	bool res = false; + +	LLUUID from_id = notification->getPayload()["from_id"]; +	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, +			from_id); + +	LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>( +					"impanel", session_id); +	if (im_floater != NULL) +	{ +		res = im_floater->getVisible() == TRUE; +	} + +	return res; +} + +// static  void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  		const std::string& session_name, const std::string& from_name,  		const std::string& message, const LLUUID& session_owner_id,  		const LLUUID& from_id)  { +	std::string from = from_name; +	if (from_name.empty()) +	{ +		from = SYSTEM_FROM; +	} +  	LLUUID session_id = LLIMMgr::computeSessionID(session_type,  			session_owner_id);  	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(  			session_id);  	if (session == NULL)  	{ -		LLIMModel::instance().logToFile(session_name, from_name, from_id, message); +		// replace interactive system message marker with correct from string value +		if (INTERACTIVE_SYSTEM_FROM == from_name) +		{ +			from = SYSTEM_FROM; +		} +		LLIMModel::instance().logToFile(session_name, from, from_id, message);  	}  	else  	{ @@ -201,8 +252,16 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  		// set searched session as active to avoid IM toast popup  		LLIMModel::instance().setActiveSessionID(session_id); -		LLIMModel::instance().addMessage(session_id, from_name, from_id, +		S32 unread = session->mNumUnread; +		S32 participant_unread = session->mParticipantUnreadMessageCount; +		LLIMModel::instance().addMessageSilently(session_id, from, from_id,  				message); +		// we shouldn't increment counters when logging, so restore them +		session->mNumUnread = unread; +		session->mParticipantUnreadMessageCount = participant_unread; + +		// update IM floater messages +		updateIMFLoaterMesages(session_id);  		// restore active session id  		if (active_session_id.isNull()) @@ -250,13 +309,13 @@ void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_fi  		if(to_file_only)  		{ -			logToIM(IM_NOTHING_SPECIAL, session_name, name, notification->getMessage(), +			logToIM(IM_NOTHING_SPECIAL, session_name, "", notification->getMessage(),  					LLUUID(), LLUUID());  		}  		else  		{ -			logToIM(IM_NOTHING_SPECIAL, session_name, name, notification->getMessage(), -					from_id, from_id); +			logToIM(IM_NOTHING_SPECIAL, session_name, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), +					from_id, LLUUID());  		}  	}  } @@ -324,7 +383,16 @@ std::string LLHandlerUtil::getSubstitutionName(const LLNotificationPtr& notifica  	if (res.empty())  	{  		LLUUID from_id = notification->getPayload()["FROM_ID"]; -		gCacheName->getFullName(from_id, res); + +		//*TODO all keys everywhere should be made of the same case, there is a mix of keys in lower and upper cases +		if (from_id.isNull())  +		{ +			from_id = notification->getPayload()["from_id"]; +		} +		if(!gCacheName->getFullName(from_id, res)) +		{ +			res = ""; +		}  	}  	return res;  } @@ -343,11 +411,60 @@ void LLHandlerUtil::addNotifPanelToIM(const LLNotificationPtr& notification)  	LLSD offer;  	offer["notification_id"] = notification->getID(); -	offer["from_id"] = notification->getPayload()["from_id"]; -	offer["from"] = name; -	offer["time"] = LLLogChat::timestamp(true); +	offer["from"] = SYSTEM_FROM; +	offer["time"] = LLLogChat::timestamp(false);  	offer["index"] = (LLSD::Integer)session->mMsgs.size();  	session->mMsgs.push_front(offer); -	LLIMFloater::show(session_id); + +	// update IM floater and counters +	LLSD arg; +	arg["session_id"] = session_id; +	arg["num_unread"] = ++(session->mNumUnread); +	arg["participant_unread"] = ++(session->mParticipantUnreadMessageCount); +	LLIMModel::getInstance()->mNewMsgSignal(arg); +} + +// static +void LLHandlerUtil::updateIMFLoaterMesages(const LLUUID& session_id) +{ +	LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); +	if (im_floater != NULL && im_floater->getVisible()) +	{ +		im_floater->updateMessages(); +	} +} + +// static +void LLHandlerUtil::updateVisibleIMFLoaterMesages(const LLNotificationPtr& notification) +{ +	const std::string name = LLHandlerUtil::getSubstitutionName(notification); +	LLUUID from_id = notification->getPayload()["from_id"]; +	LLUUID session_id = spawnIMSession(name, from_id); + +	updateIMFLoaterMesages(session_id); +} + +// static +void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification) +{ +	const std::string name = LLHandlerUtil::getSubstitutionName(notification); +	LLUUID from_id = notification->getPayload()["from_id"]; +	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); + +	LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession( +			session_id); + +	if (session == NULL) +	{ +		return; +	} + +	LLSD arg; +	arg["session_id"] = session_id; +	session->mNumUnread--; +	arg["num_unread"] = session->mNumUnread; +	session->mParticipantUnreadMessageCount--; +	arg["participant_unread"] = session->mParticipantUnreadMessageCount; +	LLIMModel::getInstance()->mNewMsgSignal(arg);  } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 8ebd5de258..e93aec9d01 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -103,6 +103,8 @@ bool LLOfferHandler::processNotification(const LLSD& notify)  		}  		else  		{ +			notification->setReusable(LLHandlerUtil::isNotificationReusable(notification)); +  			LLUUID session_id;  			if (LLHandlerUtil::canSpawnIMSession(notification))  			{ @@ -113,35 +115,58 @@ bool LLOfferHandler::processNotification(const LLSD& notify)  				session_id = LLHandlerUtil::spawnIMSession(name, from_id);  			} -			if (LLHandlerUtil::canAddNotifPanelToIM(notification)) +			bool show_toast = true; +			bool add_notid_to_im = LLHandlerUtil::canAddNotifPanelToIM(notification); +			if (add_notid_to_im)  			{  				LLHandlerUtil::addNotifPanelToIM(notification); -				LLHandlerUtil::logToIMP2P(notification, true); +				if (LLHandlerUtil::isIMFloaterOpened(notification)) +				{ +					show_toast = false; +				}  			} -			else if (notification->getPayload().has("SUPPRESS_TOAST") + +			if (notification->getPayload().has("SUPPRESS_TOAST")  						&& notification->getPayload()["SUPPRESS_TOAST"])  			{ -				LLHandlerUtil::logToIMP2P(notification);  				LLNotificationsUtil::cancel(notification);  			} -			else +			else if(show_toast)  			{  				LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); - +				// don't close notification on panel destroy since it will be used by IM floater +				notify_box->setCloseNotificationOnDestroy(!add_notid_to_im);  				LLToast::Params p;  				p.notif_id = notification->getID();  				p.notification = notification;  				p.panel = notify_box;  				p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); +				// we not save offer notifications to the syswell floater that should be added to the IM floater +				p.can_be_stored = !add_notid_to_im;  				LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);  				if(channel)  					channel->addToast(p); -				LLHandlerUtil::logToIMP2P(notification); +				// if we not add notification to IM - add it to notification well +				if (!add_notid_to_im) +				{ +					// send a signal to the counter manager +					mNewNotificationSignal(); +				} +			} -				// send a signal to the counter manager -				mNewNotificationSignal(); +			if (LLHandlerUtil::canLogToIM(notification)) +			{ +				// log only to file if notif panel can be embedded to IM and IM is opened +				if (add_notid_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) +				{ +					LLHandlerUtil::logToIMP2P(notification, true); +				} +				else +				{ +					LLHandlerUtil::logToIMP2P(notification); +				}  			}  		}  	} @@ -155,6 +180,11 @@ bool LLOfferHandler::processNotification(const LLSD& notify)  		}  		else  		{ +			if (LLHandlerUtil::canAddNotifPanelToIM(notification) +					&& !LLHandlerUtil::isIMFloaterOpened(notification)) +			{ +				LLHandlerUtil::decIMMesageCounter(notification); +			}  			mChannel->killToastByNotificationID(notification->getID());  		}  	} @@ -166,8 +196,11 @@ bool LLOfferHandler::processNotification(const LLSD& notify)  void LLOfferHandler::onDeleteToast(LLToast* toast)  { -	// send a signal to the counter manager -	mDelNotificationSignal(); +	if (!LLHandlerUtil::canAddNotifPanelToIM(toast->getNotification())) +	{ +		// send a signal to the counter manager +		mDelNotificationSignal(); +	}  	// send a signal to a listener to let him perform some action  	// in this case listener is a SysWellWindow and it will remove a corresponding item from its list @@ -181,7 +214,9 @@ void LLOfferHandler::onRejectToast(LLUUID& id)  	if (notification  			&& LLNotificationManager::getInstance()->getHandlerForNotification( -					notification->getType()) == this) +					notification->getType()) == this +					// don't delete notification since it may be used by IM floater +					&& !LLHandlerUtil::canAddNotifPanelToIM(notification))  	{  		LLNotifications::instance().cancel(notification);  	} diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 4e2c5085ed..1f1afe293a 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -150,6 +150,12 @@ bool LLTipHandler::processNotification(const LLSD& notify)  			LLHandlerUtil::spawnIMSession(name, from_id);  		} +		// don't spawn toast for inventory accepted/declined offers if respective IM window is open (EXT-5909) +		if (!LLHandlerUtil::canSpawnToast(notification)) +		{ +			return true; +		} +  		LLToastPanel* notify_box = NULL;  		if("FriendOffline" == notification->getName() || "FriendOnline" == notification->getName())  		{ diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 57b478ffef..a0ba2f739b 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -495,6 +495,7 @@ BOOL LLPanelAvatarProfile::postBuild()  			&LLPanelAvatarProfile::onMapButtonClick, this)), NULL);  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +	registrar.add("Profile.ShowOnMap",  boost::bind(&LLPanelAvatarProfile::onMapButtonClick, this));  	registrar.add("Profile.Pay",  boost::bind(&LLPanelAvatarProfile::pay, this));  	registrar.add("Profile.Share", boost::bind(&LLPanelAvatarProfile::share, this));  	registrar.add("Profile.BlockUnblock", boost::bind(&LLPanelAvatarProfile::toggleBlock, this)); @@ -504,6 +505,7 @@ BOOL LLPanelAvatarProfile::postBuild()  	registrar.add("Profile.CSR", boost::bind(&LLPanelAvatarProfile::csr, this));  	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; +	enable.add("Profile.EnableShowOnMap", boost::bind(&LLPanelAvatarProfile::enableShowOnMap, this));  	enable.add("Profile.EnableGod", boost::bind(&enable_god));  	enable.add("Profile.EnableBlock", boost::bind(&LLPanelAvatarProfile::enableBlock, this));  	enable.add("Profile.EnableUnblock", boost::bind(&LLPanelAvatarProfile::enableUnblock, this)); @@ -698,6 +700,15 @@ void LLPanelAvatarProfile::toggleBlock()  	LLAvatarActions::toggleBlock(getAvatarId());  } +bool LLPanelAvatarProfile::enableShowOnMap() +{ +	bool is_buddy_online = LLAvatarTracker::instance().isBuddyOnline(getAvatarId()); + +	bool enable_map_btn = (is_buddy_online && is_agent_mappable(getAvatarId())) +		|| gAgent.isGodlike(); +	return enable_map_btn; +} +  bool LLPanelAvatarProfile::enableBlock()  {  	return LLAvatarActions::canBlock(getAvatarId()) && !LLAvatarActions::isBlocked(getAvatarId()); diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index 2bd23b6e9c..bb8df2ff9c 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -202,6 +202,7 @@ protected:  	void unfreeze();  	void csr(); +	bool enableShowOnMap();  	bool enableBlock();  	bool enableUnblock();  	bool enableGod(); diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 362657a458..a186bc926c 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -119,8 +119,13 @@ void LLPanelBlockedList::refreshBlockedList()  	std::vector<LLMute>::iterator it;  	for (it = mutes.begin(); it != mutes.end(); ++it)  	{ -		std::string display_name = it->getDisplayName(); -		mBlockedList->addStringUUIDItem(display_name, it->mID, ADD_BOTTOM, TRUE); +		LLScrollListItem::Params item_p; +		item_p.enabled(TRUE); +		item_p.value(it->mID); // link UUID of blocked item with ScrollListItem +		item_p.columns.add().column("item_name").value(it->mName);//.type("text"); +		item_p.columns.add().column("item_type").value(it->getDisplayType());//.type("text").width(111); + +		mBlockedList->addRow(item_p, ADD_BOTTOM);  	}  } @@ -145,9 +150,7 @@ void LLPanelBlockedList::onRemoveBtnClick()  {  	std::string name = mBlockedList->getSelectedItemLabel();  	LLUUID id = mBlockedList->getStringUUIDSelectedItem(); -	LLMute mute(id); -	mute.setFromDisplayName(name); -	// now mute.mName has the suffix trimmed off +	LLMute mute(id, name);  	S32 last_selected = mBlockedList->getFirstSelectedIndex();  	if (LLMuteList::getInstance()->remove(mute)) diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 021e1f5159..70a7bf644b 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -1893,7 +1893,7 @@ void LLPanelClassifiedEdit::resetControls()  	LLPanelClassifiedInfo::resetControls();  	getChild<LLComboBox>("category")->setCurrentByIndex(0); -	getChild<LLIconsComboBox>("content_type")->setCurrentByIndex(0); +	getChild<LLComboBox>("content_type")->setCurrentByIndex(0);  	childSetValue("auto_renew", false);  	childSetValue("price_for_listing", MINIMUM_PRICE_FOR_LISTING);  	childSetEnabled("price_for_listing", TRUE); @@ -1928,7 +1928,7 @@ U32 LLPanelClassifiedEdit::getContentType()  void LLPanelClassifiedEdit::setContentType(U32 content_type)  { -	LLIconsComboBox* ct_cb = getChild<LLIconsComboBox>("content_type"); +	LLComboBox* ct_cb = getChild<LLComboBox>("content_type");  	ct_cb->setCurrentByIndex(content_type);  	ct_cb->resetDirty();  } @@ -1988,7 +1988,7 @@ U8 LLPanelClassifiedEdit::getFlags()  {  	bool auto_renew = childGetValue("auto_renew").asBoolean(); -	LLComboBox* content_cb = getChild<LLIconsComboBox>("content_type"); +	LLComboBox* content_cb = getChild<LLComboBox>("content_type");  	bool mature = content_cb->getCurrentIndex() == CB_ITEM_MATURE;  	return pack_classified_flags_request(auto_renew, false, mature, false); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 7505581904..c43cbf5819 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -609,7 +609,9 @@ void LLTaskInvFVBridge::performAction(LLFolderView* folder, LLInventoryModel* mo  		{  			if (price > 0 && price > gStatusBar->getBalance())  			{ -				LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("this_costs"), price); +				LLStringUtil::format_map_t args; +				args["AMOUNT"] = llformat("%d", price); +				LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("this_costs", args), price);  			}  			else  			{ @@ -1188,7 +1190,8 @@ public:  	LLTaskObjectBridge(  		LLPanelObjectInventory* panel,  		const LLUUID& uuid, -		const std::string& name); +		const std::string& name, +		U32 flags = 0);  	virtual LLUIImagePtr getIcon() const;  }; @@ -1196,8 +1199,9 @@ public:  LLTaskObjectBridge::LLTaskObjectBridge(  	LLPanelObjectInventory* panel,  	const LLUUID& uuid, -	const std::string& name) : -	LLTaskInvFVBridge(panel, uuid, name) +	const std::string& name, +	U32 flags) : +	LLTaskInvFVBridge(panel, uuid, name, flags)  {  } @@ -1442,9 +1446,15 @@ LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory*  		//									   object->getName());  		break;  	case LLAssetType::AT_OBJECT: +		{ +		item = dynamic_cast<LLInventoryItem*>(object); +		U32 flags = ( NULL == item ? 0 : item->getFlags() ); +  		new_bridge = new LLTaskObjectBridge(panel,  											object->getUUID(), -											object->getName()); +											object->getName(), +											flags); +		}  		break;  	case LLAssetType::AT_NOTECARD:  		new_bridge = new LLTaskNotecardBridge(panel, diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index cdd79b1559..1a1650c38b 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -567,9 +567,13 @@ void LLPanelPlaceProfile::onForSaleBannerClick()  		if(parcel->getLocalID() == mSelectedParcelID &&  				mLastSelectedRegionID ==selected_region->getRegionID())  		{ -			if(parcel->getSalePrice() - gStatusBar->getBalance() > 0) +			S32 price = parcel->getSalePrice(); + +			if(price - gStatusBar->getBalance() > 0)  			{ -				LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("buying_selected_land"), parcel->getSalePrice()); +				LLStringUtil::format_map_t args; +				args["AMOUNT"] = llformat("%d", price); +				LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("buying_selected_land", args), price);  			}  			else  			{ diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 26b57c003b..f9ba6f625d 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -278,6 +278,11 @@ BOOL LLPanelPlaces::postBuild()  	mFilterEditor = getChild<LLFilterEditor>("Filter");  	if (mFilterEditor)  	{ +		//when list item is being clicked the filter editor looses focus +		//committing on focus lost leads to detaching list items +		//BUT a detached list item cannot be made selected and must not be clicked onto +		mFilterEditor->setCommitOnFocusLost(false); +  		mFilterEditor->setCommitCallback(boost::bind(&LLPanelPlaces::onFilterEdit, this, _2, false));  	} diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index 120b584cd9..9b5e38d0aa 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -68,15 +68,16 @@ const F32 TOTAL_LOGIN_TIME = 10.f;	// seconds, wild guess at time from GL contex  S32 gLastStartAnimationFrame = 0;	// human-style indexing, first image = 1  const S32 ANIMATION_FRAMES = 1; //13; +static LLRegisterPanelClassWrapper<LLProgressView> r("progress_view"); + +  // XUI: Translate -LLProgressView::LLProgressView(const LLRect &rect)  +LLProgressView::LLProgressView()   :	LLPanel(),  	mPercentDone( 0.f ),  	mMouseDownInActiveArea( false ),  	mUpdateEvents("LLProgressView")  { -	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_progress.xml"); -	reshape(rect.getWidth(), rect.getHeight());  	mUpdateEvents.listen("self", boost::bind(&LLProgressView::handleUpdate, this, _1));  } @@ -92,6 +93,9 @@ BOOL LLProgressView::postBuild()  	getChild<LLTextBox>("message_text")->setClickedCallback(onClickMessage, this); +	// hidden initially, until we need it +	LLPanel::setVisible(FALSE); +  	sInstance = this;  	return TRUE;  } @@ -126,19 +130,23 @@ BOOL LLProgressView::handleKeyHere(KEY key, MASK mask)  void LLProgressView::setVisible(BOOL visible)  { +	// hiding progress view  	if (getVisible() && !visible)  	{ -  		mFadeTimer.start(); +		// hiding progress view, so show menu bars +		LLUI::getRootView()->getChildView("menu_bar_holder")->setVisible(TRUE);  	} +	// showing progress view  	else if (!getVisible() && visible)  	{ -		gViewerWindow->addPopup(this); - +		// showing progress view, so hide menu bars +		LLUI::getRootView()->getChildView("menu_bar_holder")->setVisible(FALSE); +		  		setFocus(TRUE);  		mFadeTimer.stop();  		mProgressTimer.start(); -		LLPanel::setVisible(visible); +		LLPanel::setVisible(TRUE);  	}  } @@ -148,7 +156,7 @@ void LLProgressView::draw()  	static LLTimer timer;  	// Paint bitmap if we've got one -	glPushMatrix(); +	glPushMatrix();	  	if (gStartTexture)  	{  		LLGLSUIDefault gls_ui; @@ -189,7 +197,7 @@ void LLProgressView::draw()  			// Fade is complete, release focus  			gFocusMgr.releaseFocusIfNeeded( this );  			LLPanel::setVisible(FALSE); -			gViewerWindow->removePopup(this); +			mFadeTimer.stop();  			gStartTexture = NULL;  		} diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h index 6853674d88..374b14be83 100644 --- a/indra/newview/llprogressview.h +++ b/indra/newview/llprogressview.h @@ -44,7 +44,7 @@ class LLProgressBar;  class LLProgressView : public LLPanel  {  public: -	LLProgressView(const LLRect& rect); +	LLProgressView();  	virtual ~LLProgressView();  	BOOL postBuild(); diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index a4426b370e..dffb5e5e12 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -710,9 +710,7 @@ void LLScreenChannel::hideToast(const LLUUID& notification_id)  	if(mToastList.end() != it)  	{  		ToastElem te = *it; -		te.toast->setVisible(FALSE); -		te.toast->stopTimer(); -		mToastList.erase(it); +		te.toast->hide();  	}  } diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp index 32a915608e..dc64296521 100644 --- a/indra/newview/llscrollingpanelparam.cpp +++ b/indra/newview/llscrollingpanelparam.cpp @@ -168,25 +168,25 @@ void LLScrollingPanelParam::draw()  	LLPanel::draw();  	// Draw the hints over the "less" and "more" buttons. -	glPushMatrix(); +	gGL.pushUIMatrix();  	{  		const LLRect& r = mHintMin->getRect();  		F32 left = (F32)(r.mLeft + BTN_BORDER);  		F32 bot  = (F32)(r.mBottom + BTN_BORDER); -		glTranslatef(left, bot, 0.f); +		gGL.translateUI(left, bot, 0.f);  		mHintMin->draw();  	} -	glPopMatrix(); +	gGL.popUIMatrix(); -	glPushMatrix(); +	gGL.pushUIMatrix();  	{  		const LLRect& r = mHintMax->getRect();  		F32 left = (F32)(r.mLeft + BTN_BORDER);  		F32 bot  = (F32)(r.mBottom + BTN_BORDER); -		glTranslatef(left, bot, 0.f); +		gGL.translateUI(left, bot, 0.f);  		mHintMax->draw();  	} -	glPopMatrix(); +	gGL.popUIMatrix();  	// Draw labels on top of the buttons diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 717a8bda1e..6cf9c6b95d 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -37,7 +37,6 @@  #include "llagent.h"  #include "llappviewer.h"  #include "llimview.h" -#include "llmutelist.h"  #include "llsdutil.h"  #include "lluicolortable.h"  #include "llviewerobjectlist.h" diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index b1b3ae473c..1c7b3a0fe0 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -571,7 +571,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if ((mFetcher->isQuitting() || mImagePriority < 1.0f || getFlags(LLWorkerClass::WCF_DELETE_REQUESTED)))  	{ -		if (mState < WRITE_TO_CACHE) +		if (mState < DECODE_IMAGE)  		{  			return true; // abort  		} diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index e6d13a7613..907740a88e 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -44,6 +44,7 @@  #include "llrect.h"  #include "lltrans.h"  #include "llnotificationsutil.h" +#include "llviewermessage.h"  const S32 BOTTOM_PAD = VPAD * 3;  const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding @@ -53,6 +54,8 @@ S32 BUTTON_WIDTH = 90;  const LLFontGL* LLToastNotifyPanel::sFont = NULL;  const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL; +LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; +  LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification, const LLRect& rect) :   LLToastPanel(notification),  mTextBox(NULL), @@ -60,7 +63,8 @@ mInfoPanel(NULL),  mControlPanel(NULL),  mNumOptions(0),  mNumButtons(0), -mAddedDefaultBtn(false) +mAddedDefaultBtn(false), +mCloseNotificationOnDestroy(true)  {  	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_notification.xml");  	if(rect != LLRect::null) @@ -193,11 +197,25 @@ mAddedDefaultBtn(false)  			// we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed  			adjustPanelForScriptNotice(button_panel_width, button_panel_height);  			updateButtonsLayout(buttons, h_pad); +			// save buttons for later use in disableButtons() +			mButtons.assign(buttons.begin(), buttons.end());  		}  	}  	// adjust panel's height to the text size  	mInfoPanel->setFollowsAll();  	snapToMessageHeight(mTextBox, MAX_LENGTH); + +	if(notification->isReusable()) +	{ +		mButtonClickConnection = sButtonClickSignal.connect( +			boost::bind(&LLToastNotifyPanel::onToastPanelButtonClicked, this, _1, _2)); + +		if(notification->isRespondedTo()) +		{ +			// User selected an option in toast, now disable required buttons in IM window +			disableRespondedOptions(notification); +		} +	}  }  void LLToastNotifyPanel::addDefaultButton()  { @@ -265,9 +283,13 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt  LLToastNotifyPanel::~LLToastNotifyPanel()   { +	mButtonClickConnection.disconnect(); +  	std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); -	if (LLNotificationsUtil::find(mNotification->getID()) != NULL) +	if (mCloseNotificationOnDestroy && LLNotificationsUtil::find(mNotification->getID()) != NULL)  	{ +		// let reusable notification be deleted +		mNotification->setReusable(false);  		LLNotifications::getInstance()->cancel(mNotification);  	}  } @@ -342,6 +364,104 @@ void LLToastNotifyPanel::adjustPanelForTipNotice()  	}  } +typedef std::set<std::string> button_name_set_t; +typedef std::map<std::string, button_name_set_t> disable_button_map_t; + +disable_button_map_t initUserGiveItemDisableButtonMap() +{ +	// see EXT-5905 for disable rules + +	disable_button_map_t disable_map; +	button_name_set_t buttons; + +	buttons.insert("Show"); +	disable_map.insert(std::make_pair("Show", buttons)); + +	buttons.insert("Discard"); +	disable_map.insert(std::make_pair("Discard", buttons)); + +	buttons.insert("Mute"); +	disable_map.insert(std::make_pair("Mute", buttons)); + +	return disable_map; +} + +disable_button_map_t initTeleportOfferedDisableButtonMap() +{ +	disable_button_map_t disable_map; +	button_name_set_t buttons; + +	buttons.insert("Teleport"); +	buttons.insert("Cancel"); + +	disable_map.insert(std::make_pair("Teleport", buttons)); +	disable_map.insert(std::make_pair("Cancel", buttons)); + +	return disable_map; +} + +disable_button_map_t initFriendshipOfferedDisableButtonMap() +{ +	disable_button_map_t disable_map; +	button_name_set_t buttons; + +	buttons.insert("Accept"); +	buttons.insert("Decline"); + +	disable_map.insert(std::make_pair("Accept", buttons)); +	disable_map.insert(std::make_pair("Decline", buttons)); + +	return disable_map; +} + +button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) +{ +	static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); +	static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); +	static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); + +	disable_button_map_t::const_iterator it; +	disable_button_map_t::const_iterator it_end; +	disable_button_map_t search_map; + +	if("UserGiveItem" == notification_name) +	{ +		search_map = user_give_item_disable_map; +	} +	else if("TeleportOffered" == notification_name) +	{ +		search_map = teleport_offered_disable_map; +	} +	else if("OfferFriendship" == notification_name) +	{ +		search_map = friendship_offered_disable_map; +	} + +	it = search_map.find(button_name); +	it_end = search_map.end(); + +	if(it_end != it) +	{ +		return it->second; +	} +	return button_name_set_t(); +} + +void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) +{ +	button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); + +	std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); +	for ( ; it != mButtons.end(); it++) +	{ +		LLButton* btn = it->second; +		if(buttons.find(btn->getName()) != buttons.end()) +		{ +			btn->setEnabled(FALSE); +		} +	} +} +  // static  void LLToastNotifyPanel::onClickButton(void* data)  { @@ -354,8 +474,81 @@ void LLToastNotifyPanel::onClickButton(void* data)  	{  		response[button_name] = true;  	} +	 +	bool is_reusable = self->mNotification->isReusable(); +	// When we call respond(), LLOfferInfo will delete itself in inventory_offer_callback(),  +	// lets copy it while it's still valid. +	LLOfferInfo* old_info = static_cast<LLOfferInfo*>(self->mNotification->getResponder()); +	LLOfferInfo* new_info = NULL; +	if(is_reusable && old_info) +	{ +		new_info = new LLOfferInfo(*old_info); +		self->mNotification->setResponder(new_info); +	} +  	self->mNotification->respond(response); -	// disable all buttons -	self->mControlPanel->setEnabled(FALSE); +	if(is_reusable) +	{ +		sButtonClickSignal(self->mNotification->getID(), button_name); + +		if(new_info) +		{ +			self->mNotification->setResponseFunctor( +				boost::bind(&LLOfferInfo::inventory_offer_callback, new_info, _1, _2)); +		} +	} +	else +	{ +		// disable all buttons +		self->mControlPanel->setEnabled(FALSE); +	}  } + +void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) +{ +	if(mNotification->getID() == notification_id) +	{ +		disableButtons(mNotification->getName(), btn_name); +	} +} + +void LLToastNotifyPanel::disableRespondedOptions(LLNotificationPtr& notification) +{ +	LLSD response = notification->getResponse(); +	for (LLSD::map_const_iterator response_it = response.beginMap();  +		response_it != response.endMap(); ++response_it) +	{ +		if (response_it->second.isBoolean() && response_it->second.asBoolean()) +		{ +			// that after multiple responses there can be many pressed buttons +			// need to process them all +			disableButtons(notification->getName(), response_it->first); +		} +	} +} + + +////////////////////////////////////////////////////////////////////////// + +LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLRect& rect /* = LLRect::null */) + : LLToastNotifyPanel(pNotification, rect) +{ +	mTextBox->setFollowsAll(); +} + +void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) +{ +	S32 text_height = mTextBox->getTextBoundingRect().getHeight(); +	S32 widget_height = mTextBox->getRect().getHeight(); +	S32 delta = text_height - widget_height; +	LLRect rc = getRect(); + +	rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height + delta); +	height = rc.getHeight(); +	width = rc.getWidth(); + +	LLToastPanel::reshape(width, height, called_from_parent); +} + +// EOF diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index 152975e7de..a8d2d03236 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -65,6 +65,7 @@ public:  	virtual ~LLToastNotifyPanel();  	LLPanel * getControlPanel() { return mControlPanel; } +	void setCloseNotificationOnDestroy(bool close) { mCloseNotificationOnDestroy = close; }  protected:  	LLButton* createButton(const LLSD& form_element, BOOL is_option); @@ -76,7 +77,7 @@ protected:  	};  	std::vector<InstanceAndS32*> mBtnCallbackData; -private: +	bool mCloseNotificationOnDestroy;  	typedef std::pair<int,LLButton*> index_button_pair_t;   	void adjustPanelForScriptNotice(S32 max_width, S32 max_height); @@ -90,6 +91,13 @@ private:  	 */  	void updateButtonsLayout(const std::vector<index_button_pair_t>& buttons, S32 h_pad); +	/** +	 * Disable specific button(s) based on notification name and clicked button +	 */ +	void disableButtons(const std::string& notification_name, const std::string& selected_button); + +	std::vector<index_button_pair_t> mButtons; +  	// panel elements  	LLTextBase*		mTextBox;  	LLPanel*		mInfoPanel;		// a panel, that contains an information @@ -98,6 +106,21 @@ private:  	// internal handler for button being clicked  	static void onClickButton(void* data); +	typedef boost::signals2::signal <void (const LLUUID& notification_id, const std::string btn_name)> +		button_click_signal_t; +	static button_click_signal_t sButtonClickSignal; +	boost::signals2::connection mButtonClickConnection; + +	/** +	 * handle sButtonClickSignal (to disable buttons) across all panels with given notification_id +	 */ +	void onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name); + +	/** +	 * Process response data. Will disable selected options +	 */ +	void disableRespondedOptions(LLNotificationPtr& notification); +  	bool mIsTip;  	bool mAddedDefaultBtn;  	bool mIsScriptDialog; @@ -111,4 +134,13 @@ private:  	static const LLFontGL* sFontSmall;  }; +class LLIMToastNotifyPanel : public LLToastNotifyPanel +{ +public: + +	LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null); + +	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); +}; +  #endif /* LLTOASTNOTIFYPANEL_H_ */ diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 125c62474e..47e60a966e 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1503,15 +1503,38 @@ void LLToolDragAndDrop::commitGiveInventoryItem(const LLUUID& to_agent,  	LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY); +	logInventoryOffer(to_agent, im_session_id);	 + +	// add buddy to recent people list +	LLRecentPeople::instance().add(to_agent); +} + +//static +void LLToolDragAndDrop::logInventoryOffer(const LLUUID& to_agent, const LLUUID &im_session_id) +{ +	// compute id of possible IM session with agent that has "to_agent" id +	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, to_agent);  	// If this item was given by drag-and-drop into an IM panel, log this action in the IM panel chat. -	if (im_session_id != LLUUID::null) +	if (im_session_id.notNull())  	{  		LLSD args;  		gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args);  	} - -	// add buddy to recent people list -	LLRecentPeople::instance().add(to_agent); +	// If this item was given by drag-and-drop on avatar while IM panel was open, log this action in the IM panel chat. +	else if (LLIMModel::getInstance()->findIMSession(session_id)) +	{ +		LLSD args; +		gIMMgr->addSystemMessage(session_id, "inventory_item_offered", args); +	} +	// If this item was given by drag-and-drop on avatar while IM panel wasn't open, log this action to IM history. +	else +	{ +		std::string full_name; +		if (gCacheName->getFullName(to_agent, full_name)) +		{ +			LLIMModel::instance().logToFile(full_name, LLTrans::getString("SECOND_LIFE"), im_session_id, LLTrans::getString("inventory_item_offered-im")); +		} +	}  }  void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent, @@ -1723,12 +1746,7 @@ void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent,  		LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY); -		// If this item was given by drag-and-drop into an IM panel, log this action in the IM panel chat. -		if (im_session_id != LLUUID::null) -		{ -			LLSD args; -			gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args); -		} +		logInventoryOffer(to_agent, im_session_id);  	}  } diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 79b2bc32a3..0da13dac8b 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -227,6 +227,10 @@ protected:  											LLInventoryCategory* cat,  											const LLUUID &im_session_id = LLUUID::null); +	// log "Inventory item offered" to IM +	static void logInventoryOffer(const LLUUID& to_agent,  +									const LLUUID &im_session_id = LLUUID::null); +  public:  	// helper functions  	static BOOL isInventoryDropAcceptable(LLViewerObject* obj, LLInventoryItem* item) { return (ACCEPT_YES_COPY_SINGLE <= willObjectAcceptInventory(obj, item)); } diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 99bfad9b45..2fcd3f1114 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -982,6 +982,119 @@ bool LLViewerMedia::isParcelAudioPlaying()  	return (LLViewerMedia::hasParcelAudio() && gAudiop && LLAudioEngine::AUDIO_PLAYING == gAudiop->isInternetStreamPlaying());  } +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::clearAllCookies() +{ +	// Clear all cookies for all plugins +	impl_list::iterator iter = sViewerMediaImplList.begin(); +	impl_list::iterator end = sViewerMediaImplList.end(); +	for (; iter != end; iter++) +	{ +		LLViewerMediaImpl* pimpl = *iter; +		if(pimpl->mMediaSource) +		{ +			pimpl->mMediaSource->clear_cookies(); +		} +	} +	 +	// FIXME: this may not be sufficient, since the on-disk cookie file won't get written until some browser instance exits cleanly. +	// It also won't clear cookies for other accounts, or for any account if we're not logged in, and won't do anything at all if there are no webkit plugins loaded. +	// Until such time as we can centralize cookie storage, the following hack should cover these cases: +	 +	// HACK: Look for cookie files in all possible places and delete them. +	// NOTE: this assumes knowledge of what happens inside the webkit plugin (it's what adds 'browser_profile' to the path and names the cookie file) +	 +	// Places that cookie files can be: +	// <getOSUserAppDir>/browser_profile/cookies +	// <getOSUserAppDir>/first_last/browser_profile/cookies  (note that there may be any number of these!) +	 +	std::string base_dir = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter(); +	std::string target; +	std::string filename; +	 +	lldebugs << "base dir = " << base_dir << llendl; + +	// The non-logged-in version is easy +	target = base_dir; +	target += "browser_profile"; +	target += gDirUtilp->getDirDelimiter(); +	target += "cookies"; +	lldebugs << "target = " << target << llendl; +	if(LLFile::isfile(target)) +	{ +		LLFile::remove(target); +	} +	 +	// the hard part: iterate over all user directories and delete the cookie file from each one +	while(gDirUtilp->getNextFileInDir(base_dir, "*_*", filename, false)) +	{ +		target = base_dir; +		target += filename; +		target += gDirUtilp->getDirDelimiter(); +		target += "browser_profile"; +		target += gDirUtilp->getDirDelimiter(); +		target += "cookies"; +		lldebugs << "target = " << target << llendl; +		if(LLFile::isfile(target)) +		{	 +			LLFile::remove(target); +		} +	} +	 +	 +} +	 +///////////////////////////////////////////////////////////////////////////////////////// +// static  +void LLViewerMedia::clearAllCaches() +{ +	// Clear all plugins' caches +	impl_list::iterator iter = sViewerMediaImplList.begin(); +	impl_list::iterator end = sViewerMediaImplList.end(); +	for (; iter != end; iter++) +	{ +		LLViewerMediaImpl* pimpl = *iter; +		pimpl->clearCache(); +	} +} +	 +///////////////////////////////////////////////////////////////////////////////////////// +// static  +void LLViewerMedia::setCookiesEnabled(bool enabled) +{ +	// Set the "cookies enabled" flag for all loaded plugins +	impl_list::iterator iter = sViewerMediaImplList.begin(); +	impl_list::iterator end = sViewerMediaImplList.end(); +	for (; iter != end; iter++) +	{ +		LLViewerMediaImpl* pimpl = *iter; +		if(pimpl->mMediaSource) +		{ +			pimpl->mMediaSource->enable_cookies(enabled); +		} +	} +} +	 +///////////////////////////////////////////////////////////////////////////////////////// +// static  +void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int port) +{ +	// Set the proxy config for all loaded plugins +	impl_list::iterator iter = sViewerMediaImplList.begin(); +	impl_list::iterator end = sViewerMediaImplList.end(); +	for (; iter != end; iter++) +	{ +		LLViewerMediaImpl* pimpl = *iter; +		if(pimpl->mMediaSource) +		{ +			pimpl->mMediaSource->proxy_setup(enable, host, port); +		} +	} +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static   bool LLViewerMedia::hasInWorldMedia()  {  	if (sInWorldMediaDisabled) return false; @@ -1334,6 +1447,8 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)  		media_source->focus(mHasFocus);  		media_source->setBackgroundColor(mBackgroundColor); +		media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort")); +		  		if(mClearCache)  		{  			mClearCache = false; diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index bc51e713a1..f9870fb3b9 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -133,6 +133,18 @@ public:  	static bool isParcelMediaPlaying();  	static bool isParcelAudioPlaying(); +	// Clear all cookies for all plugins +	static void clearAllCookies(); +	 +	// Clear all plugins' caches +	static void clearAllCaches(); +	 +	// Set the "cookies enabled" flag for all loaded plugins +	static void setCookiesEnabled(bool enabled); +	 +	// Set the proxy config for all loaded plugins +	static void setProxyConfig(bool enable, const std::string &host, int port); +	  private:  	static void onTeleportFinished();  }; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 5c40d02f8d..5598a589cc 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -436,7 +436,8 @@ void init_menus()  	gMenuBarView->setRect(LLRect(0, top, 0, top - MENU_BAR_HEIGHT));  	gMenuBarView->setBackgroundColor( color ); -	gMenuHolder->addChild(gMenuBarView); +	LLView* menu_bar_holder = gViewerWindow->getRootView()->getChildView("menu_bar_holder"); +	menu_bar_holder->addChild(gMenuBarView);      gViewerWindow->setMenuBackgroundColor(false,           LLViewerLogin::getInstance()->isInProductionGrid()); @@ -471,9 +472,10 @@ void init_menus()  	gLoginMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_login.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());  	gLoginMenuBarView->arrangeAndClear();  	LLRect menuBarRect = gLoginMenuBarView->getRect(); -	gLoginMenuBarView->setRect(LLRect(menuBarRect.mLeft, menuBarRect.mTop, gViewerWindow->getRootView()->getRect().getWidth() - menuBarRect.mLeft,  menuBarRect.mBottom)); +	menuBarRect.setLeftTopAndSize(0, menu_bar_holder->getRect().getHeight(), menuBarRect.getWidth(), menuBarRect.getHeight()); +	gLoginMenuBarView->setRect(menuBarRect);  	gLoginMenuBarView->setBackgroundColor( color ); -	gMenuHolder->addChild(gLoginMenuBarView); +	menu_bar_holder->addChild(gLoginMenuBarView);  	// tooltips are on top of EVERYTHING, including menus  	gViewerWindow->getRootView()->sendChildToFront(gToolTipView); @@ -3274,7 +3276,9 @@ void handle_buy_object(LLSaleInfo sale_info)  	if (price > 0 && price > gStatusBar->getBalance())  	{ -		LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("this_object_costs"), price); +		LLStringUtil::format_map_t args; +		args["AMOUNT"] = llformat("%d", price); +		LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("this_object_costs", args), price);  		return;  	} @@ -4404,8 +4408,10 @@ void handle_buy_or_take()  		}  		else  		{ +			LLStringUtil::format_map_t args; +			args["AMOUNT"] = llformat("%d", total_price);  			LLFloaterBuyCurrency::buyCurrency( -				"Buying this costs", total_price); +					LLTrans::getString("BuyingCosts", args), total_price);  		}  	}  	else diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 00762894cd..dfde9a9d1d 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -811,10 +811,10 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt  				if(!(can_afford_transaction(expected_upload_cost)))  				{ -					LLFloaterBuyCurrency::buyCurrency( -									  llformat(LLTrans::getString("UploadingCosts").c_str(), -										   data->mAssetInfo.getName().c_str()), -									  expected_upload_cost); +					LLStringUtil::format_map_t args; +					args["NAME"] = data->mAssetInfo.getName(); +					args["AMOUNT"] = llformat("%d", expected_upload_cost); +					LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("UploadingCosts", args), expected_upload_cost);  					is_balance_sufficient = FALSE;  				}  				else if(region) @@ -1001,7 +1001,9 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty  			if (balance < expected_upload_cost)  			{  				// insufficient funds, bail on this upload -				LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("uploading_costs"), expected_upload_cost); +				LLStringUtil::format_map_t args; +				args["AMOUNT"] = llformat("%d", expected_upload_cost); +				LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("uploading_costs", args), expected_upload_cost);  				return;  			}  		} diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index bd0012057c..3d0dfbed40 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -105,6 +105,7 @@  #include "llpanelplaceprofile.h"  #include <boost/algorithm/string/split.hpp> // +#include <boost/regex.hpp>  #if LL_WINDOWS // For Windows specific error handler  #include "llwindebug.h"	// For the invalid message handler @@ -272,7 +273,9 @@ void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_  	}  	else  	{ -		LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("giving"), amount); +		LLStringUtil::format_map_t args; +		args["AMOUNT"] = llformat("%d", amount); +		LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("giving", args), amount);  	}  } @@ -1081,6 +1084,21 @@ LLOfferInfo::LLOfferInfo(const LLSD& sd)  	mHost = LLHost(sd["sender"].asString());  } +LLOfferInfo::LLOfferInfo(const LLOfferInfo& info) +{ +	mIM = info.mIM; +	mFromID = info.mFromID; +	mFromGroup = info.mFromGroup; +	mFromObject = info.mFromObject; +	mTransactionID = info.mTransactionID; +	mFolderID = info.mFolderID; +	mObjectID = info.mObjectID; +	mType = info.mType; +	mFromName = info.mFromName; +	mDesc = info.mDesc; +	mHost = info.mHost; +} +  LLSD LLOfferInfo::asLLSD()  {  	LLSD sd; @@ -1572,7 +1590,11 @@ void inventory_offer_handler(LLOfferInfo* info)  	}  	else // Agent -> Agent Inventory Offer  	{ +		p.responder = info;  		// Note: sets inventory_offer_callback as the callback +		// *TODO fix memory leak +		// inventory_offer_callback() is not invoked if user received notification and  +		// closes viewer(without responding the notification)  		p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2));  		p.name = "UserGiveItem"; @@ -4498,8 +4520,64 @@ void process_money_balance_reply( LLMessageSystem* msg, void** )  			payload["from_id"] = from_id;  			LLNotificationsUtil::add("PaymentRecived", args, payload);  		} +		//AD *HACK: Parsing incoming string to localize messages that come from server! EXT-5986 +		// It's only a temporarily and ineffective measure. It doesn't affect performance much +		// because we get here only for specific type of messages, but anyway it is not right to do it! +		// *TODO: Server-side changes should be made and this code removed.  		else  		{ +			if(desc.find("You paid")==0) +			{ +				// Regular expression for message parsing- change it in case of server-side changes. +				// Each set of parenthesis will later be used to find arguments of message we generate +				// in the end of this if- (.*) gives us name of money receiver, (\\d+)-amount of money we pay +				// and ([^$]*)- reason of payment +				boost::regex expr("You paid (?:.{0}|(.*) )L\\$(\\d+)\\s?([^$]*)\\."); +				boost::match_results <std::string::const_iterator> matches; +				if(boost::regex_match(desc, matches, expr)) +				{ +					// Name of full localizable notification string +					// there are three types of this string- with name of receiver and reason of payment, +					// without name and without reason (but not simultaneously) +					// example of string without name - You paid L$100 to create a group. +					// example of string without reason - You paid Smdby Linden L$100. +					// example of string with reason and name - You paid Smbdy Linden L$100 for a land access pass. +					std::string line = "you_paid_ldollars_no_name"; + +					// arguments of string which will be in notification +					LLStringUtil::format_map_t str_args; + +					// extracting amount of money paid (without L$ symbols). It is always present. +					str_args["[AMOUNT]"] = std::string(matches[2]); + +					// extracting name of person/group you are paying (it may be absent) +					std::string name = std::string(matches[1]); +					if(!name.empty()) +					{ +						str_args["[NAME]"] = name; +						line = "you_paid_ldollars"; +					} + +					// extracting reason of payment (it may be absent) +					std::string reason = std::string(matches[3]); +					if (reason.empty()) +					{ +						line = "you_paid_ldollars_no_reason"; +					} +					else +					{ +						std::string localized_reason; +						// if we haven't found localized string for reason of payment leave it as it was +						str_args["[REASON]"] =  LLTrans::findString(localized_reason, reason) ? localized_reason : reason; +					} + +					// forming final message string by retrieving localized version from xml +					// and applying previously found arguments +					line = LLTrans::getString(line, str_args); +					args["MESSAGE"] = line; +				} +			} +  			LLNotificationsUtil::add("SystemMessage", args);  		} @@ -5486,6 +5564,8 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)  				args["TO_NAME"] = target_name;  				LLSD payload; +				 +				//*TODO please rewrite all keys to the same case, lower or upper  				payload["from_id"] = target_id;  				payload["SESSION_NAME"] = target_name;  				payload["SUPPRESS_TOAST"] = true; diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 7dd629dcfd..88f9697037 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -215,6 +215,8 @@ struct LLOfferInfo  		mIM(IM_NOTHING_SPECIAL), mType(LLAssetType::AT_NONE) {};  	LLOfferInfo(const LLSD& sd); +	LLOfferInfo(const LLOfferInfo& info); +  	void forceResponse(InventoryOfferResponse response);  	EInstantMessage mIM; diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index ea8af223c3..c9b3886fef 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -524,7 +524,10 @@ LLUIImagePtr LLEmbeddedItems::getItemImage(llwchar ext_char) const  				break;  			case LLAssetType::AT_SOUND:			img_name = "Inv_Sound";		break;  			case LLAssetType::AT_CLOTHING:		img_name = "Inv_Clothing";	break; -			case LLAssetType::AT_OBJECT:		img_name = "Inv_Object"; 	break; +			case LLAssetType::AT_OBJECT: +				img_name = LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS & item->getFlags() ? +					"Inv_Object_Multi" : "Inv_Object"; +				break;  			case LLAssetType::AT_CALLINGCARD:	img_name = "Inv_CallingCard"; break;  			case LLAssetType::AT_LANDMARK:		img_name = "Inv_Landmark"; 	break;  			case LLAssetType::AT_NOTECARD:		img_name = "Inv_Notecard";	break; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index dbbf0219c9..9fbffdac35 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1546,8 +1546,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority()  		}  		else  		{ -			// Leave the priority as-is -			return mDecodePriority; +			priority = -1.f; //stop fetching  		}  	}  	else if (cur_discard < 0) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index adac4b9b40..e7d64c48a0 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1351,7 +1351,8 @@ LLViewerWindow::LLViewerWindow(  	mStatesDirty(false),  	mIsFullscreenChecked(false),  	mCurrResolutionIndex(0), -    mViewerWindowListener(new LLViewerWindowListener(this)) +    mViewerWindowListener(new LLViewerWindowListener(this)), +	mProgressView(NULL)  {  	LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));  	LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); @@ -1588,8 +1589,7 @@ void LLViewerWindow::initBase()  	gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view");  	// Add the progress bar view (startup view), which overrides everything -	mProgressView = new LLProgressView(full_window); -	getRootView()->addChild(mProgressView); +	mProgressView = getRootView()->getChild<LLProgressView>("progress_view");  	setShowProgress(FALSE);  	setProgressCancelButtonVisible(FALSE); diff --git a/indra/newview/skins/default/textures/icons/Inv_Object_Multi.png b/indra/newview/skins/default/textures/icons/Inv_Object_Multi.pngBinary files differ new file mode 100644 index 0000000000..11f4871ad8 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Inv_Object_Multi.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index b1594816b2..a3e5361e76 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -247,6 +247,7 @@ with the same filename but different name    <texture name="Inv_Landmark" file_name="icons/Inv_Landmark.png" preload="false" />    <texture name="Inv_Notecard" file_name="icons/Inv_Notecard.png" preload="false" />    <texture name="Inv_Object" file_name="icons/Inv_Object.png" preload="false" /> +  <texture name="Inv_Object_Multi" file_name="icons/Inv_Object_Multi.png" preload="false" />    <texture name="Inv_Pants" file_name="icons/Inv_Pants.png" preload="false" />    <texture name="Inv_Script" file_name="icons/Inv_Script.png" preload="false" />    <texture name="Inv_Shirt" file_name="icons/Inv_Shirt.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/de/panel_bottomtray.xml b/indra/newview/skins/default/xui/de/panel_bottomtray.xml index d3f89b0ad3..d52b8dcf4d 100644 --- a/indra/newview/skins/default/xui/de/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/de/panel_bottomtray.xml @@ -9,7 +9,7 @@  	<layout_stack name="toolbar_stack">  		<layout_panel name="speak_panel">  			<talk_button name="talk"> -				<speak_button label="Sprechen" label_selected="Sprechen" name="speak_btn"/> +				<speak_button label="Sprechen" label_selected="Sprechen" name="speak_btn" halign="right" />  			</talk_button>  		</layout_panel>  		<layout_panel name="gesture_panel"> diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml index 961bd6b5e4..e02d32596a 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml @@ -182,7 +182,7 @@       width="180"       layout="topleft"       name="buy_action"> -        [NAME] L$ [PRICE] +        [ACTION]      </text>      <text       type="string" diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml index 85853f39bb..1ace760816 100644 --- a/indra/newview/skins/default/xui/en/main_view.xml +++ b/indra/newview/skins/default/xui/en/main_view.xml @@ -143,12 +143,19 @@    <panel mouse_opaque="false"           follows="left|right|top"           name="status_bar_container" -                tab_stop="false" +         tab_stop="false"           height="19"           left="0"            top="0"            width="1024"           visible="false"/> +  <view mouse_opaque="false" +        follows="all" +        name="menu_bar_holder" +        left="0" +        top="0" +        width="1024" +        height="768"/>    <notify_box_view top="0"                     follows="all"                     height="768" @@ -159,6 +166,15 @@    <panel top="0"           follows="all"           height="768" +         mouse_opaque="true" +         name="progress_view" +         filename="panel_progress.xml"  +         class="progress_view" +         width="1024" +         visible="false"/> +  <panel top="0" +         follows="all" +         height="768"           mouse_opaque="false"           name="popup_holder"           class="popup_holder" diff --git a/indra/newview/skins/default/xui/en/menu_profile_overflow.xml b/indra/newview/skins/default/xui/en/menu_profile_overflow.xml index 5162a4902f..b0b7b554b0 100644 --- a/indra/newview/skins/default/xui/en/menu_profile_overflow.xml +++ b/indra/newview/skins/default/xui/en/menu_profile_overflow.xml @@ -6,6 +6,15 @@   name="profile_overflow_menu"   width="120">      <menu_item_call +     label="Map" +     layout="topleft" +     name="show_on_map"> +        <menu_item_call.on_click +         function="Profile.ShowOnMap" /> +        <menu_item_call.on_enable +         function="Profile.EnableShowOnMap" /> +    </menu_item_call> +    <menu_item_call       label="Pay"       layout="topleft"       name="pay"> diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index 072ea882e6..d3f6695375 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -39,7 +39,13 @@       name="blocked"       tool_tip="List of currently blocked Residents"       top="30" -     width="270" /> +     width="270"> +        <scroll_list.columns +         name="item_name" /> +        <scroll_list.columns +         name="item_type" +         width="96" /> +    </scroll_list>      <button       follows="left|bottom"       height="23" diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index e70a0512d6..58c5c11e51 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -74,12 +74,15 @@             name="talk"             top="5"            width="105"> +            <!-- do not remove halign attribute with default value. otherwise it can't be overridden in other locales. +             & pad_right is default value for long label which can be right aligned. See EXT-6318 -->    <speak_button -    halign="left" +    halign="center"      name="speak_btn"      label="Speak"      label_selected="Speak" -    pad_left="12" +    pad_right="22" +    use_ellipses="true"      />                <show_button>                    <show_button.init_callback diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 627e616af5..d1e0746d9d 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -216,7 +216,7 @@ height="16"  name="login_help"  top_pad="2"  right="-10" -    width="180"> +    width="190">         Need help logging in?   </text>  <!--  <text      follows="right|bottom" diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index 6b5f0c3896..6bf00373ea 100644 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <panel  	follows="left|right|top|bottom" -	name="MediaControlsPanel" +	name="MediaControls"  	background_visible="false"  	height="200"  	layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index 412485e03f..30191aecb6 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -314,9 +314,12 @@           left="2"           mouse_opaque="false"           name="add_friend" +         pad_left="1"  +         pad_right="1"           tool_tip="Offer friendship to the Resident"           top="5" -         width="80" /> +         use_ellipses="true" +         width="117" />          <button           follows="bottom|left"           height="23" @@ -325,8 +328,8 @@           name="im"           tool_tip="Open instant message session"           top="5" -         left_pad="3" -         width="39" /> +         left_pad="1" +         width="21" />          <button           follows="bottom|left"           height="23" @@ -334,20 +337,12 @@           layout="topleft"           name="call"           tool_tip="Call this Resident" -         left_pad="3" +         left_pad="1" +         pad_left="1"  +         pad_right="1"           top="5" -         width="43" /> -        <button -         enabled="false" -         follows="bottom|left" -         height="23" -         label="Map" -         layout="topleft" -         name="show_on_map_btn" -         tool_tip="Show the Resident on the map" -         top="5" -         left_pad="3" -         width="41" /> +         use_ellipses="true" +         width="51" />          <button           follows="bottom|left"           height="23" @@ -355,9 +350,12 @@           layout="topleft"           name="teleport"           tool_tip="Offer teleport" -         left_pad="3" +         left_pad="1" +         pad_left="1"  +         pad_right="1"           top="5" -         width="69" /> +         use_ellipses="true" +         width="92" />          <button           follows="bottom|right"           height="23" @@ -367,7 +365,6 @@           tool_tip="Pay money to or share inventory with the Resident"           right="-1"           top="5" -	 	 left_pad="3"           width="23" />          </layout_panel>        <layout_panel diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 3a766bb798..47386bd332 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2202,7 +2202,8 @@ Clears (deletes) the media and all params from the given face.  	<!-- Viewer menu -->  	<string name="AcquiredItems">Acquired Items</string>  	<string name="Cancel">Cancel</string> -	<string name="UploadingCosts">Uploading %s costs</string> +	<string name="UploadingCosts">Uploading [NAME] costs L$ [AMOUNT]</string> +	<string name="BuyingCosts">Buying this costs L$ [AMOUNT]</string>  	<string name="UnknownFileExtension">  		Unknown file extension .%s  Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh @@ -3050,14 +3051,48 @@ If you continue to receive this message, contact the [SUPPORT_SITE].    <!-- Financial operations strings -->    <string name="paid_you_ldollars">[NAME] paid you L$[AMOUNT]</string> -  <string name="giving">Giving</string> -  <string name="uploading_costs">Uploading costs</string> -  <string name="this_costs">This costs</string> -  <string name="buying_selected_land">Buying selected land</string> -  <string name="this_object_costs">This object costs"</string> +  <string name="you_paid_ldollars">You paid [NAME] L$[AMOUNT] [REASON].</string> +  <string name="you_paid_ldollars_no_reason">You paid [NAME] L$[AMOUNT].</string> +  <string name="you_paid_ldollars_no_name">You paid L$[AMOUNT] [REASON].</string> +  <string name="for a parcel of land">for a parcel of land</string> +  <string name="for a land access pass">for a land access pass</string> +  <string name="for deeding land">for deeding land</string> +  <string name="to create a group">to create a group</string> +  <string name="to join a group">to join a group</string> +  <string name="to upload">to upload</string> +   +  <string name="giving">Giving L$ [AMOUNT]</string> +  <string name="uploading_costs">Uploading costs L$ [AMOUNT]</string> +  <string name="this_costs">This costs L$ [AMOUNT]</string> +  <string name="buying_selected_land">Buying selected land L$ [AMOUNT]</string> +  <string name="this_object_costs">This object costs L$ [AMOUNT]</string>    <string name="group_role_everyone">Everyone</string>    <string name="group_role_officers">Officers</string>    <string name="group_role_owners">Owners</string> +  <string name="uploading_abuse_report">Uploading... +   +Abuse Report</string> + +  <!-- names for new inventory items--> +  <string name="New Shape">New Shape</string> +  <string name="New Skin">New Skin</string> +  <string name="New Hair">New Hair</string> +  <string name="New Eyes">New Eyes</string> +  <string name="New Shirt">New Shirt</string> +  <string name="New Pants">New Pants</string> +  <string name="New Shoes">New Shoes</string> +  <string name="New Socks">New Socks</string> +  <string name="New Jacket">New Jacket</string> +  <string name="New Gloves">New Gloves</string> +  <string name="New Undershirt">New Undershirt</string> +  <string name="New Underpants">New Underpants</string> +  <string name="New Skirt">New Skirt</string> +  <string name="New Alpha">New Alpha</string> +  <string name="New Tattoo">New Tattoo</string> +  <string name="Invalid Wearable">Invalid Wearable</string> +  <string name="New Script">New Script</string> +  <string name="New Folder">New Folder</string> +  <string name="Contents">Contents</string>  </strings> diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml index ef885e8045..aa3ea736b8 100644 --- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml +++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml @@ -2,6 +2,7 @@  <chat_history    message_header="panel_chat_header.xml"    message_separator="panel_chat_separator.xml" +  message_plaintext_separator="panel_chat_plaintext_separator.xml"    left_text_pad="10"    right_text_pad="15"    left_widget_pad="0" | 
