From 6f41747bc4d8afcb2b19ac02295575031bcf9021 Mon Sep 17 00:00:00 2001
From: Steven Bennetts <steve@lindenlab.com>
Date: Wed, 21 Oct 2009 04:58:23 +0000
Subject: [PATCH] Merging revisions 2112-2128 of
 https://svn.aws.productengine.com/secondlife/pe/stable-2 into
 P:\svn\viewer-2.0.0, respecting ancestry * Bugs: EXT-1605 EXT-1506 EXT-1663
 EXT-1616 EXT-1599 EXT-1587 * Dev: EXT-748 EXT-1447 * IM Cleanup

---
 .../media_plugins/gstreamer010/CMakeLists.txt |  6 +-
 indra/newview/CMakeLists.txt                  |  2 +
 indra/newview/app_settings/settings.xml       | 33 ++++---
 indra/newview/llavatarlist.cpp                | 14 ++-
 indra/newview/llavatarlist.h                  |  7 +-
 indra/newview/llavatarlistitem.cpp            |  4 +-
 indra/newview/llavatarlistitem.h              |  2 +-
 indra/newview/llchannelmanager.cpp            |  2 +-
 indra/newview/llchiclet.cpp                   |  3 +-
 indra/newview/llfriendcard.cpp                | 87 +++++++++++++++++++
 indra/newview/llfriendcard.h                  |  6 ++
 indra/newview/llimfloater.cpp                 | 32 ++++++-
 indra/newview/llimfloater.h                   |  5 ++
 indra/newview/llimpanel.cpp                   |  4 +-
 indra/newview/llimpanel.h                     |  2 -
 indra/newview/llimview.cpp                    | 69 +++++++++------
 indra/newview/llimview.h                      | 30 +++++--
 indra/newview/llinventorybridge.cpp           | 59 ++++++++++++-
 indra/newview/llinventorybridge.h             |  1 +
 indra/newview/llnearbychathandler.cpp         |  2 +-
 indra/newview/llnotificationtiphandler.cpp    |  1 +
 indra/newview/llpanellandmarks.cpp            | 29 ++-----
 indra/newview/llpanelteleporthistory.cpp      | 80 +++++++++++++++--
 indra/newview/llpanelteleporthistory.h        |  5 +-
 indra/newview/llparticipantlist.cpp           | 56 ++++++++++++
 indra/newview/llparticipantlist.h             | 48 ++++++++++
 indra/newview/llscreenchannel.cpp             | 18 ++--
 indra/newview/llsyswellwindow.cpp             |  2 +-
 indra/newview/llteleporthistorystorage.cpp    | 13 +--
 indra/newview/llteleporthistorystorage.h      |  5 +-
 indra/newview/lltoast.cpp                     | 12 +--
 indra/newview/lltoast.h                       |  9 +-
 .../xui/en/menu_teleport_history_item.xml     |  6 +-
 .../skins/default/xui/en/panel_people.xml     |  1 +
 34 files changed, 519 insertions(+), 136 deletions(-)
 create mode 100644 indra/newview/llparticipantlist.cpp
 create mode 100644 indra/newview/llparticipantlist.h

diff --git a/indra/media_plugins/gstreamer010/CMakeLists.txt b/indra/media_plugins/gstreamer010/CMakeLists.txt
index 5c0ce3ee174..a9f7938b412 100644
--- a/indra/media_plugins/gstreamer010/CMakeLists.txt
+++ b/indra/media_plugins/gstreamer010/CMakeLists.txt
@@ -42,12 +42,12 @@ set(media_plugin_gstreamer010_HEADER_FILES
     llmediaimplgstreamertriviallogging.h
     )
 
