diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index e9f6288f44c94aa87469a1548885f3bbdb196a69..9ce8ce8d55db843777197d0b1c11540132d805a8 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -1022,6 +1022,20 @@ void LLButton::setImageOverlay(const std::string& image_name, LLFontGL::HAlign a
 	}
 }
 
+void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment, const LLColor4& color)
+{
+	if (image_id.isNull())
+	{
+		mImageOverlay = NULL;
+	}
+	else
+	{
+		mImageOverlay = LLUI::getUIImageByID(image_id);
+		mImageOverlayAlignment = alignment;
+		mImageOverlayColor = color;
+	}
+}
+
 void LLButton::onMouseCaptureLost()
 {
 	resetMouseDownTimer();
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 5e28b8cdff5a14e8fd02951c27f4565af35f40d1..cd149e31131b2ba57bd7ac413d24ba54376c8f23 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -200,6 +200,7 @@ class LLButton
 	void			setDisabledSelectedLabelColor( const LLColor4& c )	{ mDisabledSelectedLabelColor = c; }
 
 	void			setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);
+	void 			setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);
 	LLPointer<LLUIImage> getImageOverlay() { return mImageOverlay; }
 
 	void            autoResize();	// resize with label of current btn state 
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 327dd01612b18c3cf20f87faa2249d84da61434a..43c44f2253e649097dce30ddc6b914b04ea3188f 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -1507,6 +1507,37 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
 	}
 }
 
+void LLTabContainer::setTabImage(LLPanel* child, const LLUUID& image_id, const LLColor4& color)
+{
+	static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
+	LLTabTuple* tuple = getTabByPanel(child);
+	if( tuple )
+	{
+		tuple->mButton->setImageOverlay(image_id, LLFontGL::RIGHT, color);
+
+		if (!mIsVertical)
+		{
+			// remove current width from total tab strip width
+			mTotalTabWidth -= tuple->mButton->getRect().getWidth();
+
+			S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
+				tuple->mButton->getImageOverlay()->getImage()->getWidth(0) :
+				0;
+
+			tuple->mPadding = image_overlay_width;
+
+			tuple->mButton->setRightHPad(6);
+			tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
+									tuple->mButton->getRect().getHeight());
+			// add back in button width to total tab strip width
+			mTotalTabWidth += tuple->mButton->getRect().getWidth();
+
+			// tabs have changed size, might need to scroll to see current tab
+			updateMaxScrollPos();
+		}
+	}
+}
+
 void LLTabContainer::setTitle(const std::string& title)
 {	
 	if (mTitleBox)
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index 5d0f194bf965dc29713f43b2271efcde386cf51c..33c49e0d6faff7250349c2f20835fdbe0505a8b3 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -172,6 +172,7 @@ class LLTabContainer : public LLPanel
 	BOOL        getTabPanelFlashing(LLPanel* child);
 	void		setTabPanelFlashing(LLPanel* child, BOOL state);
 	void 		setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white);
+	void 		setTabImage(LLPanel* child, const LLUUID& img_id, const LLColor4& color = LLColor4::white);
 	void		setTitle( const std::string& title );
 	const std::string getPanelTitle(S32 index);
 
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index a4fc095727d0158641b346f67ce97651a40c9a7d..c29a3a0035a3dbded4adbab335eb3bcb82389578 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10070,6 +10070,18 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>SpeakerParticipantRemoveDelay</key>
+    <map>
+      <key>Comment</key>
+      <string>Timeout to remove participants who is not in channel before removed from list of active speakers (text/voice chat)</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <real>10.0</real>
+    </map>
+
     <key>UseStartScreen</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 8da207f887f70e5a25c2c9154e12019758a96858..f1de4e298246769f0f85b16e6bc16df06eb655ff 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -1272,6 +1272,7 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)
 		chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index));
 
 		arrange();
+		LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, chiclet);
 
 		return true;
 	}
@@ -1299,6 +1300,7 @@ void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it)
 	mChicletList.erase(it);
 	
 	arrange();
+	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, chiclet);
 	chiclet->die();
 }
 
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 4789adb6046b942b9518ae63e12bba989482b45d..73597e7de3393b066d4c9224f1fb3f97f10d2aa7 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -110,6 +110,8 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
 		}
 	}
 	setOverlapsScreenChannel(true);
+
+	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
 }
 
 void LLIMFloater::onFocusLost()
@@ -228,6 +230,7 @@ void LLIMFloater::sendMsg()
 
 LLIMFloater::~LLIMFloater()
 {
+	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);
 }
 
 //virtual
@@ -351,13 +354,15 @@ void* LLIMFloater::createPanelAdHocControl(void* userdata)
 
 void LLIMFloater::onSlide()
 {
-	LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel");
-	im_control_panel->setVisible(!im_control_panel->getVisible());
+	mControlPanel->setVisible(!mControlPanel->getVisible());
+
+	gSavedSettings.setBOOL("IMShowControlPanel", mControlPanel->getVisible());
 
-	gSavedSettings.setBOOL("IMShowControlPanel", im_control_panel->getVisible());
+	getChild<LLButton>("slide_left_btn")->setVisible(mControlPanel->getVisible());
+	getChild<LLButton>("slide_right_btn")->setVisible(!mControlPanel->getVisible());
 
-	getChild<LLButton>("slide_left_btn")->setVisible(im_control_panel->getVisible());
-	getChild<LLButton>("slide_right_btn")->setVisible(!im_control_panel->getVisible());
+	LLLayoutStack* stack = getChild<LLLayoutStack>("im_panels");
+	if (stack) stack->setAnimate(true);
 }
 
 //static
@@ -511,14 +516,14 @@ bool LLIMFloater::toggle(const LLUUID& session_id)
 	if(!isChatMultiTab())
 	{
 		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
-		if (floater && floater->getVisible())
+		if (floater && floater->getVisible() && floater->hasFocus())
 		{
 			// clicking on chiclet to close floater just hides it to maintain existing
 			// scroll/text entry state
 			floater->setVisible(false);
 			return false;
 		}
-		else if(floater && !floater->isDocked())
+		else if(floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus()))
 		{
 			floater->setVisible(TRUE);
 			floater->setFocus(TRUE);
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index d9db385d06a0fb581ece415e524650113d9a34e2..0ca0325451bdf6874feefc052dc94eddc9a4a374 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -116,6 +116,8 @@ class LLIMFloater : public LLTransientDockableFloater
 
 	static void onIMChicletCreated(const LLUUID& session_id);
 
+	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; }
+
 private:
 	// process focus events to set a currently active session
 	/* virtual */ void onFocusLost();
diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp
index 6cc985aef494dbefd9d63593336e734a84a86860..06a7b4a29c235fc5246821a1ad48e89b4550b05d 100644
--- a/indra/newview/llimfloatercontainer.cpp
+++ b/indra/newview/llimfloatercontainer.cpp
@@ -35,19 +35,22 @@
 
 #include "llimfloatercontainer.h"
 #include "llfloaterreg.h"
+#include "llimview.h"
+#include "llavatariconctrl.h"
+#include "llagent.h"
 
 //
 // LLIMFloaterContainer
 //
 LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)
-:	LLMultiFloater(seed),
-	mActiveVoiceFloater(NULL)
+:	LLMultiFloater(seed)
 {
 	mAutoResize = FALSE;
 }
 
 LLIMFloaterContainer::~LLIMFloaterContainer()
 {
+	LLGroupMgr::getInstance()->removeObserver(this);
 }
 
 BOOL LLIMFloaterContainer::postBuild()
@@ -87,13 +90,84 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,
 
 	LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);
 
-	// make sure active voice icon shows up for new tab
-	if (floaterp == mActiveVoiceFloater)
+	LLUUID session_id = floaterp->getKey();
+
+	if(gAgent.isInGroup(session_id))
+	{
+		mSessions[session_id] = floaterp;
+		mID = session_id;
+		mGroupID.push_back(session_id);
+		LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(session_id);
+		LLGroupMgr* gm = LLGroupMgr::getInstance();
+		gm->addObserver(this);
+
+		if (group_data && group_data->mInsigniaID.notNull())
+		{
+			mTabContainer->setTabImage(get_ptr_in_map(mSessions, session_id), group_data->mInsigniaID);
+		}
+		else
+		{
+			gm->sendGroupPropertiesRequest(session_id);
+		}
+	}
+	else
+	{
+		LLUUID avatar_id = LLIMModel::getInstance()->getOtherParticipantID(session_id);
+		LLAvatarPropertiesProcessor& app = LLAvatarPropertiesProcessor::instance();
+		app.addObserver(avatar_id, this);
+		floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, avatar_id));
+		mSessions[avatar_id] = floaterp;
+
+		LLUUID* icon_id_ptr = LLAvatarIconIDCache::getInstance()->get(avatar_id);
+		if(!icon_id_ptr)
+		{
+			app.sendAvatarPropertiesRequest(avatar_id);
+		}
+		else
+		{
+			mTabContainer->setTabImage(floaterp, *icon_id_ptr);
+		}
+	}
+}
+
+void LLIMFloaterContainer::processProperties(void* data, enum EAvatarProcessorType type)
+{
+	if (APT_PROPERTIES == type)
+	{
+			LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data);
+			if (avatar_data)
+			{
+				LLUUID avatar_id = avatar_data->avatar_id;
+				if(avatar_data->image_id != *LLAvatarIconIDCache::getInstance()->get(avatar_id))
+				{
+					LLAvatarIconIDCache::getInstance()->add(avatar_id,avatar_data->image_id);
+				}
+				mTabContainer->setTabImage(get_ptr_in_map(mSessions, avatar_id), avatar_data->image_id);
+			}
+	}
+}
+
+void LLIMFloaterContainer::changed(LLGroupChange gc)
+{
+	if (GC_PROPERTIES == gc)
 	{
-		mTabContainer->setTabImage(floaterp, "active_voice_tab.tga");	
+		for(groupIDs_t::iterator it = mGroupID.begin(); it!=mGroupID.end(); it++)
+		{
+			LLUUID group_id = *it;
+			LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(group_id);
+			if (group_data && group_data->mInsigniaID.notNull())
+			{
+				mTabContainer->setTabImage(get_ptr_in_map(mSessions, group_id), group_data->mInsigniaID);
+			}
+		}
 	}
 }
 
+void LLIMFloaterContainer::onCloseFloater(LLUUID id)
+{
+	LLAvatarPropertiesProcessor::instance().removeObserver(id, this);
+}
+
 LLIMFloaterContainer* LLIMFloaterContainer::findInstance()
 {
 	return LLFloaterReg::findTypedInstance<LLIMFloaterContainer>("im_container");
diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h
index d4a542dfc22c449da8d184b3ca3254cb422b5175..1333b098bc28143d13c0d9240f9873239471441e 100644
--- a/indra/newview/llimfloatercontainer.h
+++ b/indra/newview/llimfloatercontainer.h
@@ -33,12 +33,17 @@
 #ifndef LL_LLIMFLOATERCONTAINER_H
 #define LL_LLIMFLOATERCONTAINER_H
 
+#include <map>
+#include <vector>
+
 #include "llfloater.h"
 #include "llmultifloater.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llgroupmgr.h"
 
 class LLTabContainer;
 
-class LLIMFloaterContainer : public LLMultiFloater
+class LLIMFloaterContainer : public LLMultiFloater, public LLAvatarPropertiesObserver, public LLGroupMgrObserver
 {
 public:
 	LLIMFloaterContainer(const LLSD& seed);
@@ -51,15 +56,23 @@ class LLIMFloaterContainer : public LLMultiFloater
 								BOOL select_added_floater, 
 								LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
 
+	void processProperties(void* data, EAvatarProcessorType type);
+	void changed(LLGroupChange gc);
+
 	static LLFloater* getCurrentVoiceFloater();
 
 	static LLIMFloaterContainer* findInstance();
 
 	static LLIMFloaterContainer* getInstance();
 
-protected:
-	
-	LLFloater* mActiveVoiceFloater;
+private:
+	typedef std::map<LLUUID,LLPanel*> avatarID_panel_map_t;
+	avatarID_panel_map_t mSessions;
+
+	typedef std::vector<LLUUID> groupIDs_t;
+	groupIDs_t mGroupID;
+
+	void onCloseFloater(LLUUID avatar_id);
 };
 
 #endif // LL_LLIMFLOATERCONTAINER_H
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 099f863dc9047394526a9e0467958f4afa4c9c40..2f4f2850654573ca901c380b7a7b6755c3765fdf 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3687,18 +3687,6 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
 	return rv;
 }
 
-BOOL LLCallingCardBridge::removeItem()
-{
-	if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem()))
-	{
-		LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
-		return FALSE;
-	}
-	else
-	{
-		return LLItemBridge::removeItem();
-	}
-}
 // +=================================================+
 // |        LLNotecardBridge                         |
 // +=================================================+
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index fced0047e8cb3ecb5c52b28219f23660312d6cde..759d0cba18a5b1e8b57255f1bd3ff44de5ec5a00 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -448,7 +448,6 @@ class LLCallingCardBridge : public LLItemBridge
 							EDragAndDropType cargo_type,
 							void* cargo_data);
 	void refreshFolderViewItem();
-	BOOL removeItem();
 
 protected:
 	LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid );
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 404e2668060ed409558ef4cae82497669bc33bd7..7f49a7defb51de4da554803a5e2aa61b36e3d5e7 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -43,8 +43,11 @@
 #include "lltrans.h"
 #include "lluictrlfactory.h"
 #include "lltooltip.h"
