diff options
| author | Merov Linden <merov@lindenlab.com> | 2012-06-08 10:40:32 -0700 | 
|---|---|---|
| committer | Merov Linden <merov@lindenlab.com> | 2012-06-08 10:40:32 -0700 | 
| commit | b4a53226c8b1b4a31c0f1411b110a0a32fa3599f (patch) | |
| tree | f96c967713d9733f8bc5bae959a53ead40e393af | |
| parent | fa0c34afc6678c9ab1814c81e11c65e4bf3d1317 (diff) | |
| parent | f7f85dd0dda563a9fb49ed65b193a9ea98da9ba2 (diff) | |
Merge pull from richard/viewer-chui
23 files changed, 315 insertions, 179 deletions
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 5e566d6c7c..5ae2df3994 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -95,6 +95,7 @@ LLAssetDictionary::LLAssetDictionary()  	addEntry(LLAssetType::AT_LINK_FOLDER, 		new AssetEntry("FOLDER_LINK",		"link_f", 	"sym folder link",	false,		false,		true));  	addEntry(LLAssetType::AT_MESH,              new AssetEntry("MESH",              "mesh",     "mesh",             false,      false,      false));  	addEntry(LLAssetType::AT_WIDGET,            new AssetEntry("WIDGET",            "widget",   "widget",           false,      false,      false)); +	addEntry(LLAssetType::AT_PERSON,            new AssetEntry("PERSON",            "person",   "person",           false,      false,      false));  	addEntry(LLAssetType::AT_NONE, 				new AssetEntry("NONE",				"-1",		NULL,		  		FALSE,		FALSE,		FALSE));  }; diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index d538accbf7..69b01731e5 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -112,6 +112,9 @@ public:  		AT_WIDGET = 40,  			// UI Widget: this is *not* an inventory asset type, only a viewer side asset (e.g. button, other ui items...) +		AT_PERSON = 45, +			// A user uuid  which is not an inventory asset type, used in viewer only for adding a person to a chat via drag and drop. +  		AT_MESH = 49,  			// Mesh data in our proprietary SLM format diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h index 40b3364b36..efcbe76795 100644 --- a/indra/llcommon/stdenums.h +++ b/indra/llcommon/stdenums.h @@ -51,7 +51,8 @@ enum EDragAndDropType  	DAD_LINK			= 14,  	DAD_MESH            = 15,  	DAD_WIDGET          = 16, -	DAD_COUNT           = 17,   // number of types in this enum +	DAD_PERSON          = 17, +	DAD_COUNT           = 18,   // number of types in this enum  };  // Reasons for drags to be denied. diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index 8282d79b67..8807b36117 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -85,6 +85,7 @@ LLInventoryDictionary::LLInventoryDictionary()  	addEntry(LLInventoryType::IT_GESTURE,             new InventoryEntry("gesture",   "gesture",       1, LLAssetType::AT_GESTURE));   	addEntry(LLInventoryType::IT_MESH,                new InventoryEntry("mesh",      "mesh",          1, LLAssetType::AT_MESH));  	addEntry(LLInventoryType::IT_WIDGET,              new InventoryEntry("widget",    "widget",        1, LLAssetType::AT_WIDGET)); +	addEntry(LLInventoryType::IT_PERSON,              new InventoryEntry("person",    "person",        1, LLAssetType::AT_PERSON));  } @@ -140,7 +141,7 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =  	LLInventoryType::IT_NONE,			// 42	AT_NONE  	LLInventoryType::IT_NONE,			// 43	AT_NONE  	LLInventoryType::IT_NONE,			// 44	AT_NONE -	LLInventoryType::IT_NONE,			// 45	AT_NONE +	LLInventoryType::IT_PERSON,			// 45	AT_PERSON  	LLInventoryType::IT_NONE,			// 46	AT_NONE  	LLInventoryType::IT_NONE,			// 47	AT_NONE  	LLInventoryType::IT_NONE,			// 48	AT_NONE diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index 4d1e0db040..645ebab234 100644 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -63,7 +63,8 @@ public:  		IT_GESTURE = 20,  		IT_MESH = 22,  		IT_WIDGET = 23, -		IT_COUNT = 24, +		IT_PERSON = 24, +		IT_COUNT = 25,  		IT_NONE = -1  	}; diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index c3d560540d..c9031dd26a 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -285,7 +285,7 @@ bool LLAvatarActions::canCall()  }  // static -void LLAvatarActions::startConference(const uuid_vec_t& ids) +void LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUID& floater_id)  {  	// *HACK: Copy into dynamic array  	LLDynamicArray<LLUUID> id_array; @@ -294,7 +294,7 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids)  		id_array.push_back(*it);  	}  	const std::string title = LLTrans::getString("conference-title"); -	LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array); +	LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array, false, floater_id);  	if (session_id != LLUUID::null)  	{  		LLIMFloater::show(session_id); diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index e5dad74fc8..0a69ad86a3 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -86,9 +86,9 @@ public:  	static void startAdhocCall(const uuid_vec_t& ids);  	/** -	 * Start conference chat with the given avatars. +	 * Start conference chat with the given avatars in a specific IM floater.  	 */ -	static void startConference(const uuid_vec_t& ids); +	static void startConference(const uuid_vec_t& ids, const LLUUID& floater_id = LLUUID::null);  	/**  	 * Show avatar profile. diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 30eecfe323..e670d3ea04 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -31,6 +31,7 @@  #include "llavatarlistitem.h"  #include "llbutton.h" +#include "llclipboard.h"  #include "llfloaterreg.h"  #include "lltextutil.h" @@ -38,6 +39,7 @@  #include "llavatarnamecache.h"  #include "llavatariconctrl.h"  #include "lloutputmonitorctrl.h" +#include "lltooldraganddrop.h"  bool LLAvatarListItem::sStaticInitialized = false;  S32 LLAvatarListItem::sLeftPadding = 0; @@ -334,6 +336,62 @@ BOOL LLAvatarListItem::handleDoubleClick(S32 x, S32 y, MASK mask)  	return LLPanel::handleDoubleClick(x, y, mask);  } +BOOL LLAvatarListItem::handleMouseDown(S32 x, S32 y, MASK mask) +{ +	if (LLUICtrl::handleMouseDown(x, y, mask)) +	{ +		return TRUE; +	} + +	gFocusMgr.setMouseCapture(this); + +	S32 screen_x; +	S32 screen_y; +	localPointToScreen(x, y, &screen_x, &screen_y); +	LLToolDragAndDrop::getInstance()->setDragStart(screen_x, screen_y); + +	return TRUE; +} + +BOOL LLAvatarListItem::handleMouseUp( S32 x, S32 y, MASK mask ) +{ +	if (LLUICtrl::childrenHandleMouseUp(x, y, mask)) +	{ +		return TRUE; +	} + +	if(hasMouseCapture()) +	{ +		gFocusMgr.setMouseCapture(NULL); +	} +	return TRUE; +} + +BOOL LLAvatarListItem::handleHover(S32 x, S32 y, MASK mask) +{ +	bool handled = hasMouseCapture(); +	if(handled) +	{ +		S32 screen_x; +		S32 screen_y; +		localPointToScreen(x, y, &screen_x, &screen_y); + +		if(LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y)) +		{ +			// First, create the global drag and drop object +			std::vector<EDragAndDropType> types; +			uuid_vec_t cargo_ids; +			types.push_back(DAD_PERSON); +			cargo_ids.push_back(mAvatarId); +			gClipboard.setSourceObject(mAvatarId, LLAssetType::AT_PERSON); +			LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_PEOPLE; +			LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, src); +		} +	} + +	return handled; +} +  void LLAvatarListItem::setValue( const LLSD& value )  {  	if (!value.isMap()) return;; diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index c95ac39696..28a50870d4 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -112,6 +112,9 @@ public:  	void onProfileBtnClick();  	/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); +	/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); +	/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); +	/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);  protected:  	/** diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index f1bc51fbe7..8701b602ce 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -125,10 +125,12 @@ void LLChicletBar::sessionRemoved(const LLUUID& session_id)  	if(getChicletPanel())  	{  		// IM floater should be closed when session removed and associated chiclet closed -		LLIMFloater* iMfloater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -		if (iMfloater != NULL) +		LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); +		if (im_floater != NULL && !im_floater->getStartConferenceInSameFloater())  		{ -			iMfloater->closeFloater(); +			// Close the IM floater only if we are not planning to close the P2P chat +			// and start a new conference in the same floater. +			im_floater->closeFloater();  		}  		getChicletPanel()->removeChiclet(session_id); diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 708913bbee..c2621938e1 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -83,8 +83,10 @@ BOOL LLIMConversation::postBuild()  	mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this));  	mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); -	mParticipantListPanel->setVisible( -			mIsNearbyChat? false : gSavedSettings.getBOOL("IMShowControlPanel")); + +	// Show the participants list in torn off floaters only. +	mParticipantListPanel->setVisible(gSavedSettings.getBOOL("IMShowControlPanel") +									  && !mIsNearbyChat); // *TODO: temporarily disabled for Nearby chat  	mExpandCollapseBtn->setImageOverlay(  				getString(mParticipantListPanel->getVisible() ? "collapse_icon" : "expand_icon"));  	mExpandCollapseBtn->setEnabled(!mIsP2PChat); @@ -209,12 +211,10 @@ void LLIMConversation::updateHeaderAndToolbar()  	}  	bool is_control_panel_visible = false; -	if (!mIsP2PChat) -	{  		// Control panel should be visible only in torn off floaters.  		is_control_panel_visible = !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel"); -		mParticipantListPanel->setVisible(is_control_panel_visible); -	} +		mParticipantListPanel->setVisible(!mIsP2PChat && is_control_panel_visible +				&& !mIsNearbyChat); // *TODO: temporarily disabled for Nearby chat  	// Display collapse image (<<) if the floater is hosted  	// or if it is torn off but has an open control panel. diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index c99da9e9c1..dcd19b5856 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -33,12 +33,14 @@  #include "llagent.h"  #include "llappviewer.h" +#include "llavataractions.h"  #include "llavatarnamecache.h"  #include "llbutton.h"  #include "llchannelmanager.h"  #include "llchiclet.h"  #include "llchicletbar.h"  #include "llfloaterreg.h" +#include "llfloateravatarpicker.h"  #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container  #include "llinventoryfunctions.h"  //#include "lllayoutstack.h" @@ -71,18 +73,12 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)  	mTypingTimer(),  	mTypingTimeoutTimer(),  	mPositioned(false), -	mSessionInitialized(false) +	mSessionInitialized(false), +	mStartConferenceInSameFloater(false)  {  	mIsNearbyChat = false; +	initIMSession(session_id); -	mSession = LLIMModel::getInstance()->findIMSession(mSessionID); - -	if (mSession) -	{ -		mIsP2PChat = mSession->isP2PSessionType(); -		mSessionInitialized = mSession->mSessionInitialized; -		mDialog = mSession->mType; -	}  	setOverlapsScreenChannel(true);  	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); @@ -112,6 +108,29 @@ void LLIMFloater::onFocusReceived()  // virtual  void LLIMFloater::onClose(bool app_quitting)  { +	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( +				mSessionID); + +	if (session == NULL) +	{ +		llwarns << "Empty session." << llendl; +		return; +	} + +	bool is_call_with_chat = session->isGroupSessionType() +			|| session->isAdHocSessionType() || session->isP2PSessionType(); + +	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + +	if (is_call_with_chat && voice_channel != NULL +			&& voice_channel->isActive()) +	{ +		LLSD payload; +		payload["session_id"] = mSessionID; +		LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); +		return; +	} +  	setTyping(false);  	// The source of much argument and design thrashing @@ -211,8 +230,24 @@ LLIMFloater::~LLIMFloater()  	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);  } -//virtual -BOOL LLIMFloater::postBuild() +void LLIMFloater::initIMSession(const LLUUID& session_id) +{ +	// Change the floater key to bind it to a new session. +	setKey(session_id); + +	mSessionID = session_id; +	mSession = LLIMModel::getInstance()->findIMSession(mSessionID); + +	if (mSession) +	{ +		mIsP2PChat = mSession->isP2PSessionType(); +		mSessionInitialized = mSession->mSessionInitialized; + +		mDialog = mSession->mType; +	} +} + +void LLIMFloater::initIMFloater()  {  	const LLUUID& other_party_id =  			LLIMModel::getInstance()->getOtherParticipantID(mSessionID); @@ -223,6 +258,34 @@ BOOL LLIMFloater::postBuild()  	boundVoiceChannel(); +	// Show control panel in torn off floaters only. +	mParticipantListPanel->setVisible(!getHost() && gSavedSettings.getBOOL("IMShowControlPanel")); + +	// Disable input editor if session cannot accept text +	if ( mSession && !mSession->mTextIMPossible ) +	{ +		mInputEditor->setEnabled(FALSE); +		mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label")); +	} + +	if (mIsP2PChat) +	{ +		// look up display name for window title +		LLAvatarNameCache::get(mSession->mOtherParticipantID, +							   boost::bind(&LLIMFloater::onAvatarNameCache, +										   this, _1, _2)); +	} +	else +	{ +		std::string session_name(LLIMModel::instance().getName(mSessionID)); +		updateSessionName(session_name, session_name); +	} +} + +//virtual +BOOL LLIMFloater::postBuild() +{ +	LLIMConversation::postBuild();  	mInputEditor = getChild<LLLineEditor>("chat_editor");  	mInputEditor->setMaxTextLength(1023); @@ -248,26 +311,12 @@ BOOL LLIMFloater::postBuild()  	mTypingStart = LLTrans::getString("IM_typing_start_string"); -	// Disable input editor if session cannot accept text -	if ( mSession && !mSession->mTextIMPossible ) -	{ -		mInputEditor->setEnabled(FALSE); -		mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label")); -	} +	LLButton* add_btn = getChild<LLButton>("add_btn"); + +	// Allow to add chat participants depending on the session type +	add_btn->setEnabled(isInviteAllowed()); +	add_btn->setClickedCallback(boost::bind(&LLIMFloater::onAddButtonClicked, this)); -	if (mIsP2PChat) -	{ -		// look up display name for window title -		LLAvatarNameCache::get(mSession->mOtherParticipantID, -							   boost::bind(&LLIMFloater::onAvatarNameCache, -										   this, _1, _2)); -	} -	else -	{ -		std::string session_name(LLIMModel::instance().getName(mSessionID)); -		updateSessionName(session_name, session_name); -	} -	  	childSetAction("voice_call_btn", boost::bind(&LLIMFloater::onCallButtonClicked, this));  	LLVoiceClient::getInstance()->addObserver(this); @@ -275,7 +324,75 @@ BOOL LLIMFloater::postBuild()  	//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"  	//see LLFloaterIMPanel for how it is done (IB) -	return LLIMConversation::postBuild(); +	initIMFloater(); + +	return TRUE; +} + +void LLIMFloater::onAddButtonClicked() +{ +       LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::onAvatarPicked, this, _1, _2), TRUE, TRUE); +       if (!picker) +       { +               return; +       } + +       // Need to disable 'ok' button when selected users are already in conversation. +       picker->setOkBtnEnableCb(boost::bind(&LLIMFloater::canAddSelectedToChat, this, _1)); +       LLFloater* root_floater = gFloaterView->getParentFloater(this); +       if (root_floater) +       { +               root_floater->addDependentFloater(picker); +       } +} + +void LLIMFloater::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names) +{ +       if (mIsP2PChat) +       { +               mStartConferenceInSameFloater = true; +               onClose(false); + +               uuid_vec_t temp_ids; +               temp_ids.push_back(mOtherParticipantUUID); +               temp_ids.insert(temp_ids.end(), ids.begin(), ids.end()); + +               LLAvatarActions::startConference(temp_ids, mSessionID); +       } +       else +       { +               inviteToSession(ids); +       } +} + +bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) +{ +       if (!mSession +               || mDialog == IM_SESSION_GROUP_START +               || mDialog == IM_SESSION_INVITE && gAgent.isInGroup(mSessionID)) +       { +               return false; +       } + +       for (uuid_vec_t::const_iterator id = uuids.begin(); +                       id != uuids.end(); ++id) +       { +               if (*id == mOtherParticipantUUID) +               { +                       return false; +               } + +               for (uuid_vec_t::const_iterator target_id = mSession->mInitialTargetIDs.begin(); +                               target_id != mSession->mInitialTargetIDs.end(); ++target_id) +               { +                       if (*id == *target_id) +                       { +                               return false; +                       } +               } +       } + +       return true;  }  void LLIMFloater::boundVoiceChannel() @@ -603,17 +720,15 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)  	//will be different only for an ad-hoc im session  	if (mSessionID != im_session_id)  	{ -		mSessionID = im_session_id; -		setKey(im_session_id); +		initIMSession(im_session_id);  		boundVoiceChannel(); -		mSession = LLIMModel::getInstance()->findIMSession(mSessionID); -		mIsP2PChat = mSession && mSession->isP2PSessionType(); -  		buildParticipantList();  	} -	 + +	initIMFloater(); +  	//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB)  	//need to send delayed messaged collected while waiting for session initialization @@ -876,96 +991,62 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update)  	}  } -BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, -		BOOL drop, EDragAndDropType cargo_type, -		void *cargo_data, EAcceptance *accept, -		std::string& tooltip_msg) +// virtual +BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +									EDragAndDropType cargo_type, +									void* cargo_data, +									EAcceptance* accept, +									std::string& tooltip_msg)  { -	if (mDialog == IM_NOTHING_SPECIAL) -	{ -		LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, -				cargo_type, cargo_data, accept); -	} - -	// handle case for dropping calling cards (and folders of calling cards) onto invitation panel for invites -	else if (isInviteAllowed()) +	if (cargo_type == DAD_PERSON)  	{ -		*accept = ACCEPT_NO; - -		if (cargo_type == DAD_CALLINGCARD) +		if (dropPerson(static_cast<LLInventoryObject*>(cargo_data), drop))  		{ -			if (dropCallingCard((LLInventoryItem*) cargo_data, drop)) -			{ -				*accept = ACCEPT_YES_MULTI; -			} +			*accept = ACCEPT_YES_MULTI;  		} -		else if (cargo_type == DAD_CATEGORY) +		else  		{ -			if (dropCategory((LLInventoryCategory*) cargo_data, drop)) -			{ -				*accept = ACCEPT_YES_MULTI; -			} +			*accept = ACCEPT_NO;  		}  	}  	return TRUE;  } -BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop) +bool LLIMFloater::dropPerson(LLInventoryObject* item, bool drop)  { -	BOOL rv = isInviteAllowed(); -	if (rv && item && item->getCreatorUUID().notNull()) -	{ -		if (drop) -		{ -			uuid_vec_t ids; -			ids.push_back(item->getCreatorUUID()); -			inviteToSession(ids); -		} -	} -	else +	bool res = item && item->getUUID().notNull(); +	if(res)  	{ -		// set to false if creator uuid is null. -		rv = FALSE; -	} -	return rv; -} +		uuid_vec_t ids; +		ids.push_back(item->getUUID()); -BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop) -{ -	BOOL rv = isInviteAllowed(); -	if (rv && category) -	{ -		LLInventoryModel::cat_array_t cats; -		LLInventoryModel::item_array_t items; -		LLUniqueBuddyCollector buddies; -		gInventory.collectDescendentsIf(category->getUUID(), -				cats, -				items, -				LLInventoryModel::EXCLUDE_TRASH, -				buddies); -		S32 count = items.count(); -		if (count == 0) -		{ -			rv = FALSE; -		} -		else if (drop) +		res = canAddSelectedToChat(ids); +		if(res && drop)  		{ -			uuid_vec_t ids; -			ids.reserve(count); -			for (S32 i = 0; i < count; ++i) +			if (mIsP2PChat)  			{ -				ids.push_back(items.get(i)->getCreatorUUID()); +				mStartConferenceInSameFloater = true; +				onClose(false); + +				ids.push_back(mOtherParticipantUUID); + +				LLAvatarActions::startConference(ids, mSessionID); +			} +			else +			{ +				inviteToSession(ids);  			} -			inviteToSession(ids);  		}  	} -	return rv; + +	return res;  }  BOOL LLIMFloater::isInviteAllowed() const  {  	return ((IM_SESSION_CONFERENCE_START == mDialog) -			|| (IM_SESSION_INVITE == mDialog)); +			 || (IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) +			 || mIsP2PChat);  }  class LLSessionInviteResponder: public LLHTTPClient::Responder @@ -1107,14 +1188,6 @@ void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD&  }  // static -void LLIMFloater::initIMFloater() -{ -	// This is called on viewer start up -	// init chat window type before user changed it in preferences -	isChatMultiTab(); -} - -//static  void LLIMFloater::sRemoveTypingIndicator(const LLSD& data)  {  	LLUUID session_id = data["session_id"]; @@ -1139,7 +1212,6 @@ void LLIMFloater::onIMChicletCreated( const LLUUID& session_id )  {  	LLIMFloater::addToHost(session_id);  } -  void LLIMFloater::addToHost(const LLUUID& session_id)  {  	if (LLIMConversation::isChatMultiTab()) @@ -1157,32 +1229,3 @@ void LLIMFloater::addToHost(const LLUUID& session_id)  		}  	}  } - -void	LLIMFloater::onClickCloseBtn() -{ - -	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( -			mSessionID); - -	if (session == NULL) -	{ -		llwarns << "Empty session." << llendl; -		return; -	} - -	bool is_call_with_chat = session->isGroupSessionType() -			|| session->isAdHocSessionType() || session->isP2PSessionType(); - -	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - -	if (is_call_with_chat && voice_channel != NULL -			&& voice_channel->isActive()) -	{ -		LLSD payload; -		payload["session_id"] = mSessionID; -		LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); -		return; -	} - -	LLFloater::onClickCloseBtn(); -} diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 24f28c8aee..b02f779637 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -56,6 +56,9 @@ public:  	virtual ~LLIMFloater(); +	void initIMSession(const LLUUID& session_id); +	void initIMFloater(); +  	// LLView overrides  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void setVisible(BOOL visible); @@ -111,20 +114,18 @@ public:  	void processAgentListUpdates(const LLSD& body);  	void processSessionUpdate(const LLSD& session_update); -	BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, -			BOOL drop, EDragAndDropType cargo_type, -			void *cargo_data, EAcceptance *accept, -			std::string& tooltip_msg); - +	/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +									   EDragAndDropType cargo_type, +									   void* cargo_data, +									   EAcceptance* accept, +									   std::string& tooltip_msg); -	static void initIMFloater();  	//used as a callback on receiving new IM message  	static void sRemoveTypingIndicator(const LLSD& data);  	static void onIMChicletCreated(const LLUUID& session_id); -protected: -	/* virtual */ void onClickCloseBtn(); +	bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; }  private:  	// process focus events to set a currently active session @@ -137,8 +138,7 @@ private:  	// For display name lookups for IM window titles  	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); -	BOOL dropCallingCard(LLInventoryItem* item, BOOL drop); -	BOOL dropCategory(LLInventoryCategory* category, BOOL drop); +	bool dropPerson(LLInventoryObject* item, bool drop);  	BOOL isInviteAllowed() const;  	BOOL inviteToSession(const uuid_vec_t& agent_ids); @@ -147,6 +147,10 @@ private:  	static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata);  	static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata);  	void setTyping(bool typing); +	void onAddButtonClicked(); +	void onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names); +	bool canAddSelectedToChat(const uuid_vec_t& uuids); +  	void onCallButtonClicked();  	// set the enable/disable state for the Call button @@ -186,6 +190,8 @@ private:  	bool mSessionInitialized;  	LLSD mQueuedMsgsForInit; +	bool mStartConferenceInSameFloater; +  	// connection to voice channel state change signal  	boost::signals2::connection mVoiceChannelStateChangeConnection;  }; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 46b1cb5f18..0d2b1f06b5 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2591,7 +2591,8 @@ LLUUID LLIMMgr::addSession(  	const std::string& name,  	EInstantMessage dialog,  	const LLUUID& other_participant_id, -	const LLDynamicArray<LLUUID>& ids, bool voice) +	const LLDynamicArray<LLUUID>& ids, bool voice, +	const LLUUID& floater_id)  {  	if (0 == ids.getLength())  	{ @@ -2606,6 +2607,18 @@ LLUUID LLIMMgr::addSession(  	LLUUID session_id = computeSessionID(dialog,other_participant_id); +	if (floater_id.notNull()) +	{ +		LLIMFloater* im_floater = LLIMFloater::findInstance(floater_id); +		if (im_floater && im_floater->getStartConferenceInSameFloater()) +		{ +			// The IM floater should be initialized with a new session_id +			// so that it is found by that id when creating a chiclet in LLIMFloater::onIMChicletCreated, +			// and a new floater is not created. +			im_floater->initIMSession(session_id); +		} +	} +  	bool new_session = !LLIMModel::getInstance()->findIMSession(session_id);  	//works only for outgoing ad-hoc sessions diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 9d19af4b62..58a2ac5162 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -347,10 +347,12 @@ public:  	// Adds a session using a specific group of starting agents  	// the dialog type is assumed correct. Returns the uuid of the session. +	// A session can be added to a floater specified by floater_id.  	LLUUID addSession(const std::string& name,  					  EInstantMessage dialog,  					  const LLUUID& other_participant_id, -					  const LLDynamicArray<LLUUID>& ids, bool voice = false); +					  const LLDynamicArray<LLUUID>& ids, bool voice = false, +					  const LLUUID& floater_id = LLUUID::null);  	/**  	 * Creates a P2P session with the requisite handle for responding to voice calls. diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 8b54c6ce53..e35dbf21d4 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -130,6 +130,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& key)  	mSpeakerMgr(NULL),  	mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT)  { +	mIsNearbyChat = true;  	mSpeakerMgr = LLLocalSpeakerMgr::getInstance();  } diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index c84790d839..ac2109dda4 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -81,7 +81,7 @@ LLContextMenu* NearbyMenu::createMenu()  		// Set up for multi-selected People  		// registrar.add("Avatar.AddFriend",	boost::bind(&LLAvatarActions::requestFriendshipDialog,	mUUIDs)); // *TODO: unimplemented -		registrar.add("Avatar.IM",			boost::bind(&LLAvatarActions::startConference,			mUUIDs)); +		registrar.add("Avatar.IM",			boost::bind(&LLAvatarActions::startConference,			mUUIDs, LLUUID::null));  		registrar.add("Avatar.Call",		boost::bind(&LLAvatarActions::startAdhocCall,			mUUIDs));  		registrar.add("Avatar.OfferTeleport",	boost::bind(&NearbyMenu::offerTeleport,					this));  		registrar.add("Avatar.RemoveFriend",boost::bind(&LLAvatarActions::removeFriendsDialog,		mUUIDs)); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 2f13ba5ab1..320a602916 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2153,7 +2153,6 @@ bool idle_startup()  		LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); -		LLIMFloater::initIMFloater();  		display_startup();  		return TRUE; diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp index 81ad96f39e..2b5acdc1e8 100644 --- a/indra/newview/lltoolbarview.cpp +++ b/indra/newview/lltoolbarview.cpp @@ -603,7 +603,7 @@ BOOL LLToolBarView::handleDragTool( S32 x, S32 y, const LLUUID& uuid, LLAssetTyp  BOOL LLToolBarView::handleDropTool( void* cargo_data, S32 x, S32 y, LLToolBar* toolbar)  {  	BOOL handled = FALSE; -	LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; +	LLInventoryObject* inv_item = static_cast<LLInventoryObject*>(cargo_data);  	LLAssetType::EType type = inv_item->getType();  	if (type == LLAssetType::AT_WIDGET) diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 4f4eef0f3d..296ded6831 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -2527,7 +2527,7 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory(  			item = (LLViewerInventoryItem*)preview->getDragItem();  		}  	} -	else if(mSource == SOURCE_VIEWER) +	else if(mSource == SOURCE_VIEWER || mSource == SOURCE_PEOPLE)  	{  		item = (LLViewerInventoryItem*)gToolBarView->getDragItem();  	} diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 245c2a23e6..44980ffdb3 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -67,7 +67,8 @@ public:  		SOURCE_WORLD,  		SOURCE_NOTECARD,  		SOURCE_LIBRARY, -		SOURCE_VIEWER +		SOURCE_VIEWER, +		SOURCE_PEOPLE  	};  	void beginDrag(EDragAndDropType type, diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp index a4b1c2155f..08ba5a5f25 100644 --- a/indra/newview/llviewerassettype.cpp +++ b/indra/newview/llviewerassettype.cpp @@ -83,6 +83,8 @@ LLViewerAssetDictionary::LLViewerAssetDictionary()  	addEntry(LLViewerAssetType::AT_WIDGET, 				new ViewerAssetEntry(DAD_WIDGET)); +	addEntry(LLViewerAssetType::AT_PERSON, 				new ViewerAssetEntry(DAD_PERSON)); +  	addEntry(LLViewerAssetType::AT_NONE, 				new ViewerAssetEntry(DAD_NONE));  }; 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 beeb4eea9b..21fc2d25d4 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -59,6 +59,7 @@                   top="5"                   width="31" />               <button +                 enabled="false"                   follows="top|left"                   height="25"                   image_hover_unselected="Toolbar_Middle_Over" @@ -69,8 +70,7 @@                   top="5"                   left_pad="4"                   name="add_btn" -                 width="31"> -             </button>    +                 width="31"/>               <button                   follows="top|left"                   height="25" @@ -82,8 +82,7 @@                   top="5"                   left_pad="4"                   name="voice_call_btn" -                 width="31"> -             </button> +                 width="31"/>               <button                   follows="right|top"                   height="25"  | 