-if (${CXX_VERSION} MATCHES "4.[23]")
+if (${CXX_VERSION} MATCHES "4[23].")
     # Work around a bad interaction between broken gstreamer headers and
     # g++ 4.3's increased strictness.
     set_source_files_properties(llmediaimplgstreamervidplug.cpp PROPERTIES
-                                COMPILE_FLAGS -Wno-error=write-strings)
-endif (${CXX_VERSION} MATCHES "4.[23]")
+                                COMPILE_FLAGS -Wno-write-strings)
+endif (${CXX_VERSION} MATCHES "4[23].")
 
 add_library(media_plugin_gstreamer010
     SHARED
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index df206513621..fbf14a73590 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -338,6 +338,7 @@ set(viewer_SOURCE_FILES
     llpanelteleporthistory.cpp
     llpanelvolume.cpp
     llparcelselection.cpp
+    llparticipantlist.cpp
     llpatchvertexarray.cpp
     llplacesinventorybridge.cpp
     llpolymesh.cpp
@@ -803,6 +804,7 @@ set(viewer_HEADER_FILES
     llpanelteleporthistory.h
     llpanelvolume.h
     llparcelselection.h
+    llparticipantlist.h
     llpatchvertexarray.h
     llplacesinventorybridge.h
     llpolymesh.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 4bfb472b936..7e368b0c9c8 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4842,10 +4842,10 @@
       <key>Value</key>
       <integer>350</integer>
     </map>
-    <key>NotificationToastTime</key>
+    <key>NotificationToastLifeTime</key>
     <map>
       <key>Comment</key>
-      <string>Width of notification messages</string>
+      <string>Number of seconds while a notification toast exists</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
@@ -4853,21 +4853,32 @@
       <key>Value</key>
       <integer>5</integer>
     </map>
+    <key>NotificationTipToastLifeTime</key>
+    <map>
+      <key>Comment</key>
+      <string>Number of seconds while a notification tip toast exist</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>10</integer>
+    </map>
     <key>ToastOpaqueTime</key>
     <map>
       <key>Comment</key>
-      <string>Width of notification messages</string>
+      <string>Number of seconds while a toast is fading </string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
       <string>S32</string>
       <key>Value</key>
-      <integer>4</integer>
+      <integer>1</integer>
     </map>
-    <key>StartUpToastTime</key>
+    <key>StartUpToastLifeTime</key>
     <map>
       <key>Comment</key>
-      <string>Width of notification messages</string>
+      <string>Number of seconds while a StartUp toast exist</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
@@ -4875,10 +4886,10 @@
       <key>Value</key>
       <integer>5</integer>
     </map>
-    <key>ToastMargin</key>
+    <key>ToastGap</key>
     <map>
       <key>Comment</key>
-      <string>Width of notification messages</string>
+      <string>Gap between toasts on a screen</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
@@ -4889,7 +4900,7 @@
     <key>ChannelBottomPanelMargin</key>
     <map>
       <key>Comment</key>
-      <string>Width of notification messages</string>
+      <string>Space from a lower toast to the Bottom Tray</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
@@ -4900,7 +4911,7 @@
     <key>NotificationChannelRightMargin</key>
     <map>
       <key>Comment</key>
-      <string>Width of notification messages</string>
+      <string>Space between toasts and a right border of an area where they can appear</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
@@ -4911,7 +4922,7 @@
     <key>OverflowToastHeight</key>
     <map>
       <key>Comment</key>
-      <string>Width of notification messages</string>
+      <string>Height of an overflow toast</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index ef48420490b..2034f98517a 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -57,17 +57,13 @@ static const LLAvatarItemNameComparator NAME_COMPARATOR;
 static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_COMPARATOR);
 
 LLAvatarList::Params::Params()
-:
-volume_column_width("volume_column_width", 0)
-, online_go_first("online_go_first", true)
+: ignore_online_status("ignore_online_status", false)
 {
 }
 
-
-
 LLAvatarList::LLAvatarList(const Params& p)
 :	LLFlatListView(p)
-, mOnlineGoFirst(p.online_go_first)
+, mIgnoreOnlineStatus(p.ignore_online_status)
 , mContextMenu(NULL)
 , mDirty(true) // to force initial update
 {
@@ -194,15 +190,15 @@ void LLAvatarList::refresh()
 }
 
 
-void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos)
+void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos)
 {
 	LLAvatarListItem* item = new LLAvatarListItem();
 	item->showStatus(false);
 	item->showInfoBtn(true);
 	item->showSpeakingIndicator(true);
 	item->setName(name);
-	item->setAvatarId(id);
-	item->setOnline(is_bold);
+	item->setAvatarId(id, mIgnoreOnlineStatus);
+	item->setOnline(mIgnoreOnlineStatus ? true : is_online);
 	item->setContextMenu(mContextMenu);
 
 	item->childSetVisible("info_btn", false);
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index ec801645feb..7372538006e 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -55,8 +55,7 @@ class LLAvatarList : public LLFlatListView
 
 	struct Params : public LLInitParam::Block<Params, LLFlatListView::Params> 
 	{
-		Optional<S32> volume_column_width;
-		Optional<bool> online_go_first;
+		Optional<bool> ignore_online_status; // show all items as online
 		Params();
 	};
 
@@ -76,7 +75,7 @@ class LLAvatarList : public LLFlatListView
 protected:
 	void refresh();
 
-	void addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos = ADD_BOTTOM);
+	void addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos = ADD_BOTTOM);
 	void computeDifference(
 		const std::vector<LLUUID>& vnew,
 		std::vector<LLUUID>& vadded,
@@ -84,7 +83,7 @@ class LLAvatarList : public LLFlatListView
 
 private:
 
-	bool mOnlineGoFirst;
+	bool mIgnoreOnlineStatus;
 	bool mDirty;
 
 	std::string				mNameFilter;
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index 90408beca08..732db90cdbe 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -180,7 +180,7 @@ void LLAvatarListItem::setName(const std::string& name)
 	mAvatarName->setToolTip(name);
 }
 
-void LLAvatarListItem::setAvatarId(const LLUUID& id)
+void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes)
 {
 	if (mAvatarId.notNull())
 		LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarId, this);
@@ -190,7 +190,7 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id)
 	mSpeakingIndicator->setSpeakerId(id);
 
 	// We'll be notified on avatar online status changes
-	if (mAvatarId.notNull())
+	if (!ignore_status_changes && mAvatarId.notNull())
 		LLAvatarTracker::instance().addParticularFriendObserver(mAvatarId, this);
 
 	// Set avatar name.
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index 2330db52491..ca75e3898f5 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -64,7 +64,7 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 	void setStatus(const std::string& status);
 	void setOnline(bool online);
 	void setName(const std::string& name);
-	void setAvatarId(const LLUUID& id);
+	void setAvatarId(const LLUUID& id, bool ignore_status_changes = false);
 	
 	const LLUUID& getAvatarId() const;
 	const std::string getAvatarName() const;
diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp
index c4619dc57a5..a75ae1d3b3c 100644
--- a/indra/newview/llchannelmanager.cpp
+++ b/indra/newview/llchannelmanager.cpp
@@ -128,7 +128,7 @@ void LLChannelManager::onLoginCompleted()
 	mStartUpChannel->setShowToasts(true);
 
 	mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this));
-	mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("ChannelBottomPanelMargin"), gSavedSettings.getS32("StartUpToastTime"));
+	mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("ChannelBottomPanelMargin"), gSavedSettings.getS32("StartUpToastLifeTime"));
 }
 
 //--------------------------------------------------------------------------
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 69fa5cdfe7a..43aca430a2b 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -861,7 +861,8 @@ void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){
 BOOL LLChicletPanel::postBuild()
 {
 	LLPanel::postBuild();
-	LLIMModel::instance().addChangedCallback(boost::bind(im_chiclet_callback, this, _1));
+	LLIMModel::instance().addNewMsgCallback(boost::bind(im_chiclet_callback, this, _1));
+	LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(im_chiclet_callback, this, _1));
 	LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLChicletPanel::findChiclet<LLChiclet>, this, _1));
 
 	return TRUE;
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index 97b7f3e9ad0..fbcaeee01f2 100644
--- a/indra/newview/llfriendcard.cpp
+++ b/indra/newview/llfriendcard.cpp
@@ -166,6 +166,93 @@ bool LLFriendCardsManager::isItemInAnyFriendsList(const LLViewerInventoryItem* i
 	return items.count() > 0;
 }
 