+#include "llnotificationsutil.h"
+#include "llregionflags.h"
 
 // newview includes
+#include "llagent.h"
 #include "llinventoryobserver.h"
 #include "lllandmarkactions.h"
 #include "lllandmarklist.h"
@@ -56,6 +59,7 @@
 #include "lltrans.h"
 #include "llviewerinventory.h"
 #include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
 #include "llviewercontrol.h"
 #include "llviewermenu.h"
 #include "llurllineeditorctrl.h"
@@ -256,36 +260,42 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
 	voice_icon.tool_tip = LLTrans::getString("LocationCtrlVoiceTooltip");
 	voice_icon.mouse_opaque = true;
 	mParcelIcon[VOICE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(voice_icon);
+	mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, VOICE_ICON));
 	addChild(mParcelIcon[VOICE_ICON]);
 
 	LLIconCtrl::Params fly_icon = p.fly_icon;
 	fly_icon.tool_tip = LLTrans::getString("LocationCtrlFlyTooltip");
 	fly_icon.mouse_opaque = true;
 	mParcelIcon[FLY_ICON] = LLUICtrlFactory::create<LLIconCtrl>(fly_icon);
+	mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, FLY_ICON));
 	addChild(mParcelIcon[FLY_ICON]);
 
 	LLIconCtrl::Params push_icon = p.push_icon;
 	push_icon.tool_tip = LLTrans::getString("LocationCtrlPushTooltip");
 	push_icon.mouse_opaque = true;
 	mParcelIcon[PUSH_ICON] = LLUICtrlFactory::create<LLIconCtrl>(push_icon);
+	mParcelIcon[PUSH_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, PUSH_ICON));
 	addChild(mParcelIcon[PUSH_ICON]);
 
 	LLIconCtrl::Params build_icon = p.build_icon;
 	build_icon.tool_tip = LLTrans::getString("LocationCtrlBuildTooltip");
 	build_icon.mouse_opaque = true;
 	mParcelIcon[BUILD_ICON] = LLUICtrlFactory::create<LLIconCtrl>(build_icon);
+	mParcelIcon[BUILD_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, BUILD_ICON));
 	addChild(mParcelIcon[BUILD_ICON]);
 
 	LLIconCtrl::Params scripts_icon = p.scripts_icon;
 	scripts_icon.tool_tip = LLTrans::getString("LocationCtrlScriptsTooltip");
 	scripts_icon.mouse_opaque = true;
 	mParcelIcon[SCRIPTS_ICON] = LLUICtrlFactory::create<LLIconCtrl>(scripts_icon);
+	mParcelIcon[SCRIPTS_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, SCRIPTS_ICON));
 	addChild(mParcelIcon[SCRIPTS_ICON]);
 
 	LLIconCtrl::Params damage_icon = p.damage_icon;
 	damage_icon.tool_tip = LLTrans::getString("LocationCtrlDamageTooltip");
 	damage_icon.mouse_opaque = true;
 	mParcelIcon[DAMAGE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(damage_icon);
+	mParcelIcon[DAMAGE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, DAMAGE_ICON));
 	addChild(mParcelIcon[DAMAGE_ICON]);
 	
 	LLTextBox::Params damage_text = p.damage_text;
@@ -918,3 +928,45 @@ bool LLLocationInputCtrl::onLocationContextMenuItemEnabled(const LLSD& userdata)
 
 	return false;
 }
+
+void LLLocationInputCtrl::onParcelIconClick(EParcelIcon icon)
+{
+	switch (icon)
+	{
+	case VOICE_ICON:
+		LLNotificationsUtil::add("NoVoice");
+		break;
+	case FLY_ICON:
+		LLNotificationsUtil::add("NoFly");
+		break;
+	case PUSH_ICON:
+		LLNotificationsUtil::add("PushRestricted");
+		break;
+	case BUILD_ICON:
+		LLNotificationsUtil::add("NoBuild");
+		break;
+	case SCRIPTS_ICON:
+	{
+		LLViewerRegion* region = gAgent.getRegion();
+		if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)
+		{
+			LLNotificationsUtil::add("ScriptsStopped");
+		}
+		else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
+		{
+			LLNotificationsUtil::add("ScriptsNotRunning");
+		}
+		else
+		{
+			LLNotificationsUtil::add("NoOutsideScripts");
+		}
+		break;
+	}
+	case DAMAGE_ICON:
+		LLNotificationsUtil::add("NotSafe");
+		break;
+	case ICON_COUNT:
+		break;
+	// no default to get compiler warning when a new icon gets added
+	}
+}
diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h
index 7959fab2de1b6297402dde99805080ef7371d644..607ccd4da6237237f57248568a959389486d6905 100644
--- a/indra/newview/lllocationinputctrl.h
+++ b/indra/newview/lllocationinputctrl.h
@@ -102,6 +102,18 @@ class LLLocationInputCtrl
 	void					handleLoginComplete();
 
 private:
+
+	enum EParcelIcon
+	{
+		VOICE_ICON = 0,
+		FLY_ICON,
+		PUSH_ICON,
+		BUILD_ICON,
+		SCRIPTS_ICON,
+		DAMAGE_ICON,
+		ICON_COUNT
+	};
+
 	friend class LLUICtrlFactory;
 	LLLocationInputCtrl(const Params&);
 	virtual ~LLLocationInputCtrl();
@@ -138,6 +150,7 @@ class LLLocationInputCtrl
 	// callbacks
 	bool					onLocationContextMenuItemEnabled(const LLSD& userdata);
 	void 					onLocationContextMenuItemClicked(const LLSD& userdata);
+	void					onParcelIconClick(EParcelIcon icon);
 
 	LLMenuGL*				mLocationContextMenu;
 	LLButton*				mAddLandmarkBtn;
@@ -146,16 +159,6 @@ class LLLocationInputCtrl
 	S32						mIconHPad;			// pad between all icons
 	S32						mAddLandmarkHPad;	// pad to left of landmark star
 	
-	enum EParcelIcon
-	{
-		VOICE_ICON = 0,
-		FLY_ICON,
-		PUSH_ICON,
-		BUILD_ICON,
-		SCRIPTS_ICON,
-		DAMAGE_ICON,
-		ICON_COUNT
-	};
 	LLIconCtrl*	mParcelIcon[ICON_COUNT];
 	LLTextBox* mDamageText;
 
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index b1cdb4d81f648f3ef9fe81d57c19e60ad9191dbe..86bdee7c7d58dab77e65819ce66a25336eb1b480 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -264,9 +264,6 @@ LLPanelGroupControlPanel::~LLPanelGroupControlPanel()
 // virtual
 void LLPanelGroupControlPanel::draw()
 {
-	//Remove event does not raised until speakerp->mActivityTimer.hasExpired() is false, see LLSpeakerManager::update()
-	//so we need update it to raise needed event
-	mSpeakerManager->update(true);
 	// Need to resort the participant list if it's in sort by recent speaker order.
 	if (mParticipantList)
 		mParticipantList->updateRecentSpeakersOrder();
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index d6e407a0edfc9f3a005bd5011f6231dc22c8ed82..47feef496af1f99033e172b0d73559d921595221 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -305,6 +305,29 @@ void LLLandmarksPanel::updateShowFolderState()
 		);
 }
 
