diff options
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" |