+
+bool LLFriendCardsManager::isObjDirectDescendentOfCategory(const LLInventoryObject* obj, 
+	const LLViewerInventoryCategory* cat) const
+{
+	// we need both params to proceed.
+	if ( !obj || !cat )
+		return false;
+
+	// Need to check that target category is in the Calling Card/Friends folder. 
+	// In other case function returns unpredictable result.
+	if ( !isCategoryInFriendFolder(cat) )
+		return false;
+
+	bool result = false;
+
+	LLInventoryModel::item_array_t* items;
+	LLInventoryModel::cat_array_t* cats;
+
+	gInventory.lockDirectDescendentArrays(cat->getUUID(), cats, items);
+	if ( items )
+	{
+		if ( obj->getType() == LLAssetType::AT_CALLINGCARD )
+		{
+			// For CALLINGCARD compare items by creator's id, if they are equal assume
+			// that it is same card and return true. Note: UUID's of compared items
+			// may be not equal. Also, we already know that obj should be type of LLInventoryItem,
+			// but in case inventory database is broken check what dynamic_cast returns.
+			const LLInventoryItem* item = dynamic_cast < const LLInventoryItem* > (obj);
+			if ( item )
+			{
+				LLUUID creator_id = item->getCreatorUUID();
+				LLViewerInventoryItem* cur_item = NULL;
+				for ( S32 i = items->count() - 1; i >= 0; --i )
+				{
+					cur_item = items->get(i);
+					if ( creator_id == cur_item->getCreatorUUID() )
+					{
+						result = true;
+						break;
+					}
+				}
+			}
+		}
+		else
+		{
+			// Else check that items have same type and name.
+			// Note: UUID's of compared items also may be not equal.
+			std::string obj_name = obj->getName();
+			LLViewerInventoryItem* cur_item = NULL;
+			for ( S32 i = items->count() - 1; i >= 0; --i )
+			{
+				cur_item = items->get(i);
+				if ( obj->getType() != cur_item->getType() )
+					continue;
+				if ( obj_name == cur_item->getName() )
+				{
+					result = true;
+					break;
+				}
+			}
+		}
+	}
+	if ( !result && cats )
+	{
+		// There is no direct descendent in items, so check categories.
+		// If target obj and descendent category have same type and name
+		// then return true. Note: UUID's of compared items also may be not equal.
+		std::string obj_name = obj->getName();
+		LLViewerInventoryCategory* cur_cat = NULL;
+		for ( S32 i = cats->count() - 1; i >= 0; --i )
+		{
+			cur_cat = cats->get(i);
+			if ( obj->getType() != cur_cat->getType() )
+				continue;
+			if ( obj_name == cur_cat->getName() )
+			{
+				result = true;
+				break;
+			}
+		}
+	}
+	gInventory.unlockDirectDescendentArrays(cat->getUUID());
+
+	return result;
+}
+
+
 bool LLFriendCardsManager::isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const
 {
 	if (NULL == cat)
diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h
index aa391ce2c16..6ada3428311 100644
--- a/indra/newview/llfriendcard.h
+++ b/indra/newview/llfriendcard.h
@@ -71,6 +71,12 @@ class LLFriendCardsManager
 	 */
 	bool isItemInAnyFriendsList(const LLViewerInventoryItem* item);
 
+	/**
+	 *	Checks if specified category is contained in the Calling Card/Friends folder and 
+	 *	determines if specified Inventory Object exists in that category.
+	 */
+	bool isObjDirectDescendentOfCategory(const LLInventoryObject* obj, const LLViewerInventoryCategory* cat) const;
+
 	/**
 	 *	Checks is the specified category is in the Calling Card/Friends folder
 	 */
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 452943007d8..8f0186ce245 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -83,13 +83,20 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
 	}
 }
 
+void LLIMFloater::onFocusLost()
+{
+	LLIMModel::getInstance()->resetActiveSessionID();
+}
+
+void LLIMFloater::onFocusReceived()
+{
+	LLIMModel::getInstance()->setActiveSessionID(mSessionID);
+}
+
 // virtual
 void LLIMFloater::onClose(bool app_quitting)
 {
-	LLIMModel::instance().sendLeaveSession(mSessionID, mOtherParticipantUUID);
-
-	//*TODO - move to the IMModel::sendLeaveSession() for the integrity (IB)
-	gIMMgr->removeSession(mSessionID);
+	gIMMgr->leaveSession(mSessionID);
 }
 
 /* static */
@@ -114,6 +121,23 @@ void LLIMFloater::newIMCallback(const LLSD& data){
 	}
 }
 
+void LLIMFloater::onVisibilityChange(const LLSD& new_visibility)
+{
+	bool visible = new_visibility.asBoolean();
+
+	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
+
+	if (visible && voice_channel &&
+		voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED)
+	{
+		LLFloaterReg::showInstance("voice_call", mSessionID);
+	}
+	else
+	{
+		LLFloaterReg::hideInstance("voice_call", mSessionID);
+	}
+}
+
 void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata )
 {
 	LLIMFloater* self = (LLIMFloater*) userdata;
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index e2f59c3507f..8fd0c7cde9a 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -84,7 +84,12 @@ class LLIMFloater : public LLTransientDockableFloater
 	// called when docked floater's position has been set by chiclet
 	void setPositioned(bool b) { mPositioned = b; };
 
+	void onVisibilityChange(const LLSD& new_visibility);
+
 private:
+	// process focus events to set a currently active session
+	/* virtual */ void onFocusLost();
+	/* virtual */ void onFocusReceived();
 	
 	static void		onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata );
 	static void		onInputEditorFocusLost(LLFocusableElement* caller, void* userdata);
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index ead74b72bff..163984f7409 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -1586,9 +1586,7 @@ void LLFloaterIMPanel::onClose(bool app_quitting)
 {
 	setTyping(FALSE);
 
-	LLIMModel::instance().sendLeaveSession(mSessionUUID, mOtherParticipantUUID);
-
-	gIMMgr->removeSession(mSessionUUID);
+	gIMMgr->leaveSession(mSessionUUID);
 
 	// *HACK hide the voice floater
 	LLFloaterReg::hideInstance("voice_call", mSessionUUID);
diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h
index af50362f001..4e306c7fabf 100644
--- a/indra/newview/llimpanel.h
+++ b/indra/newview/llimpanel.h
@@ -250,8 +250,6 @@ class LLFloaterIMPanel : public LLFloater
 	EInstantMessage getDialogType() const { return mDialog; }
 	void setDialogType(EInstantMessage dialog) { mDialog = dialog; }
 
-	void requestAutoConnect();
-
 	void sessionInitReplyReceived(const LLUUID& im_session_id);
 
 	// Handle other participant in the session typing.
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 20b9cc1f8ba..9974de0ef17 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -93,30 +93,45 @@ std::map<LLUUID, LLIMModel::LLIMSession*> LLIMModel::sSessionsMap;
 
 
 void toast_callback(const LLSD& msg){
-	// do not show toast in busy mode
-	if (gAgent.getBusy())
+	// do not show toast in busy mode or it goes from agent
+	if (gAgent.getBusy() || gAgent.getID() == msg["from_id"])
 	{
 		return;
 	}
-	
-	//we send notifications to reset counter also
-	if (msg["num_unread"].asInteger())
+
+	// check whether incoming IM belongs to an active session or not
+	if (LLIMModel::getInstance()->getActiveSessionID() == msg["session_id"])
 	{
-		LLSD args;
-		args["MESSAGE"] = msg["message"];
-		args["TIME"] = msg["time"];
-		args["FROM"] = msg["from"];
-		args["FROM_ID"] = msg["from_id"];
-		args["SESSION_ID"] = msg["session_id"];
+		return;
+	}
+	
+	LLSD args;
+	args["MESSAGE"] = msg["message"];
+	args["TIME"] = msg["time"];
+	args["FROM"] = msg["from"];
+	args["FROM_ID"] = msg["from_id"];
+	args["SESSION_ID"] = msg["session_id"];
 
-		LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID()));
+	LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID()));
+}
+
+void LLIMModel::setActiveSessionID(const LLUUID& session_id)
+{
+	// check if such an ID really exists
+	if (!findIMSession(session_id))
+	{
+		llwarns << "Trying to set as active a non-existent session!" << llendl;
+		return;
 	}
+
+	mActiveSessionID = session_id;
 }
 
 LLIMModel::LLIMModel() 
 {
-	addChangedCallback(LLIMFloater::newIMCallback);
-	addChangedCallback(toast_callback);
+	addNewMsgCallback(LLIMFloater::newIMCallback);
+	addNoUnreadMsgsCallback(LLIMFloater::newIMCallback);
+	addNewMsgCallback(toast_callback);
 }
 
 