+void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus)
+{
+	if (selectItemInAccordionTab(mFavoritesInventoryPanel, "tab_favorites", obj_id, take_keyboard_focus))
+	{
+		return;
+	}
+
+	if (selectItemInAccordionTab(mLandmarksInventoryPanel, "tab_landmarks", obj_id, take_keyboard_focus))
+	{
+		return;
+	}
+
+	if (selectItemInAccordionTab(mMyInventoryPanel, "tab_inventory", obj_id, take_keyboard_focus))
+	{
+		return;
+	}
+
+	if (selectItemInAccordionTab(mLibraryInventoryPanel, "tab_library", obj_id, take_keyboard_focus))
+	{
+		return;
+	}
+}
+
 //////////////////////////////////////////////////////////////////////////
 // PROTECTED METHODS
 //////////////////////////////////////////////////////////////////////////
@@ -350,6 +373,36 @@ LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const
 	return mCurrentSelectedList ?  mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;
 }
 
+LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list,
+															 const std::string& tab_name,
+															 const LLUUID& obj_id,
+															 BOOL take_keyboard_focus) const
+{
+	if (!inventory_list)
+		return NULL;
+
+	LLFolderView* folder_view = inventory_list->getRootFolder();
+
+	LLFolderViewItem* item = folder_view->getItemByID(obj_id);
+	if (!item)
+		return NULL;
+
+	LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(tab_name);
+	if (!tab->isExpanded())
+	{
+		tab->changeOpenClose(false);
+	}
+
+	folder_view->setSelection(item, FALSE, take_keyboard_focus);
+
+	LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
+	LLRect screen_rc;
+	localRectToScreen(item->getRect(), &screen_rc);
+	accordion->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue()));
+
+	return item;
+}
+
 void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate)
 {
 	if(!panel) return; 
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 569739237d46ecd793c0bad24752767d6eb68fb2..96b790844ca12e1f9ab84fc22f1457cc5af2b51e 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -73,6 +73,11 @@ class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
 	 */
 	void updateShowFolderState();
 
+	/**
+	 * Selects item with "obj_id" in one of accordion tabs.
+	 */
+	void setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus);
+
 protected:
 	/**
 	 * @return true - if current selected panel is not null and selected item is a landmark
@@ -81,6 +86,17 @@ class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
 	bool isReceivedFolderSelected() const;
 	void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb);
 	LLFolderViewItem* getCurSelectedItem() const;
+
+	/**
+	 * Selects item with "obj_id" in "inventory_list" and scrolls accordion
+	 * scrollbar to show the item.
+	 * Returns pointer to the item if it is found in "inventory_list", otherwise NULL.
+	 */
+	LLFolderViewItem* selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list,
+											   const std::string& tab_name,
+											   const LLUUID& obj_id,
+											   BOOL take_keyboard_focus) const;
+
 	void updateSortOrder(LLInventoryPanel* panel, bool byDate);
 
 	//LLRemoteParcelInfoObserver interface
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index a71c8d895899ae0da56020daad4afe445a7a553b..b037674c3744f4e1ba8271b4b92529c03437ad27 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -842,6 +842,19 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
 
 			mPlaceProfile->setVisible(FALSE);
 		}
+		else
+		{
+			LLLandmarksPanel* landmarks_panel =
+					dynamic_cast<LLLandmarksPanel*>(mTabContainer->getPanelByName("Landmarks"));
+			if (landmarks_panel && mItem.notNull())
+			{
+				// If a landmark info is being closed we open the landmarks tab
+				// and set this landmark selected.
+				mTabContainer->selectTabPanel(landmarks_panel);
+
+				landmarks_panel->setItemSelected(mItem->getUUID(), TRUE);
+			}
+		}
 	}
 }
 
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index b049f914ad88745257a0ef1fda4b73d53ceac08b..88b706fb6bf9aab3c7ab9cb99a214f5dc70cb6d9 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -125,6 +125,8 @@ LLParticipantList::~LLParticipantList()
 		delete mParticipantListMenu;
 		mParticipantListMenu = NULL;
 	}
+
+	mAvatarList->setContextMenu(NULL);
 }
 
 void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible)
@@ -431,6 +433,10 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()
 	LLContextMenu* main_menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
 		"menu_participant_list.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 
+	// Don't show sort options for P2P chat
+	bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1);
+	main_menu->setItemVisible("SortByName", is_sort_visible);
+	main_menu->setItemVisible("SortByRecentSpeakers", is_sort_visible);
 	main_menu->setItemVisible("Moderator Options", isGroupModerator());
 	main_menu->arrangeAndClear();
 
@@ -456,11 +462,6 @@ void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const
 		LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteSelected", false);
 		LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteOthers", false);
 	}
-
-	// Don't show sort options for P2P chat
-	bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1);
-	LLMenuGL::sMenuContainer->childSetVisible("SortByName", is_sort_visible);
-	LLMenuGL::sMenuContainer->childSetVisible("SortByRecentSpeakers", is_sort_visible);
 }
 
 void LLParticipantList::LLParticipantListMenu::sortParticipantList(const LLSD& userdata)
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 0dd9203c6d9992774c82dde2190034f36197d846..9608cd1263766a72ae959744ab76aad4d6c395b7 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -44,7 +44,6 @@
 #include "llvoavatar.h"
 #include "llworld.h"
 
-const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers
 const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
 const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
 
@@ -73,8 +72,6 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerTy
 	}
 
 	gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id));
-
-	mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
 }
 
 
@@ -164,6 +161,89 @@ bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPo
 	return(	lhs->mDisplayName.compare(rhs->mDisplayName) < 0 );
 }
 
+LLSpeakerActionTimer::LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id)
+: LLEventTimer(action_period)
+, mActionCallback(action_cb)
+, mSpeakerId(speaker_id)
+{
+}
+
+BOOL LLSpeakerActionTimer::tick()
+{
+	if (mActionCallback)
+	{
+		return (BOOL)mActionCallback(mSpeakerId);
+	}
+	return TRUE;
+}
+
+LLSpeakersDelayActionsStorage::LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay)
+: mActionCallback(action_cb)
+, mActionDelay(action_delay)
+{
+}
+
+LLSpeakersDelayActionsStorage::~LLSpeakersDelayActionsStorage()
+{
+	removeAllTimers();
+}
+
+void LLSpeakersDelayActionsStorage::setActionTimer(const LLUUID& speaker_id)
+{
+	bool not_found = true;
+	if (mActionTimersMap.size() > 0)
+	{
+		not_found = mActionTimersMap.find(speaker_id) == mActionTimersMap.end();
+	}
+
+	// If there is already a started timer for the passed UUID don't do anything.
+	if (not_found)
+	{
+		// Starting a timer to remove an participant after delay is completed
+		mActionTimersMap.insert(LLSpeakerActionTimer::action_value_t(speaker_id,
+			new LLSpeakerActionTimer(
+				boost::bind(&LLSpeakersDelayActionsStorage::onTimerActionCallback, this, _1),
+				mActionDelay, speaker_id)));
+	}
+}
+
+void LLSpeakersDelayActionsStorage::unsetActionTimer(const LLUUID& speaker_id)
+{
+	if (mActionTimersMap.size() == 0) return;
+
+	LLSpeakerActionTimer::action_timer_iter_t it_speaker = mActionTimersMap.find(speaker_id);
+
+	if (it_speaker != mActionTimersMap.end())
+	{
+		delete it_speaker->second;
+		mActionTimersMap.erase(it_speaker);
+	}
+}
+
+void LLSpeakersDelayActionsStorage::removeAllTimers()
+{
+	LLSpeakerActionTimer::action_timer_iter_t iter = mActionTimersMap.begin();
+	for (; iter != mActionTimersMap.end(); ++iter)
+	{
+		delete iter->second;
+	}
+	mActionTimersMap.clear();
+}
+
+bool LLSpeakersDelayActionsStorage::onTimerActionCallback(const LLUUID& speaker_id)
+{
+	unsetActionTimer(speaker_id);
+
+	if (mActionCallback)
+	{
+		mActionCallback(speaker_id);
+	}
+
+	// do not return true to avoid deleting of an timer twice:
+	// in LLSpeakersDelayActionsStorage::unsetActionTimer() & LLEventTimer::updateClass()
+	return false;
+}
+
 
 //
 // LLSpeakerMgr
@@ -172,10 +252,14 @@ bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPo
 LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) : 
 	mVoiceChannel(channelp)
 {
+	static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0);
+
+	mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay);
 }
 
 LLSpeakerMgr::~LLSpeakerMgr()
 {
+	delete mSpeakerDelayRemover;
 }
 
 LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
@@ -198,7 +282,6 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
 		{
 			// keep highest priority status (lowest value) instead of overriding current value
 			speakerp->mStatus = llmin(speakerp->mStatus, status);
-			speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
 			// RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id
 			// we need to override speakers that we think are objects when we find out they are really
 			// residents
@@ -210,6 +293,8 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
 		}
 	}
 
+	mSpeakerDelayRemover->unsetActionTimer(speakerp->mID);
+
 	return speakerp;
 }
 
@@ -314,7 +399,7 @@ void LLSpeakerMgr::update(BOOL resort_ok)
 	S32 sort_index = 0;
 	speaker_list_t::iterator sorted_speaker_it;
 	for(sorted_speaker_it = mSpeakersSorted.begin(); 
-		sorted_speaker_it != mSpeakersSorted.end(); )
+		sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it)
 	{
 		LLPointer<LLSpeaker> speakerp = *sorted_speaker_it;
 		
@@ -327,19 +412,6 @@ void LLSpeakerMgr::update(BOOL resort_ok)
 
 		// stuff sort ordinal into speaker so the ui can sort by this value
 		speakerp->mSortIndex = sort_index++;
-
-		// remove speakers that have been gone too long
-		if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL && speakerp->mActivityTimer.hasExpired())
-		{
-			fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "remove");
-
-			mSpeakers.erase(speakerp->mID);
-			sorted_speaker_it = mSpeakersSorted.erase(sorted_speaker_it);
-		}
-		else
-		{
-			++sorted_speaker_it;
-		}
 	}
 }
 
@@ -363,6 +435,35 @@ void LLSpeakerMgr::updateSpeakerList()
 	}
 }
 
+void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp)
+{
+	speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+	speakerp->mDotColor = INACTIVE_COLOR;
+	mSpeakerDelayRemover->setActionTimer(speakerp->mID);
+}
+
+bool LLSpeakerMgr::removeSpeaker(const LLUUID& speaker_id)
+{
+	mSpeakers.erase(speaker_id);
+
+	speaker_list_t::iterator sorted_speaker_it = mSpeakersSorted.begin();
+	
+	for(; sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it)
+	{
+		if (speaker_id == (*sorted_speaker_it)->mID)
+		{
+			mSpeakersSorted.erase(sorted_speaker_it);
+			break;
+		}
+	}
+
+	fireEvent(new LLSpeakerListChangeEvent(this, speaker_id), "remove");
+
+	update(TRUE);
+
+	return false;
+}
+
 LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id)
 {
 	//In some conditions map causes crash if it is empty(Windows only), adding check (EK)
@@ -511,9 +612,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
 			{
 				if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())
 				{
-					speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
-					speakerp->mDotColor = INACTIVE_COLOR;
-					speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+					setSpeakerNotInChannel(speakerp);
 				}
 				else if (agent_data["transition"].asString() == "ENTER")
 				{
@@ -563,9 +662,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
 			std::string agent_transition = update_it->second.asString();
 			if (agent_transition == "LEAVE" && speakerp.notNull())
 			{
-				speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
-				speakerp->mDotColor = INACTIVE_COLOR;
-				speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+				setSpeakerNotInChannel(speakerp);
 			}
 			else if ( agent_transition == "ENTER")
 			{
@@ -734,12 +831,13 @@ void LLActiveSpeakerMgr::updateSpeakerList()
 	mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
 
 	// always populate from active voice channel
-	if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel)
+	if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel) //MA: seems this is always false
 	{
 		fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");
 		mSpeakers.clear();
 		mSpeakersSorted.clear();
 		mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
+		mSpeakerDelayRemover->removeAllTimers();
 	}
 	LLSpeakerMgr::updateSpeakerList();
 
@@ -800,9 +898,7 @@ void LLLocalSpeakerMgr::updateSpeakerList()
 			LLVOAvatar* avatarp = (LLVOAvatar*)gObjectList.findObject(speaker_id);
 			if (!avatarp || dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS)
 			{
-				speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
-				speakerp->mDotColor = INACTIVE_COLOR;
-				speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+				setSpeakerNotInChannel(speakerp);
 			}
 		}
 	}
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index da8dfdf548e639dbaf949c8065bc7ca4fe568cd5..63237204c8620e2b1e40d2ef04864471a2fe1db0 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -73,7 +73,6 @@ class LLSpeaker : public LLRefCount, public LLOldEvents::LLObservable, public LL
 	F32				mLastSpokeTime;		// timestamp when this speaker last spoke
 	F32				mSpeechVolume;		// current speech amplitude (timea average rms amplitude?)
 	std::string		mDisplayName;		// cache user name for this speaker