@@ -311,7 +326,7 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
 	LLSD arg;
 	arg["session_id"] = session_id;
 	arg["num_unread"] = 0;
-	mChangedSignal(arg);
+	mNoUnreadMsgsSignal(arg);
 
     // TODO: in the future is there a more efficient way to return these
 	//of course there is - return as parameter (IB)
@@ -390,7 +405,7 @@ bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id,
 	arg["from"] = from;
 	arg["from_id"] = from_id;
 	arg["time"] = LLLogChat::timestamp(false);
-	mChangedSignal(arg);
+	mNewMsgSignal(arg);
 
 	return true;
 }
@@ -623,11 +638,6 @@ void LLIMModel::sendMessage(const std::string& utf8_text,
 	//*TODO should be deleted, because speaker manager updates through callback the recent list
 	LLRecentPeople::instance().add(other_participant_id);
 }
-										  
-boost::signals2::connection LLIMModel::addChangedCallback( boost::function<void (const LLSD& data)> cb )
-{
-	return mChangedSignal.connect(cb);
-}
 
 void session_starter_helper(
 	const LLUUID& temp_session_id,
@@ -1274,13 +1284,6 @@ void LLIMMgr::addMessage(
 		return;
 	}
 
-	//not sure why...but if it is from ourselves we set the target_id
-	//to be NULL
-	if( other_participant_id == gAgent.getID() )
-	{
-		other_participant_id = LLUUID::null;
-	}
-
 	LLFloaterIMPanel* floater;
 	LLUUID new_session_id = session_id;
 	if (new_session_id.isNull())
@@ -1549,6 +1552,16 @@ LLUUID LLIMMgr::addSession(
 	return session_id;
 }
 
+bool LLIMMgr::leaveSession(const LLUUID& session_id)
+{
+	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
+	if (!im_session) return false;
+
+	LLIMModel::getInstance()->sendLeaveSession(session_id, im_session->mOtherParticipantID);
+	gIMMgr->removeSession(session_id);
+	return true;
+}
+
 // This removes the panel referenced by the uuid, and then restores
 // internal consistency. The internal pointer is not deleted? Did you mean
 // a pointer to the corresponding LLIMSession? Session data is cleared now.
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index d98b5ca2973..f9db6d8ed23 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -75,10 +75,20 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 
 	LLIMModel();
 
+
+	//we should control the currently active session
+	LLUUID	mActiveSessionID;
+	void	setActiveSessionID(const LLUUID& session_id);
+	void	resetActiveSessionID() { mActiveSessionID.setNull(); }
+	LLUUID	getActiveSessionID() { return mActiveSessionID; }
+
 	//*TODO make it non-static as LLIMMOdel is a singleton (IB)
 	static std::map<LLUUID, LLIMSession*> sSessionsMap;  //mapping session_id to session
 
-	boost::signals2::signal<void(const LLSD&)> mChangedSignal;
+	typedef boost::signals2::signal<void(const LLSD&)> session_signal_t;
+	typedef boost::function<void(const LLSD&)> session_callback_t;
+	session_signal_t mNewMsgSignal;
+	session_signal_t mNoUnreadMsgsSignal;
 	
 	/** 
 	 * Find an IM Session corresponding to session_id
@@ -91,7 +101,8 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 	 */
 	void updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id);
 
-	boost::signals2::connection addChangedCallback( boost::function<void (const LLSD& data)> cb );
+	boost::signals2::connection addNewMsgCallback( session_callback_t cb ) { return mNewMsgSignal.connect(cb); }
+	boost::signals2::connection addNoUnreadMsgsCallback( session_callback_t cb ) { return mNoUnreadMsgsSignal.connect(cb); }
 
 	bool newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id, 
 		const std::vector<LLUUID>& ids = std::vector<LLUUID>());
@@ -219,10 +230,12 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 					  const std::string& voice_session_handle,
 					  const std::string& caller_uri = LLStringUtil::null);
 
-	// This removes the panel referenced by the uuid, and then
-	// restores internal consistency. The internal pointer is not
-	// deleted.
-	void removeSession(LLUUID session_id);
+	/**
+	 * Leave the session with session id. Send leave session notification
+	 * to the server and removes all associated session data
+	 * @return false if the session with specified id was not exist
+	 */
+	bool leaveSession(const LLUUID& session_id);
 
 	void inviteToSession(
 		const LLUUID& session_id, 
@@ -295,6 +308,11 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	bool endCall(const LLUUID& session_id);
 
 private:
+	// This removes the panel referenced by the uuid, and then
+	// restores internal consistency. The internal pointer is not
+	// deleted.
+	void removeSession(LLUUID session_id);
+
 	// create a panel and update internal representation for
 	// consistency. Returns the pointer, caller (the class instance
 	// since it is a private method) is not responsible for deleting
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index b539715055d..23f0c7c4503 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1462,6 +1462,39 @@ BOOL LLFolderBridge::copyToClipboard() const
 	return FALSE;
 }
 