-	LLFrameTimer	mActivityTimer;	// time out speakers when they are not part of current voice channel
 	BOOL			mHasSpoken;			// has this speaker said anything this session?
 	BOOL			mHasLeftCurrentCall;	// has this speaker left the current voice call?
 	LLColor4		mDotColor;
@@ -120,6 +119,92 @@ class LLSpeakerListChangeEvent : public LLOldEvents::LLEvent
 	const LLUUID& mSpeakerID;
 };
 
+/**
+ * class LLSpeakerActionTimer
+ * 
+ * Implements a timer that calls stored callback action for stored speaker after passed period.
+ *
+ * Action is called until callback returns "true".
+ * In this case the timer will be removed via LLEventTimer::updateClass().
+ * Otherwise it should be deleted manually in place where it is used.
+ * If action callback is not set timer will tick only once and deleted.
+ */
+class LLSpeakerActionTimer : public LLEventTimer
+{
+public:
+	typedef boost::function<bool(const LLUUID&)>	action_callback_t;
+	typedef std::map<LLUUID, LLSpeakerActionTimer*> action_timers_map_t;
+	typedef action_timers_map_t::value_type			action_value_t;
+	typedef action_timers_map_t::const_iterator		action_timer_const_iter_t;
+	typedef action_timers_map_t::iterator			action_timer_iter_t;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param action_cb - callback which will be called each time after passed action period.
+	 * @param action_period - time in seconds timer should tick.
+	 * @param speaker_id - LLUUID of speaker which will be passed into action callback.
+	 */
+	LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id);
+	virtual ~LLSpeakerActionTimer() {};
+
+	/**
+	 * Implements timer "tick".
+	 *
+	 * If action callback is not specified returns true. Instance will be deleted by LLEventTimer::updateClass().
+	 */
+	virtual BOOL tick();
+
+private:
+	action_callback_t	mActionCallback;
+	LLUUID				mSpeakerId;
+};
+
+/**
+ * Represents a functionality to store actions for speakers with delay.
+ * Is based on LLSpeakerActionTimer.
+ */
+class LLSpeakersDelayActionsStorage
+{
+public:
+	LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay);
+	~LLSpeakersDelayActionsStorage();
+
+	/**
+	 * Sets new LLSpeakerActionTimer with passed speaker UUID.
+	 */
+	void setActionTimer(const LLUUID& speaker_id);
+
+	/**
+	 * Removes stored LLSpeakerActionTimer for passed speaker UUID from internal map and deletes it.
+	 *
+	 * @see onTimerActionCallback()
+	 */
+	void unsetActionTimer(const LLUUID& speaker_id);
+
+	void removeAllTimers();
+private:
+	/**
+	 * Callback of the each instance of LLSpeakerActionTimer.
+	 *
+	 * Unsets an appropriate timer instance and calls action callback for specified speacker_id.
+	 * It always returns false to not use LLEventTimer::updateClass functionality of timer deleting.
+	 *
+	 * @see unsetActionTimer()
+	 */
+	bool onTimerActionCallback(const LLUUID& speaker_id);
+
+	LLSpeakerActionTimer::action_timers_map_t	mActionTimersMap;
+	LLSpeakerActionTimer::action_callback_t		mActionCallback;
+
+	/**
+	 * Delay to call action callback for speakers after timer was set.
+	 */
+	F32	mActionDelay;
+
+};
+
+
 class LLSpeakerMgr : public LLOldEvents::LLObservable
 {
 public:
@@ -144,6 +229,8 @@ class LLSpeakerMgr : public LLOldEvents::LLObservable
 
 protected:
 	virtual void updateSpeakerList();
+	void setSpeakerNotInChannel(LLSpeaker* speackerp);
+	bool removeSpeaker(const LLUUID& speaker_id);
 
 	typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
 	speaker_map_t		mSpeakers;
@@ -151,6 +238,11 @@ class LLSpeakerMgr : public LLOldEvents::LLObservable
 	speaker_list_t		mSpeakersSorted;
 	LLFrameTimer		mSpeechTimer;
 	LLVoiceChannel*		mVoiceChannel;
+
+	/**
+	 * time out speakers when they are not part of current session
+	 */
+	LLSpeakersDelayActionsStorage* mSpeakerDelayRemover;
 };
 
 class LLIMSpeakerMgr : public LLSpeakerMgr
diff --git a/indra/newview/lltransientdockablefloater.cpp b/indra/newview/lltransientdockablefloater.cpp
index 7e4d4988d128b55863d13fbfdf3971c07b8953ed..c9bfe178ce430a3e417e0feaa32541dc3cd05011 100644
--- a/indra/newview/lltransientdockablefloater.cpp
+++ b/indra/newview/lltransientdockablefloater.cpp
@@ -42,6 +42,7 @@ LLTransientDockableFloater::LLTransientDockableFloater(LLDockControl* dockContro
 		LLDockableFloater(dockControl, uniqueDocking, key, params)
 {
 	LLTransientFloaterMgr::getInstance()->registerTransientFloater(this);
+	LLTransientFloater::init(this);
 }
 
 LLTransientDockableFloater::~LLTransientDockableFloater()
diff --git a/indra/newview/lltransientdockablefloater.h b/indra/newview/lltransientdockablefloater.h
index 6e8a3afd2213a6dbf92ef2fc4e72f93393834e0f..e0541d6597917d5c2a581f2cffbc46a20f8dad3d 100644
--- a/indra/newview/lltransientdockablefloater.h
+++ b/indra/newview/lltransientdockablefloater.h
@@ -37,12 +37,13 @@
 #include "llfloater.h"
 #include "lldockcontrol.h"
 #include "lldockablefloater.h"
+#include "lltransientfloatermgr.h"
 
 /**
  * Represents floater that can dock and managed by transient floater manager.
  * Transient floaters should be hidden if user click anywhere except defined view list.
  */
-class LLTransientDockableFloater : public LLDockableFloater
+class LLTransientDockableFloater : public LLDockableFloater, LLTransientFloater
 {
 public:
 	LOG_CLASS(LLTransientDockableFloater);
@@ -52,6 +53,7 @@ class LLTransientDockableFloater : public LLDockableFloater
 
 	/*virtual*/ void setVisible(BOOL visible);
 	/* virtual */void setDocked(bool docked, bool pop_on_undock = true);
+	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; }
 };
 
 #endif /* LL_TRANSIENTDOCKABLEFLOATER_H */
diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp
index 347399f2391d1e1ed7e899adc90eb19cd4cb2c75..8f1a738453f996e81bbe71b1a53248ecb4ff1402 100644
--- a/indra/newview/lltransientfloatermgr.cpp
+++ b/indra/newview/lltransientfloatermgr.cpp
@@ -44,57 +44,68 @@ LLTransientFloaterMgr::LLTransientFloaterMgr()
 {
 	gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(
 			&LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3));
+
+	mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(GLOBAL, std::set<LLView*>()));
+	mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(IM, std::set<LLView*>()));
 }
 
-void LLTransientFloaterMgr::registerTransientFloater(LLFloater* floater)
+void LLTransientFloaterMgr::registerTransientFloater(LLTransientFloater* floater)
 {
 	mTransSet.insert(floater);
 }
 
-void LLTransientFloaterMgr::unregisterTransientFloater(LLFloater* floater)
+void LLTransientFloaterMgr::unregisterTransientFloater(LLTransientFloater* floater)
 {
 	mTransSet.erase(floater);
 }
 
+void LLTransientFloaterMgr::addControlView(ETransientGroup group, LLView* view)
+{
+	mGroupControls.find(group)->second.insert(view);
+}
+
+void LLTransientFloaterMgr::removeControlView(ETransientGroup group, LLView* view)
+{
+	mGroupControls.find(group)->second.erase(view);
+}
+
 void LLTransientFloaterMgr::addControlView(LLView* view)
 {
-	mControlsSet.insert(view);
+	addControlView(GLOBAL, view);
 }
 
 void LLTransientFloaterMgr::removeControlView(LLView* view)
 {
 	// we will still get focus lost callbacks on this view, but that's ok
 	// since we run sanity checking logic every time
-	mControlsSet.erase(view);
+	removeControlView(GLOBAL, view);
 }
 
-void LLTransientFloaterMgr::hideTransientFloaters()
+void LLTransientFloaterMgr::hideTransientFloaters(S32 x, S32 y)
 {
-	for (std::set<LLFloater*>::iterator it = mTransSet.begin(); it
+	for (std::set<LLTransientFloater*>::iterator it = mTransSet.begin(); it
 			!= mTransSet.end(); it++)
 	{
-		LLFloater* floater = *it;
-		if (floater->isDocked())
+		LLTransientFloater* floater = *it;
+		if (floater->isTransientDocked())
 		{
-			floater->setVisible(FALSE);
+			ETransientGroup group = floater->getGroup();
+
+			bool hide = isControlClicked(mGroupControls.find(group)->second, x, y);
+			if (hide)
+			{
+				floater->setTransientVisible(FALSE);
+			}
 		}
 	}
 }
 
-void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
-		MASK mask)
+bool LLTransientFloaterMgr::isControlClicked(std::set<LLView*>& set, S32 x, S32 y)
 {
-	bool hide = true;
-	for (controls_set_t::iterator it = mControlsSet.begin(); it
-			!= mControlsSet.end(); it++)
+	bool res = true;
+	for (controls_set_t::iterator it = set.begin(); it
+			!= set.end(); it++)
 	{
-		// don't hide transient floater if any context menu opened
-		if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL)
-		{
-			hide = false;
-			break;
-		}
-
 		LLView* control_view = *it;
 		if (!control_view->getVisible())
 		{
@@ -105,14 +116,32 @@ void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
 		// if click inside view rect
 		if (rect.pointInRect(x, y))
 		{
-			hide = false;
+			res = false;
 			break;
 		}
 	}
+	return res;
+}
+
+void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
+		MASK mask)
+{
+	// don't hide transient floater if any context menu opened
+	if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL)
+	{
+		return;
+	}
 
+	bool hide = isControlClicked(mGroupControls.find(GLOBAL)->second, x, y);
 	if (hide)
 	{
-		hideTransientFloaters();
+		hideTransientFloaters(x, y);
 	}
 }
 
+void LLTransientFloater::init(LLFloater* thiz)
+{
+	// used since LLTransientFloater(this) can't be used in descendant constructor parameter initialization.
+	mFloater = thiz;
+}
+
diff --git a/indra/newview/lltransientfloatermgr.h b/indra/newview/lltransientfloatermgr.h
index cef6e1fe4566a2615209e6a306d3c3723b0eaec1..1f99325a7fb98f4d1fb388d8009b8426ff1f788e 100644
--- a/indra/newview/lltransientfloatermgr.h
+++ b/indra/newview/lltransientfloatermgr.h
@@ -37,27 +37,60 @@
 #include "llsingleton.h"
 #include "llfloater.h"
 
+class LLTransientFloater;
 
 /**
  * Provides functionality to hide transient floaters.
  */
 class LLTransientFloaterMgr: public LLSingleton<LLTransientFloaterMgr>
 {
-public:
+protected:
 	LLTransientFloaterMgr();
-	void registerTransientFloater(LLFloater* floater);
-	void unregisterTransientFloater(LLFloater* floater);
+	friend class LLSingleton<LLTransientFloaterMgr>;
+
+public:
+	enum ETransientGroup
+	{
+		GLOBAL, IM
+	};
+
+	void registerTransientFloater(LLTransientFloater* floater);
+	void unregisterTransientFloater(LLTransientFloater* floater);
+	void addControlView(ETransientGroup group, LLView* view);
+	void removeControlView(ETransientGroup group, LLView* view);
 	void addControlView(LLView* view);
 	void removeControlView(LLView* view);
 
 private:
-	void hideTransientFloaters();
+	void hideTransientFloaters(S32 x, S32 y);
 	void leftMouseClickCallback(S32 x, S32 y, MASK mask);
-
+	bool isControlClicked(std::set<LLView*>& set, S32 x, S32 y);
 private:
-	std::set<LLFloater*> mTransSet;
+	std::set<LLTransientFloater*> mTransSet;
+
 	typedef std::set<LLView*> controls_set_t;
-	controls_set_t mControlsSet;
+	typedef std::map<ETransientGroup, std::set<LLView*> > group_controls_t;
+	group_controls_t mGroupControls;
+};
+
+/**
+ * An abstract class declares transient floater interfaces.
+ */
+class LLTransientFloater
+{
+protected:
+	/**
+	 * Class initialization method.
+	 * Should be called from descendant constructor.
+	 */
+	void init(LLFloater* thiz);
+public:
+	virtual LLTransientFloaterMgr::ETransientGroup getGroup() = 0;
+	bool isTransientDocked() { return mFloater->isDocked(); };
+	void setTransientVisible(BOOL visible) {mFloater->setVisible(visible); }
+
+private:
+	LLFloater* mFloater;
 };
 
 #endif  // LL_LLTRANSIENTFLOATERMGR_H
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index d57bc0af1d70188a7937bc82bdcf334af4deb5eb..7487fa99972184c00367f28cb3bd9c934aab4632 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2009,7 +2009,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 		// Someone has offered us some inventory.
 		{
 			LLOfferInfo* info = new LLOfferInfo;
-			bool mute_im = false;
 			if (IM_INVENTORY_OFFERED == dialog)
 			{
 				struct offer_agent_bucket_t
@@ -2026,11 +2025,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 				bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0];
 				info->mType = (LLAssetType::EType) bucketp->asset_type;
 				info->mObjectID = bucketp->object_id;
-				
-				if(accept_im_from_only_friend&&!is_friend)
-				{
-					mute_im = true;
-				}
 			}
 			else
 			{
@@ -2061,7 +2055,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 			info->mDesc = message;
 			info->mHost = msg->getSender();
 			//if (((is_busy && !is_owned_by_me) || is_muted))
-			if ( is_muted || mute_im)
+			if (is_muted)
 			{
 				// Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331)
 				LLInventoryFetchObserver::item_ref_t items;
diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml
index 1d51d19a4a05d139905f9df67efba6241f774963..bd25288a9ec996606a1ade92eabbb94c688b964a 100644
--- a/indra/newview/skins/default/xui/en/floater_im_container.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_container.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <multi_floater
- can_minimize="false"
+ can_close="false"  
+ can_minimize="true"
  can_resize="true"
  height="390"
  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index 243b63db0085bc596107a5f27fae2cec712117db..613530b7aa9bd922303ba88dd83b692cd60ffc1d 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -17,6 +17,7 @@
  min_width="250"
  min_height="190">
   <layout_stack
+   animate="false" 
   follows="all"
   height="320"
   width="360"
diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml
index a666b8a4273bc3ccc5198d7e1a81f9c983e7f0ee..9796f7b5b663747eaa047f1a5049fb024085f9ab 100644
--- a/indra/newview/skins/default/xui/en/inspect_avatar.xml
+++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml
@@ -58,8 +58,10 @@
      height="35"
      left="8"
      name="user_details"
+     right="-10"
      word_wrap="true"
      top_pad="6"
+     use_ellipses="true"
      width="220">This is my second life description and I really think it is great.
     </text>
     <slider
diff --git a/indra/newview/skins/default/xui/en/panel_my_profile.xml b/indra/newview/skins/default/xui/en/panel_my_profile.xml
index 2659156ba8bdea77f23a53fd25127d9efd726fdf..34cde61252ce77e2fad1587b6dc45261014205b7 100644
--- a/indra/newview/skins/default/xui/en/panel_my_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_my_profile.xml
@@ -51,6 +51,7 @@
          top="0"
          left="0"
          height="505"
+         user_resize="false"
          width="313">
         <scroll_container
          color="DkGray2"
@@ -365,6 +366,7 @@
      top_pad="0"
      name="profile_me_buttons_panel"
      visible="false"
+     user_resize="false" 
      auto_resize="false" 
      height="28"
      width="313">
diff --git a/indra/newview/skins/default/xui/en/panel_notes.xml b/indra/newview/skins/default/xui/en/panel_notes.xml
index 45b64d5e26be29077c45ef20a9332e696d3a5244..ac100a2c0694b88f7503b81d0f4ecd85cae84fdd 100644
--- a/indra/newview/skins/default/xui/en/panel_notes.xml
+++ b/indra/newview/skins/default/xui/en/panel_notes.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel
  follows="all"
- height="535"
+ height="540"
  label="Notes &amp; Privacy"
  layout="topleft"
  left="0"
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 8a02637817ae2869d302b25b51ee16b3abb1cd07..da3a2274c958f3ec18c8e60620c97145b592e0d4 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -3,7 +3,7 @@
 <panel
 background_visible="true"
  follows="all"
- height="570"
+ height="575"
  label="People"
  layout="topleft"
  min_height="350"
@@ -337,7 +337,7 @@ background_visible="true"
     </tab_container>
     <panel
      follows="bottom|left"
-     height="25"
+     height="35"
      layout="topleft"
      left="10"
      name="button_bar"
diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml
index 822e049eec040045203412ed1c81be934b694e46..65ccd10cf02788b90bbd881c606a4f52e05e2156 100644
--- a/indra/newview/skins/default/xui/en/panel_pick_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml
@@ -39,7 +39,7 @@
      height="500"
      layout="topleft"
      left="10"
-     top_pad="10"
+     top_pad="5"
      name="profile_scroll"
      width="313">
     <panel
@@ -102,7 +102,7 @@
     </scroll_container>
     <panel
      follows="left|right|bottom"
-     height="20"
+     height="35"
      layout="topleft"
      top_pad="8"
      left="10"
diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml
index a2b0adf9d9835d9f16a459712fb24360e4a8884d..d31f4d039f9e5e6c335e6545dd0d7385a63bfade 100644
--- a/indra/newview/skins/default/xui/en/panel_picks.xml
+++ b/indra/newview/skins/default/xui/en/panel_picks.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel
  follows="all"
- height="535"
+ height="540"
  label="Picks"
  layout="topleft"
  left="0"
@@ -121,7 +121,7 @@
         <panel
          layout="topleft"
          left="0"
-         height="25"
+         height="30"
          top_pad="10"
          name="buttons_cucks"
          width="313">
diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml
index 2b907ed251d27da141f20ae5b80bcce649c03a9d..812dc5ce5925177e0c3bae5855a2865e3e62c7cf 100644
--- a/indra/newview/skins/default/xui/en/panel_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel
  follows="all"
- height="535"
+ height="540"
  label="Profile"
  layout="topleft"
  left="0"
@@ -284,7 +284,7 @@
       </layout_panel>
       <layout_panel
               follows="bottom|left"
-         height="28"
+         height="30"
          layout="topleft"
          name="profile_buttons_panel"
          auto_resize="false" 
@@ -355,7 +355,7 @@
         </layout_panel>
       <layout_panel
          follows="bottom|left"
-         height="28"
+         height="30"
          layout="topleft"
          name="profile_me_buttons_panel"
          visible="false"
@@ -364,7 +364,7 @@
          follows="bottom|right"
          height="23"
          left="20"
-	 top="0"
+         top="0"
          label="Edit Profile"
          name="edit_profile_btn"
          tool_tip="Edit your personal information"
diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml
index c51447eaf002b38b422c6c5da9e610ec5ef844ad..d46e1f98525d96f8e2f3844e53d5fe3092a1190a 100644
--- a/indra/newview/skins/default/xui/en/panel_profile_view.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml
@@ -60,7 +60,7 @@
      tab_min_width="80"
      tab_height="30"
      tab_position="top"
-     top_pad="10"
+     top_pad="5"
      width="313">
         <panel
          class="panel_profile"