+BOOL LLFolderBridge::isClipboardPasteable() const
+{
+	if ( ! LLInvFVBridge::isClipboardPasteable() )
+		return FALSE;
+
+	// Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
+	if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) )
+	{
+		LLInventoryModel* model = getInventoryModel();
+		if ( !model )
+		{
+			return FALSE;
+		}
+
+		LLDynamicArray<LLUUID> objects;
+		LLInventoryClipboard::instance().retrieve(objects);
+		const LLViewerInventoryCategory *current_cat = getCategory();
+
+		// Search for the direct descendent of current Friends subfolder among all pasted items, 
+		// and return false if is found.
+		for(S32 i = objects.count() - 1; i >= 0; --i)
+		{
+			const LLUUID &obj_id = objects.get(i);
+			if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
+			{
+				return FALSE;
+			}
+		}
+
+	}
+	return TRUE;
+}
+
 BOOL LLFolderBridge::isClipboardPasteableAsLink() const
 {
 	// Check normal paste-as-link permissions
@@ -1479,13 +1512,15 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
 	const LLViewerInventoryCategory *current_cat = getCategory();
 	if (current_cat)
 	{
+		const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat );
 		const LLUUID &current_cat_id = current_cat->getUUID();
 		LLDynamicArray<LLUUID> objects;
 		LLInventoryClipboard::instance().retrieve(objects);
 		S32 count = objects.count();
 		for(S32 i = 0; i < count; i++)
 		{
-			const LLInventoryCategory *cat = model->getCategory(objects.get(i));
+			const LLUUID &obj_id = objects.get(i);
+			const LLInventoryCategory *cat = model->getCategory(obj_id);
 			if (cat)
 			{
 				const LLUUID &cat_id = cat->getUUID();
@@ -1496,6 +1531,17 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
 					return FALSE;
 				}
 			}
+			// Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
+			if ( is_in_friend_folder )
+			{
+				// If object is direct descendent of current Friends subfolder than return false.
+				// Note: We can't use 'const LLInventoryCategory *cat', because it may be null
+				// in case type of obj_id is LLInventoryItem.
+				if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
+				{
+					return FALSE;
+				}
+			}
 		}
 	}
 	return TRUE;
@@ -2819,6 +2865,17 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 				break;
 			}
 		}
+
+		if ( is_movable )
+		{
+			// Don't allow creating duplicates in the Calling Card/Friends
+			// subfolders, see bug EXT-1599. Check is item direct descendent
+			// of target folder and forbid item's movement if it so.
+			// Note: isItemDirectDescendentOfCategory checks if
+			// passed category is in the Calling Card/Friends folder
+			is_movable = ! LLFriendCardsManager::instance()
+				.isObjDirectDescendentOfCategory (inv_item, getCategory());
+		}
  
 		LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
 
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index d1d2c57f074..6b2a2d32dec 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -315,6 +315,7 @@ class LLFolderBridge : public LLInvFVBridge
 	virtual BOOL isItemMovable() const ;
 	virtual BOOL isUpToDate() const;
 	virtual BOOL isItemCopyable() const;
+	virtual BOOL isClipboardPasteable() const;
 	virtual BOOL isClipboardPasteableAsLink() const;
 	virtual BOOL copyToClipboard() const;
 	
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index 59b19b6dcb6..4aefbd1a334 100644
--- a/indra/newview/llnearbychathandler.cpp
+++ b/indra/newview/llnearbychathandler.cpp
@@ -225,7 +225,7 @@ void LLNearbyChatScreenChannel::showToastsBottom()
 
 	LLRect	toast_rect;	
 	S32		bottom = getRect().mBottom;
-	S32		margin = gSavedSettings.getS32("ToastMargin");
+	S32		margin = gSavedSettings.getS32("ToastGap");
 
 	for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
 	{
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
index c08f92b983d..7239f49b7f6 100644
--- a/indra/newview/llnotificationtiphandler.cpp
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -91,6 +91,7 @@ bool LLTipHandler::processNotification(const LLSD& notify)
 		LLToast::Params p;
 		p.notif_id = notification->getID();
 		p.notification = notification;
+		p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime");
 		p.panel = notify_box;
 		p.is_tip = true;
 		p.can_be_stored = false;
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 93e58f3441d..f05029582c7 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -458,20 +458,8 @@ void LLLandmarksPanel::initListCommandsHandlers()
 
 void LLLandmarksPanel::updateListCommands()
 {
-	// TODO: should be false when "Received" folder is selected
-	bool add_folder_enabled = mCurrentSelectedList == mLandmarksInventoryPanel;
-	bool trash_enabled = false; // TODO: should be false when "Received" folder is selected
-
-	LLFolderViewItem* current_item = getCurSelectedItem();
-
-	if (current_item)
-	{
-		LLFolderViewEventListener* listenerp = current_item->getListener();
-		if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
-		{
-			trash_enabled = mCurrentSelectedList != mLibraryInventoryPanel;
-		}
-	}
+	bool add_folder_enabled = isActionEnabled("category");
+	bool trash_enabled = isActionEnabled("delete");
 
 	// keep Options & Add Landmark buttons always enabled
 	mListCommands->childSetEnabled(ADD_FOLDER_BUTTON_NAME, add_folder_enabled);
@@ -635,7 +623,13 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 
 	if("category" == command_name)
 	{
-		return mCurrentSelectedList == mLandmarksInventoryPanel; 
+		// we can add folder only in Landmarks Accordion
+		if (mCurrentSelectedList == mLandmarksInventoryPanel)
+		{
+			// ... but except Received folder
+			return !isReceivedFolderSelected();
+		}
+		else return false;
 	}
 	else if("paste" == command_name || "rename" == command_name || "cut" == command_name || "delete" == command_name)
 	{
@@ -650,11 +644,6 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 	{
 		return rootFolderView->getSelectedCount() == 1;
 	}
-	// we can add folder, or change item/folder only in Landmarks Accordion
-	else if ("add_folder" == command_name)
-	{
-		return mLandmarksInventoryPanel == mCurrentSelectedList;
-	}
 	else
 	{
 		llwarns << "Unprocessed command has come: " << command_name << llendl;
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 207ed723b2b..7dd9df674c0 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -60,6 +60,7 @@ class LLTeleportHistoryFlatItem : public LLPanel
 	virtual BOOL postBuild();
 
 	S32 getIndex() { return mIndex; }
+	void setIndex(S32 index) { mIndex = index; }
 	const std::string& getRegionName() { return mRegionName;}
 
 	/*virtual*/ void setValue(const LLSD& value);
@@ -180,7 +181,7 @@ LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu()
 
 	registrar.add("TeleportHistory.Teleport",	boost::bind(&LLTeleportHistoryPanel::ContextMenu::onTeleport, this));
 	registrar.add("TeleportHistory.MoreInformation",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onInfo, this));
-	registrar.add("TeleportHistory.Copy",		boost::bind(&LLTeleportHistoryPanel::ContextMenu::onCopy, this));
+	registrar.add("TeleportHistory.CopyToClipboard",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard, this));
 
 	// create the context menu from the XUI
 	return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
@@ -203,11 +204,11 @@ void LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback(const std::string& sl
 	gClipboard.copyFromString(utf8str_to_wstring(slurl));
 }
 
-void LLTeleportHistoryPanel::ContextMenu::onCopy()
+void LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard()
 {
 	LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[mIndex].mGlobalPos;
 	LLLandmarkActions::getSLURLfromPosGlobal(globalPos,
-		boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1), false);
+		boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1));
 }
 
 // Not yet implemented; need to remove buildPanel() from constructor when we switch
@@ -237,7 +238,7 @@ BOOL LLTeleportHistoryPanel::postBuild()
 	mTeleportHistory = LLTeleportHistoryStorage::getInstance();
 	if (mTeleportHistory)
 	{
-		mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::onTeleportHistoryChange, this));
+		mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::onTeleportHistoryChange, this, _1));
 	}
 
 	mHistoryAccordion = getChild<LLAccordionCtrl>("history_accordion");
@@ -488,7 +489,7 @@ void LLTeleportHistoryPanel::refresh()
 			if (mLastSelectedItemIndex == mCurrentItem)
 				curr_flat_view->selectItem(item, true);
 		}
-			
+
 		mCurrentItem--;
 
 		if (++added_items >= ADD_LIMIT)
@@ -503,10 +504,75 @@ void LLTeleportHistoryPanel::refresh()
 		mDirty = false;
 }
 
-void LLTeleportHistoryPanel::onTeleportHistoryChange()
+void LLTeleportHistoryPanel::onTeleportHistoryChange(S32 removed_index)
 {
 	mLastSelectedItemIndex = -1;
-	showTeleportHistory();
+
+	if (-1 == removed_index)
+		showTeleportHistory(); // recreate all items
+	else
+		replaceItem(removed_index); // replace removed item by most recent
+}
+
+void LLTeleportHistoryPanel::replaceItem(S32 removed_index)
+{
+	// Flat list for 'Today' (mItemContainers keeps accordion tabs in reverse order)
+	LLFlatListView* fv = getFlatListViewFromTab(mItemContainers[mItemContainers.size() - 1]);
+
+	// Empty flat list for 'Today' means that other flat lists are empty as well,
+	// so all items from teleport history should be added.
+	if (!fv || fv->size() == 0)
+	{
+		showTeleportHistory();
+		return;
+	}
+
+	const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems();
+	LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(history_items.size(), // index will be decremented inside loop below
+									&mContextMenu,
+									history_items[history_items.size() - 1].mTitle); // Most recent item, it was
+															 // added instead of removed
+	fv->addItem(item, LLUUID::null, ADD_TOP);
+
+	// Index of each item, from last to removed item should be decremented
+	// to point to the right item in LLTeleportHistoryStorage
+	for (S32 tab_idx = mItemContainers.size() - 1; tab_idx >= 0; --tab_idx)
+	{
+		LLAccordionCtrlTab* tab = mItemContainers.get(tab_idx);
+		if (!tab->getVisible())
+			continue;
+
+		fv = getFlatListViewFromTab(tab);
+		if (!fv)
+		{
+			showTeleportHistory();
+			return;
+		}
+
+		std::vector<LLPanel*> items;
+		fv->getItems(items);
+
+		S32 items_cnt = items.size();
+		for (S32 n = 0; n < items_cnt; ++n)
+		{
+			LLTeleportHistoryFlatItem *item = (LLTeleportHistoryFlatItem*) items[n];
+
+			if (item->getIndex() == removed_index)
+			{
+				fv->removeItem(item);
+
+				// If flat list becames empty, then accordion tab should be hidden
+				if (fv->size() == 0)
+					tab->setVisible(false);
+
+				mHistoryAccordion->arrange();
+
+				return; // No need to decrement idexes for the rest of items
+			}
+
+			item->setIndex(item->getIndex() - 1);
+		}
+	}
 }
 
 void LLTeleportHistoryPanel::showTeleportHistory()
diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h
index 49a97c5022e..7c1b4034324 100644
--- a/indra/newview/llpanelteleporthistory.h
+++ b/indra/newview/llpanelteleporthistory.h
@@ -57,7 +57,7 @@ class LLTeleportHistoryPanel : public LLPanelPlacesTab
 		LLContextMenu* createMenu();
 		void onTeleport();
 		void onInfo();
-		void onCopy();
+		void onCopyToClipboard();
 
 		static void gotSLURLCallback(const std::string& slurl);
 
@@ -90,7 +90,8 @@ class LLTeleportHistoryPanel : public LLPanelPlacesTab
 
 	void refresh();
 	void getNextTab(const LLDate& item_date, S32& curr_tab, LLDate& tab_date);
-	void onTeleportHistoryChange();
+	void onTeleportHistoryChange(S32 removed_index);
+	void replaceItem(S32 removed_index);
 	void showTeleportHistory();
 	void handleItemSelect(LLFlatListView* );
 	LLFlatListView* getFlatListViewFromTab(LLAccordionCtrlTab *);
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
new file mode 100644
index 00000000000..f1e585f285c
--- /dev/null
+++ b/indra/newview/llparticipantlist.cpp
@@ -0,0 +1,56 @@
+/** 
+ * @file llparticipantlist.cpp
+ * @brief LLParticipantList implementing LLSimpleListener listener
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ * 
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llparticipantlist.h"
+#include "llavatarlist.h"
+#include "llfloateractivespeakers.h"
+
+
+LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list):
+	mSpeakerMgr(data_source),
+	mAvatarList(avatar_list)
+{
+	mSpeakerMgr->addListener(this, "add");
+	mSpeakerMgr->addListener(this, "remove");
+	mSpeakerMgr->addListener(this, "clear");
+	std::string str = "test";
+	mAvatarList->setNoItemsCommentText(str);
+
+	//LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
+}
+
+bool LLParticipantList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+	return true;
+}
diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h
new file mode 100644
index 00000000000..2ec563a3560
--- /dev/null
+++ b/indra/newview/llparticipantlist.h
@@ -0,0 +1,48 @@
+/** 
+ * @file llparticipantlist.h
+ * @brief LLParticipantList implementing LLSimpleListener listener
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ * 
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llevent.h"
+
+class LLSpeakerMgr;
+class LLAvatarList;
+
+class LLParticipantList: public LLOldEvents::LLSimpleListener
+{
+	public:
+		LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list);
+		/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+
+	private:
+		LLSpeakerMgr*		mSpeakerMgr;
+		LLAvatarList* 		mAvatarList;
+};
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index a72100a9b3c..816e161f656 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -381,7 +381,7 @@ void LLScreenChannel::showToastsBottom()
 		if(it != mToastList.rbegin())
 		{
 			bottom = (*(it-1)).toast->getRect().mTop;
-			toast_margin = gSavedSettings.getS32("ToastMargin");
+			toast_margin = gSavedSettings.getS32("ToastGap");
 		}
 
 		toast_rect = (*it).toast->getRect();
@@ -394,7 +394,7 @@ void LLScreenChannel::showToastsBottom()
 		{
 			if( it != mToastList.rend()-1)
 			{
-				stop_showing_toasts = ((*it).toast->getRect().mTop + gSavedSettings.getS32("OverflowToastHeight") + gSavedSettings.getS32("ToastMargin")) > getRect().mTop;
+				stop_showing_toasts = ((*it).toast->getRect().mTop + gSavedSettings.getS32("OverflowToastHeight") + gSavedSettings.getS32("ToastGap")) > getRect().mTop;
 			}
 		} 
 
@@ -412,7 +412,7 @@ void LLScreenChannel::showToastsBottom()
 			(*it).toast->stopTimer();
 			mHiddenToastsNum++;
 		}
-		createOverflowToast(bottom, gSavedSettings.getS32("NotificationToastTime"));
+		createOverflowToast(bottom, gSavedSettings.getS32("NotificationToastLifeTime"));
 	}	
 }
 
@@ -426,7 +426,7 @@ void LLScreenChannel::showToastsCentre()
 	for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
 	{
 		toast_rect = (*it).toast->getRect();
-		toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + gSavedSettings.getS32("ToastMargin"), toast_rect.getWidth() ,toast_rect.getHeight());
+		toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + gSavedSettings.getS32("ToastGap"), toast_rect.getWidth() ,toast_rect.getHeight());
 		(*it).toast->setRect(toast_rect);
 
 		(*it).toast->setVisible(TRUE);	
@@ -443,7 +443,7 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer)
 {
 	LLRect toast_rect;
 	LLToast::Params p;
-	p.timer_period = timer;
+	p.lifetime_secs = timer;
 	mOverflowToastPanel = new LLToast(p);
 
 	if(!mOverflowToastPanel)
@@ -465,7 +465,7 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer)
 
 	toast_rect = mOverflowToastPanel->getRect();
 	mOverflowToastPanel->reshape(getRect().getWidth(), toast_rect.getHeight(), true);
-	toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), getRect().getWidth(), toast_rect.getHeight());	
+	toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight());	
 	mOverflowToastPanel->setRect(toast_rect);
 
 	text_box->setValue(text);
@@ -518,7 +518,7 @@ void LLScreenChannel::createStartUpToast(S32 notif_num, S32 bottom, F32 timer)
 {
 	LLRect toast_rect;
 	LLToast::Params p;
-	p.timer_period = timer;
+	p.lifetime_secs = timer;
 	mStartUpToastPanel = new LLToast(p);
 
 	if(!mStartUpToastPanel)
@@ -545,7 +545,7 @@ void LLScreenChannel::createStartUpToast(S32 notif_num, S32 bottom, F32 timer)
 
 	toast_rect = mStartUpToastPanel->getRect();
 	mStartUpToastPanel->reshape(getRect().getWidth(), toast_rect.getHeight(), true);
-	toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), getRect().getWidth(), toast_rect.getHeight());	
+	toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight());	
 	mStartUpToastPanel->setRect(toast_rect);
 
 	text_box->setValue(text);
@@ -703,7 +703,7 @@ void LLScreenChannel::updateShowToastsState()
 		LLRect this_rect = getRect();
 		if(floater->getVisible() && floater->isDocked())
 		{
-			channel_bottom += (floater->getRect().getHeight() + gSavedSettings.getS32("ToastMargin"));
+			channel_bottom += (floater->getRect().getHeight() + gSavedSettings.getS32("ToastGap"));
 		}
 
 		if(channel_bottom != this_rect.mBottom)
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 9729281bacd..86290e66955 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -528,7 +528,7 @@ LLSysWellWindow::RowPanel::~RowPanel()
 //---------------------------------------------------------------------------------
 void LLSysWellWindow::RowPanel::onClosePanel()
 {
-	gIMMgr->removeSession(mChiclet->getSessionId());
+	gIMMgr->leaveSession(mChiclet->getSessionId());
 	// This row panel will be removed from the list in LLSysWellWindow::sessionRemoved().
 }
 
diff --git a/indra/newview/llteleporthistorystorage.cpp b/indra/newview/llteleporthistorystorage.cpp
index a588153ca22..d3bbda1c72c 100644
--- a/indra/newview/llteleporthistorystorage.cpp
+++ b/indra/newview/llteleporthistorystorage.cpp
@@ -93,14 +93,12 @@ void LLTeleportHistoryStorage::onTeleportHistoryChange()
 
 	addItem(item.mTitle, item.mGlobalPos);
 	save();
-
-	mHistoryChangedSignal();
 }
 
 void LLTeleportHistoryStorage::purgeItems()
 {
 	mItems.clear();
-	mHistoryChangedSignal();
+	mHistoryChangedSignal(-1);
 }
 
 void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos)
@@ -116,15 +114,16 @@ bool LLTeleportHistoryStorage::compareByTitleAndGlobalPos(const LLTeleportHistor
 
 void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos, const LLDate& date)
 {
-
 	LLTeleportHistoryPersistentItem item(title, global_pos, date);
 
 	slurl_list_t::iterator item_iter = std::find_if(mItems.begin(), mItems.end(),
 							    boost::bind(&LLTeleportHistoryStorage::compareByTitleAndGlobalPos, this, _1, item));
 
 	// If there is such item already, remove it, since new item is more recent
+	S32 removed_index = -1;
 	if (item_iter != mItems.end())
 	{
+		removed_index = item_iter - mItems.begin();
 		mItems.erase(item_iter);
 	}
 
@@ -141,9 +140,12 @@ void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d
 		// If second to last item is more recent than last, then resort items
 		if (item_iter->mDate > item.mDate)
 		{
+			removed_index = -1;
 			std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate());
 		}
 	}
+
+	mHistoryChangedSignal(removed_index);
 }
 
 void LLTeleportHistoryStorage::removeItem(S32 idx)
@@ -211,6 +213,8 @@ void LLTeleportHistoryStorage::load()
 	file.close();
 
 	std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate());
+
+	mHistoryChangedSignal(-1);
 }
 
 void LLTeleportHistoryStorage::dump() const
@@ -234,7 +238,6 @@ boost::signals2::connection LLTeleportHistoryStorage::setHistoryChangedCallback(
 }
 
 void LLTeleportHistoryStorage::goToItem(S32 idx)
-
 {
 	// Validate specified index.
 	if (idx < 0 || idx >= (S32)mItems.size())
diff --git a/indra/newview/llteleporthistorystorage.h b/indra/newview/llteleporthistorystorage.h
index f67c4e2fb94..2eaa94f2eda 100644
--- a/indra/newview/llteleporthistorystorage.h
+++ b/indra/newview/llteleporthistorystorage.h
@@ -80,8 +80,9 @@ class LLTeleportHistoryStorage: public LLSingleton<LLTeleportHistoryStorage>
 
 	typedef std::vector<LLTeleportHistoryPersistentItem> slurl_list_t;
 
-	typedef boost::function<void()>		history_callback_t;
-	typedef boost::signals2::signal<void()>	history_signal_t;
+	// removed_index is index of removed item, which replaced by more recent
+	typedef boost::function<void(S32 removed_index)>		history_callback_t;
+	typedef boost::signals2::signal<void(S32 removed_index)>	history_signal_t;
 
 	LLTeleportHistoryStorage();
 	~LLTeleportHistoryStorage();
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
index 84931e4d2dc..19f56a5cf0c 100644
--- a/indra/newview/lltoast.cpp
+++ b/indra/newview/lltoast.cpp
@@ -43,7 +43,7 @@ using namespace LLNotificationsUI;
 //--------------------------------------------------------------------------
 LLToast::LLToast(LLToast::Params p) :	LLModalDialog(LLSD(), p.is_modal),
 										mPanel(p.panel), 
-										mTimerValue(p.timer_period),  
+										mToastLifetime(p.lifetime_secs),  
 										mNotificationID(p.notif_id),  
 										mSessionID(p.session_id),
 										mCanFade(p.can_fade),
@@ -103,22 +103,22 @@ void LLToast::setAndStartTimer(F32 period)
 {
 	if(mCanFade)
 	{
-		mTimerValue = period;
+		mToastLifetime = period;
 		mTimer.start();
 	}
 }
 
 //--------------------------------------------------------------------------
-bool LLToast::timerHasExpired()
+bool LLToast::lifetimeHasExpired()
 {
 	if (mTimer.getStarted())
 	{
 		F32 elapsed_time = mTimer.getElapsedTimeF32();
-		if (elapsed_time > gSavedSettings.getS32("ToastOpaqueTime")) 
+		if ((mToastLifetime - elapsed_time) <= gSavedSettings.getS32("ToastOpaqueTime")) 
 		{
 			setBackgroundOpaque(FALSE);
 		}
-		if (elapsed_time > mTimerValue) 
+		if (elapsed_time > mToastLifetime) 
 		{
 			return true;
 		}
@@ -183,7 +183,7 @@ void LLToast::insertPanel(LLPanel* panel)
 //--------------------------------------------------------------------------
 void LLToast::draw()
 {
-	if(timerHasExpired())
+	if(lifetimeHasExpired())
 	{
 		tick();
 	}
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index 29c231a01d9..504b83a6609 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -63,7 +63,7 @@ class LLToast : public LLModalDialog
 		LLUUID				notif_id;	 //notification ID
 		LLUUID				session_id;	 //im session ID
 		LLNotificationPtr	notification;
-		F32					timer_period;
+		F32					lifetime_secs;
 		toast_callback_t	on_delete_toast;
 		toast_callback_t	on_mouse_enter;
 		bool				can_fade;
@@ -82,7 +82,7 @@ class LLToast : public LLModalDialog
 					force_show(false),
 					force_store(false),
 					panel(NULL),
-					timer_period(gSavedSettings.getS32("NotificationToastTime"))
+					lifetime_secs(gSavedSettings.getS32("NotificationToastLifeTime"))
 
 		{};
 	};
@@ -153,7 +153,7 @@ class LLToast : public LLModalDialog
 private:
 
 	// check timer
-	bool	timerHasExpired();
+	bool	lifetimeHasExpired();
 	// on timer finished function
 	void	tick();
 
@@ -161,8 +161,9 @@ class LLToast : public LLModalDialog
 	LLUUID				mSessionID;
 	LLNotificationPtr	mNotification;
 
+	// timer counts a lifetime of a toast
 	LLTimer		mTimer;
-	F32			mTimerValue;
+	F32			mToastLifetime; // in seconds
 
 	LLPanel*	mPanel;
 	LLButton*	mHideBtn;
diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
index 515278c23d4..0160d52b171 100644
--- a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
@@ -17,10 +17,10 @@
          function="TeleportHistory.MoreInformation" />
     </menu_item_call>
     <menu_item_call
-     label="Copy"
+     label="Copy to Clipboard"
      layout="topleft"
-     name="Copy">
+     name="CopyToClipboard">
         <menu_item_call.on_click
-         function="TeleportHistory.Copy" />
+         function="TeleportHistory.CopyToClipboard" />
     </menu_item_call>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 8076b88a655..085b7324730 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -68,6 +68,7 @@ background_visible="true"
             <avatar_list
              follows="all"
              height="470"
+             ignore_online_status="true"
              layout="topleft"
              left="0"
              name="avatar_list"
-- 
GitLab