diff options
Diffstat (limited to 'indra/newview')
81 files changed, 2211 insertions, 1594 deletions
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 5aaf9d0097..a692ef6a3e 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2880,7 +2880,7 @@ void LLAgent::endAnimationUpdateUI() mCameraLag.clearVec(); // JC - Added for always chat in third person option - gFocusMgr.setKeyboardFocus(NULL, NULL); + gFocusMgr.setKeyboardFocus(NULL); gToolMgr->setCurrentToolset(gMouselookToolset); @@ -4004,7 +4004,7 @@ void LLAgent::changeCameraToMouselook(BOOL animate) if( mCameraMode != CAMERA_MODE_MOUSELOOK ) { - gViewerWindow->setKeyboardFocus( NULL, NULL ); + gViewerWindow->setKeyboardFocus( NULL ); mLastCameraMode = mCameraMode; mCameraMode = CAMERA_MODE_MOUSELOOK; @@ -4225,7 +4225,7 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL animate) mbFlagsDirty = TRUE; } - gViewerWindow->setKeyboardFocus( NULL, NULL ); + gViewerWindow->setKeyboardFocus( NULL ); gViewerWindow->setMouseCapture( NULL ); LLVOAvatar::onCustomizeStart(); @@ -5225,6 +5225,102 @@ void LLAgent::processAgentDropGroup(LLMessageSystem *msg, void **) } } +class LLAgentDropGroupViewerNode : public LLHTTPNode +{ + virtual void post( + LLHTTPNode::ResponsePtr response, + const LLSD& context, + const LLSD& input) const + { + + if ( + !input.isMap() || + !input.has("body") ) + { + //what to do with badly formed message? + response->status(400); + response->result(LLSD("Invalid message parameters")); + } + + LLSD body = input["body"]; + if ( body.has("body") ) + { + //stupid message system doubles up the "body"s + body = body["body"]; + } + + if ( + body.has("AgentData") && + body["AgentData"].isArray() && + body["AgentData"][0].isMap() ) + { + llinfos << "VALID DROP GROUP" << llendl; + + //there is only one set of data in the AgentData block + LLSD agent_data = body["AgentData"][0]; + LLUUID agent_id; + LLUUID group_id; + + agent_id = agent_data["AgentID"].asUUID(); + group_id = agent_data["GroupID"].asUUID(); + + if (agent_id != gAgentID) + { + llwarns + << "AgentDropGroup for agent other than me" << llendl; + + response->notFound(); + return; + } + + // Remove the group if it already exists remove it + // and add the new data to pick up changes. + LLGroupData gd; + gd.mID = group_id; + S32 index = gAgent.mGroups.find(gd); + if (index != -1) + { + gAgent.mGroups.remove(index); + if (gAgent.getGroupID() == group_id) + { + gAgent.mGroupID.setNull(); + gAgent.mGroupPowers = 0; + gAgent.mGroupName[0] = '\0'; + gAgent.mGroupTitle[0] = '\0'; + } + + // refresh all group information + gAgent.sendAgentDataUpdateRequest(); + + gGroupMgr->clearGroupData(group_id); + // close the floater for this group, if any. + LLFloaterGroupInfo::closeGroup(group_id); + // refresh the group panel of the search window, + //if necessary. + LLFloaterDirectory::refreshGroup(group_id); + } + else + { + llwarns + << "AgentDropGroup, agent is not part of group " + << group_id << llendl; + } + + response->result(LLSD()); + } + else + { + //what to do with badly formed message? + response->status(400); + response->result(LLSD("Invalid message parameters")); + } + } +}; + +LLHTTPRegistration<LLAgentDropGroupViewerNode> + gHTTPRegistrationAgentDropGroupViewerNode( + "/message/AgentDropGroup"); + // static void LLAgent::processAgentGroupDataUpdate(LLMessageSystem *msg, void **) { diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ad934abfa7..8b126b7597 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -425,7 +425,7 @@ static void ui_audio_callback(const LLUUID& uuid) { if (gAudiop) { - F32 volume = gSavedSettings.getF32("AudioLevelUI"); + F32 volume = gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI"); gAudiop->triggerSound(uuid, gAgent.getID(), volume); } } diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index c3c892a572..76cfe92c4c 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -252,7 +252,6 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) if(view) { LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); - LLFocusMgr::FocusLostCallback callback = gFocusMgr.getFocusCallback(); view->getPanel()->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO); if((LLAssetType::AT_TEXTURE == asset_type) @@ -262,7 +261,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) } //LLInventoryView::dumpSelectionInformation((void*)view); // restore keyboard focus - gFocusMgr.setKeyboardFocus(focus_ctrl, callback); + gFocusMgr.setKeyboardFocus(focus_ctrl); } } else diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 3517c1e18a..78365e66f1 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -93,51 +93,20 @@ private: // Functions // -//inline constructor -// for chat bars embedded in floaters, etc -LLChatBar::LLChatBar(const std::string& name) -: LLPanel(name, LLRect(), BORDER_NO), +LLChatBar::LLChatBar() +: LLPanel("", LLRect(), BORDER_NO), mInputEditor(NULL), mGestureLabelTimer(), mLastSpecialChatChannel(0), mIsBuilt(FALSE), - mDynamicLayout(FALSE), - mGestureCombo(NULL), - mObserver(NULL) -{ -} - -LLChatBar::LLChatBar(const std::string& name, const LLRect& rect) -: LLPanel(name, rect, BORDER_NO), - mInputEditor(NULL), - mGestureLabelTimer(), - mLastSpecialChatChannel(0), - mIsBuilt(FALSE), - mDynamicLayout(TRUE), mGestureCombo(NULL), mObserver(NULL) { setIsChrome(TRUE); - gUICtrlFactory->buildPanel(this,"panel_chat_bar.xml"); - - mIsFocusRoot = TRUE; - - setRect(rect); // override xml rect - - setBackgroundOpaque(TRUE); - setBackgroundVisible(TRUE); - - // Start visible if we left the app while chatting. - setVisible( gSavedSettings.getBOOL("ChatVisible") ); - - // Apply custom layout. - layout(); - -#if !LL_RELEASE_FOR_DOWNLOAD + #if !LL_RELEASE_FOR_DOWNLOAD childDisplayNotFound(); #endif - } @@ -151,25 +120,18 @@ LLChatBar::~LLChatBar() BOOL LLChatBar::postBuild() { childSetAction("History", toggleChatHistory, this); - childSetAction("Say", onClickSay, this); - childSetAction("Shout", onClickShout, this); + childSetCommitCallback("Say", onClickSay, this); // attempt to bind to an existing combo box named gesture setGestureCombo(LLUICtrlFactory::getComboBoxByName(this, "Gesture")); - LLButton * sayp = static_cast<LLButton*>(getChildByName("Say", TRUE)); - if(sayp) - { - setDefaultBtn(sayp); - } - mInputEditor = LLUICtrlFactory::getLineEditorByName(this, "Chat Editor"); if (mInputEditor) { mInputEditor->setCallbackUserData(this); mInputEditor->setKeystrokeCallback(&onInputEditorKeystroke); - mInputEditor->setFocusLostCallback(&onInputEditorFocusLost); - mInputEditor->setFocusReceivedCallback( &onInputEditorGainFocus ); + mInputEditor->setFocusLostCallback(&onInputEditorFocusLost, this); + mInputEditor->setFocusReceivedCallback( &onInputEditorGainFocus, this ); mInputEditor->setCommitOnFocusLost( FALSE ); mInputEditor->setRevertOnEsc( FALSE ); mInputEditor->setIgnoreTab(TRUE); @@ -189,16 +151,6 @@ BOOL LLChatBar::postBuild() //----------------------------------------------------------------------- // virtual -void LLChatBar::reshape(S32 width, S32 height, BOOL called_from_parent) -{ - LLPanel::reshape(width, height, called_from_parent); - if (mIsBuilt) - { - layout(); - } -} - -// virtual BOOL LLChatBar::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent ) { BOOL handled = FALSE; @@ -208,13 +160,6 @@ BOOL LLChatBar::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent ) // ALT-RETURN is reserved for windowed/fullscreen toggle if( KEY_RETURN == key ) { - //if (childGetValue("Chat Editor").asString().empty()) - //{ - // // no text, just close chat bar - // stopChat(); - // return TRUE; - //} - if (mask == MASK_CONTROL) { // shout @@ -239,78 +184,8 @@ BOOL LLChatBar::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent ) return handled; } - -void LLChatBar::layout() -{ - if (!mDynamicLayout) return; - - S32 rect_width = mRect.getWidth(); - S32 count = 9; // number of elements in LLToolBar - S32 pad = 4; - - LLRect gesture_rect; - S32 gesture_width = 0; - if (childGetRect("Gesture", gesture_rect)) - { - gesture_width = gesture_rect.getWidth(); - } - F32 segment_width = (F32)(rect_width - (pad + gesture_width)) / (F32)count; - - S32 btn_width = lltrunc(segment_width-pad); - - S32 x = 0; - S32 y = 1; - LLRect r; - - x = llround(0 * segment_width); - r.setOriginAndSize(x, y, btn_width, BTN_HEIGHT); - childSetRect("History", r); - - x = llround(1 * segment_width); - // Hack this one up so it looks nice. - if (mInputEditor) - { - r.setOriginAndSize(x, y+2, llfloor(6*segment_width-pad), 18); - mInputEditor->reshape(r.getWidth(), r.getHeight(), TRUE); - mInputEditor->setRect(r); - } - - x = llround(7 * segment_width); - r.setOriginAndSize(x, y, btn_width, BTN_HEIGHT); - childSetRect("Say", r); - - x = llround(8 * segment_width); - r.setOriginAndSize(x, y, btn_width, BTN_HEIGHT); - childSetRect("Shout", r); - - x = rect_width - (pad + gesture_width); - r.setOriginAndSize(x, y, gesture_width, BTN_HEIGHT); - childSetRect("Gesture", r); -} - - void LLChatBar::refresh() { - //BOOL chat_mode = gSavedSettings.getBOOL("ChatVisible"); - - //// Grab focus when no one else has it, and we're in chat mode. - //if (!gFocusMgr.getKeyboardFocus() - // && chat_mode) - //{ - // childSetFocus("Chat Editor", TRUE); - //} - - // Only show this view when user wants to be chatting - //setVisible(chat_mode); - - // hide in mouselook, but keep previous visibility state - //BOOL mouselook = gAgent.cameraMouselook(); - // call superclass setVisible so that we don't overwrite the saved setting - if (mDynamicLayout) - { - LLPanel::setVisible(gSavedSettings.getBOOL("ChatVisible")); - } - // HACK: Leave the name of the gesture in place for a few seconds. const F32 SHOW_GESTURE_NAME_TIME = 2.f; if (mGestureLabelTimer.getStarted() && mGestureLabelTimer.getElapsedTimeF32() > SHOW_GESTURE_NAME_TIME) @@ -584,12 +459,7 @@ void LLChatBar::stopChat() // hide chat bar so it doesn't grab focus back gChatBar->setVisible(FALSE); -} - -void LLChatBar::setVisible(BOOL visible) -{ - gSavedSettings.setBOOL("ChatVisible", visible); - LLPanel::setVisible(visible); + gSavedSettings.setBOOL("ChatVisible", FALSE); } // static @@ -663,30 +533,30 @@ void LLChatBar::onInputEditorKeystroke( LLLineEditor* caller, void* userdata ) } // static -void LLChatBar::onInputEditorFocusLost( LLUICtrl* caller, void* userdata) +void LLChatBar::onInputEditorFocusLost( LLFocusableElement* caller, void* userdata) { // stop typing animation gAgent.stopTyping(); } // static -void LLChatBar::onInputEditorGainFocus( LLUICtrl* caller, void* userdata ) +void LLChatBar::onInputEditorGainFocus( LLFocusableElement* caller, void* userdata ) { LLFloaterChat::setHistoryCursorAndScrollToEnd(); } // static -void LLChatBar::onClickSay( void* userdata ) +void LLChatBar::onClickSay( LLUICtrl* ctrl, void* userdata ) { LLChatBar* self = (LLChatBar*) userdata; - self->sendChat( CHAT_TYPE_NORMAL ); -} - -// static -void LLChatBar::onClickShout( void* userdata ) -{ - LLChatBar *self = (LLChatBar *)userdata; - self->sendChat( CHAT_TYPE_SHOUT ); + if (ctrl->getValue().asString() == "shout") + { + self->sendChat( CHAT_TYPE_SHOUT ); + } + else + { + self->sendChat( CHAT_TYPE_NORMAL ); + } } void LLChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) diff --git a/indra/newview/llchatbar.h b/indra/newview/llchatbar.h index 76a80125ae..f198574dcd 100644 --- a/indra/newview/llchatbar.h +++ b/indra/newview/llchatbar.h @@ -49,17 +49,12 @@ class LLChatBar { public: // constructor for inline chat-bars (e.g. hosted in chat history window) - LLChatBar(const std::string& name); - LLChatBar(const std::string& name, const LLRect& rect); + LLChatBar(); ~LLChatBar(); virtual BOOL postBuild(); - virtual void reshape(S32 width, S32 height, BOOL called_from_parent); virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent); - // Adjust buttons and input field for width - void layout(); - void refresh(); void refreshGestures(); @@ -86,20 +81,18 @@ public: LLWString stripChannelNumber(const LLWString &mesg, S32* channel); // callbacks - static void onClickSay( void* userdata ); - static void onClickShout( void* userdata ); + static void onClickSay( LLUICtrl*, void* userdata ); static void onTabClick( void* userdata ); static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); - static void onInputEditorFocusLost(LLUICtrl* caller,void* userdata); - static void onInputEditorGainFocus(LLUICtrl* caller,void* userdata); + static void onInputEditorFocusLost(LLFocusableElement* caller,void* userdata); + static void onInputEditorGainFocus(LLFocusableElement* caller,void* userdata); static void onCommitGesture(LLUICtrl* ctrl, void* data); static void startChat(void*); static void stopChat(); - /*virtual*/ void setVisible(BOOL visible); protected: void sendChat(EChatType type); void updateChat(); @@ -113,7 +106,6 @@ protected: S32 mLastSpecialChatChannel; BOOL mIsBuilt; - BOOL mDynamicLayout; LLComboBox* mGestureCombo; LLChatBarGestureObserver* mObserver; diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index 693ffe091b..18c3983b9a 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -155,7 +155,6 @@ BOOL LLFloaterAnimPreview::postBuild() mPlayButton->setDisabledImages("",""); mPlayButton->setScaleImage(TRUE); - mPlayButton->setFixedBorder(0, 0); mStopButton = LLViewerUICtrlFactory::getButtonByName(this, "stop_btn"); if (!mStopButton) @@ -170,7 +169,6 @@ BOOL LLFloaterAnimPreview::postBuild() mStopButton->setDisabledImages("",""); mStopButton->setScaleImage(TRUE); - mStopButton->setFixedBorder(0, 0); r.set(r.mRight + PREVIEW_HPAD, y, getRect().getWidth() - PREVIEW_HPAD, y - BTN_HEIGHT); childSetCommitCallback("playback_slider", onSliderMove, this); diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index a2ea8c2794..8dcd38c0bb 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -189,12 +189,15 @@ void LLFloaterAvatarPicker::onList(LLUICtrl* ctrl, void* userdata) return; } - std::vector<LLScrollListItem*> items = self->mListNames->getAllSelected(); - for (std::vector<LLScrollListItem*>::iterator iter = items.begin(); - iter != items.end(); ++iter) + std::vector<LLScrollListItem*> items = + self->mListNames->getAllSelected(); + for ( + std::vector<LLScrollListItem*>::iterator iter = items.begin(); + iter != items.end(); + ++iter) { LLScrollListItem* item = *iter; - self->mAvatarNames.push_back(item->getColumn(0)->getText()); + self->mAvatarNames.push_back(item->getColumn(0)->getValue().asString()); self->mAvatarIDs.push_back(item->getUUID()); self->childSetEnabled("Select", TRUE); } @@ -225,8 +228,8 @@ void LLFloaterAvatarPicker::doSelectionChange(const std::deque<LLFolderViewItem* mAvatarNames.clear(); childSetEnabled("Select", FALSE); } + BOOL first_calling_card = TRUE; - BOOL first_calling_card = TRUE; std::deque<LLFolderViewItem*>::const_iterator item_it; for (item_it = items.begin(); item_it != items.end(); ++item_it) { diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index 5fdbf7d408..82fe16172b 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -164,10 +164,16 @@ void LLFloaterChat::onVisibilityChange(BOOL new_visibility) { // Hide the chat overlay when our history is visible. gConsole->setVisible( !new_visibility ); + + // stop chat history tab from flashing when it appears + if (new_visibility) + { + LLFloaterChatterBox::getInstance()->setFloaterFlashing(this, FALSE); + } + LLFloater::onVisibilityChange(new_visibility); } - void add_timestamped_line(LLViewerTextEditor* edit, const LLString& line, const LLColor4& color) { bool prepend_newline = true; @@ -238,6 +244,12 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) { chat_floater->mPanel->setSpeaker(chat.mFromID, chat.mFromName, LLSpeaker::STATUS_NOT_IN_CHANNEL, LLSpeaker::SPEAKER_OBJECT); } + + // start tab flashing on incoming text from other users (ignoring system text, etc) + if (!chat_floater->isInVisibleChain() && chat.mSourceType == CHAT_SOURCE_AGENT) + { + LLFloaterChatterBox::getInstance()->setFloaterFlashing(chat_floater, TRUE); + } } // static @@ -246,8 +258,14 @@ void LLFloaterChat::setHistoryCursorAndScrollToEnd() LLViewerTextEditor* history_editor = (LLViewerTextEditor*)LLFloaterChat::getInstance(LLSD())->getChildByName("Chat History Editor", TRUE); LLViewerTextEditor* history_editor_with_mute = (LLViewerTextEditor*)LLFloaterChat::getInstance(LLSD())->getChildByName("Chat History Editor with mute", TRUE); - history_editor->setCursorAndScrollToEnd(); - history_editor_with_mute->setCursorAndScrollToEnd(); + if (history_editor) + { + history_editor->setCursorAndScrollToEnd(); + } + if (history_editor_with_mute) + { + history_editor_with_mute->setCursorAndScrollToEnd(); + } } @@ -269,7 +287,7 @@ void LLFloaterChat::onClickMute(void *data) if (gFloaterMute) { - gFloaterMute->show(); + LLFloaterMute::showInstance(); } } @@ -433,7 +451,7 @@ void* LLFloaterChat::createSpeakersPanel(void* data) //static void* LLFloaterChat::createChatPanel(void* data) { - LLChatBar* chatp = new LLChatBar("floating_chat_bar"); + LLChatBar* chatp = new LLChatBar(); return chatp; } @@ -441,7 +459,7 @@ void* LLFloaterChat::createChatPanel(void* data) void LLFloaterChat::hideInstance(const LLSD& id) { LLFloaterChat* floaterp = LLFloaterChat::getInstance(LLSD()); - // don't do anything when hosted in the chatterbox + if(floaterp->getHost()) { LLFloaterChatterBox::hideInstance(LLSD()); diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h index 808393b267..58fa607b38 100644 --- a/indra/newview/llfloaterchat.h +++ b/indra/newview/llfloaterchat.h @@ -82,6 +82,7 @@ public: protected: LLPanelActiveSpeakers* mPanel; + BOOL mScrolledToEnd; }; #endif diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp index bdd30906d2..85bc8182a5 100644 --- a/indra/newview/llfloaterchatterbox.cpp +++ b/indra/newview/llfloaterchatterbox.cpp @@ -86,9 +86,15 @@ LLFloaterMyFriends* LLFloaterMyFriends::showInstance(const LLSD& id) //static void LLFloaterMyFriends::hideInstance(const LLSD& id) { - if(instanceVisible(id)) + LLFloaterMyFriends* floaterp = LLFloaterMyFriends::getInstance(); + + if(floaterp->getHost()) { - LLFloaterChatterBox::hideInstance(LLSD()); + LLFloaterChatterBox::hideInstance(); + } + else + { + LLUISingleton<LLFloaterMyFriends>::hideInstance(id); } } @@ -124,10 +130,23 @@ LLFloaterChatterBox::LLFloaterChatterBox(const LLSD& seed) : mAutoResize = FALSE; gUICtrlFactory->buildFloater(this, "floater_chatterbox.xml", NULL, FALSE); - addFloater(LLFloaterMyFriends::getInstance(0), TRUE); + if (gSavedSettings.getBOOL("ContactsTornOff")) + { + LLFloaterMyFriends* floater_contacts = LLFloaterMyFriends::getInstance(0); + // add then remove to set up relationship for re-attach + addFloater(floater_contacts, FALSE); + removeFloater(floater_contacts); + // reparent to floater view + gFloaterView->addChild(floater_contacts); + } + else + { + addFloater(LLFloaterMyFriends::getInstance(0), TRUE); + } + if (gSavedSettings.getBOOL("ChatHistoryTornOff")) { - LLFloaterChat* floater_chat = LLFloaterChat::getInstance(LLSD()); + LLFloaterChat* floater_chat = LLFloaterChat::getInstance(); // add then remove to set up relationship for re-attach addFloater(floater_chat, FALSE); removeFloater(floater_chat); @@ -217,7 +236,7 @@ void LLFloaterChatterBox::draw() mActiveVoiceFloater = current_active_floater; - LLFloater::draw(); + LLMultiFloater::draw(); } void LLFloaterChatterBox::onOpen() @@ -236,10 +255,17 @@ void LLFloaterChatterBox::removeFloater(LLFloater* floaterp) if (floaterp->getName() == "chat floater") { // only my friends floater now locked - mTabContainer->lockTabs(1); + mTabContainer->lockTabs(mTabContainer->getNumLockedTabs() - 1); gSavedSettings.setBOOL("ChatHistoryTornOff", TRUE); floaterp->setCanClose(TRUE); } + else if (floaterp->getName() == "floater_my_friends") + { + // only chat floater now locked + mTabContainer->lockTabs(mTabContainer->getNumLockedTabs() - 1); + gSavedSettings.setBOOL("ContactsTornOff", TRUE); + floaterp->setCanClose(TRUE); + } LLMultiFloater::removeFloater(floaterp); } @@ -247,19 +273,43 @@ void LLFloaterChatterBox::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainerCommon::eInsertionPoint insertion_point) { + S32 num_locked_tabs = mTabContainer->getNumLockedTabs(); + + // already here + if (floaterp->getHost() == this) return; + // make sure my friends and chat history both locked when re-attaching chat history if (floaterp->getName() == "chat floater") { - // select my friends tab - mTabContainer->selectFirstTab(); - // add chat history to the right of the my friends tab - //*TODO: respect select_added_floater so that we don't leave first tab selected - LLMultiFloater::addFloater(floaterp, select_added_floater, LLTabContainer::RIGHT_OF_CURRENT); + mTabContainer->unlockTabs(); + // add chat history as second tab if contact window is present, first tab otherwise + if (getChildByName("floater_my_friends", TRUE)) + { + // assuming contacts window is first tab, select it + mTabContainer->selectFirstTab(); + // and add ourselves after + LLMultiFloater::addFloater(floaterp, select_added_floater, LLTabContainer::RIGHT_OF_CURRENT); + } + else + { + LLMultiFloater::addFloater(floaterp, select_added_floater, LLTabContainer::START); + } + // make sure first two tabs are now locked - mTabContainer->lockTabs(2); + mTabContainer->lockTabs(num_locked_tabs + 1); gSavedSettings.setBOOL("ChatHistoryTornOff", FALSE); floaterp->setCanClose(FALSE); } + else if (floaterp->getName() == "floater_my_friends") + { + mTabContainer->unlockTabs(); + // add contacts window as first tab + LLMultiFloater::addFloater(floaterp, select_added_floater, LLTabContainer::START); + // make sure first two tabs are now locked + mTabContainer->lockTabs(num_locked_tabs + 1); + gSavedSettings.setBOOL("ContactsTornOff", FALSE); + floaterp->setCanClose(FALSE); + } else { LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); @@ -276,24 +326,27 @@ void LLFloaterChatterBox::addFloater(LLFloater* floaterp, //static LLFloaterChatterBox* LLFloaterChatterBox::showInstance(const LLSD& seed) { - LLFloaterChatterBox* floater = LLUISingleton<LLFloaterChatterBox>::showInstance(seed); + LLFloaterChatterBox* chatterbox_floater = LLUISingleton<LLFloaterChatterBox>::showInstance(seed); // if TRUE, show tab for active voice channel, otherwise, just show last tab - if (seed.asBoolean()) + LLFloater* floater_to_show = NULL; + LLUUID session_id = seed.asUUID(); + if (session_id.notNull()) { - LLFloater* floater_to_show = getCurrentVoiceFloater(); - if (floater_to_show) - { - floater_to_show->open(); - } - else - { - // just open chatterbox if there is no active voice window - LLUISingleton<LLFloaterChatterBox>::getInstance(seed)->open(); - } + floater_to_show = gIMMgr->findFloaterBySession(session_id); + } + + if (floater_to_show) + { + floater_to_show->open(); + } + else + { + // just open chatterbox to the last selected tab + chatterbox_floater->open(); } - return floater; + return chatterbox_floater; } //static diff --git a/indra/newview/llfloaterchatterbox.h b/indra/newview/llfloaterchatterbox.h index 34410935f2..bf06ee9d38 100644 --- a/indra/newview/llfloaterchatterbox.h +++ b/indra/newview/llfloaterchatterbox.h @@ -50,7 +50,7 @@ public: void onClose(bool app_quitting); // override LLUISingleton behavior - static LLFloaterMyFriends* showInstance(const LLSD& id); + static LLFloaterMyFriends* showInstance(const LLSD& id = LLSD()); static void hideInstance(const LLSD& id); static BOOL instanceVisible(const LLSD& id); @@ -77,7 +77,7 @@ public: BOOL select_added_floater, LLTabContainerCommon::eInsertionPoint insertion_point = LLTabContainerCommon::END); - static LLFloaterChatterBox* showInstance(const LLSD& seed); + static LLFloaterChatterBox* showInstance(const LLSD& seed = LLSD()); static BOOL instanceVisible(const LLSD& seed); static LLFloater* getCurrentVoiceFloater(); diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 6f4945e54b..9d52107a20 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -104,7 +104,6 @@ LLPanelFriends::LLPanelFriends() : LLPanel(), LLEventTimer(1000000), mObserver(NULL), - mMenuState(0), mShowMaxSelectWarning(TRUE), mAllowRightsChange(TRUE), mNumRightsChanged(0) @@ -182,16 +181,13 @@ BOOL LLPanelFriends::postBuild() { mFriendsList = LLUICtrlFactory::getScrollListByName(this, "friend_list"); mFriendsList->setMaxSelectable(MAX_FRIEND_SELECT); - mFriendsList->setMaxiumumSelectCallback(onMaximumSelect); + mFriendsList->setMaximumSelectCallback(onMaximumSelect); mFriendsList->setCommitOnSelectionChange(TRUE); childSetCommitCallback("friend_list", onSelectName, this); childSetDoubleClickCallback("friend_list", onClickIM); refreshNames(); - childSetCommitCallback("online_status_cb", onClickOnlineStatus, this); - childSetCommitCallback("map_status_cb", onClickMapStatus, this); - childSetCommitCallback("modify_status_cb", onClickModifyStatus, this); childSetAction("im_btn", onClickIM, this); childSetAction("profile_btn", onClickProfile, this); childSetAction("offer_teleport_btn", onClickOfferTeleport, this); @@ -204,6 +200,10 @@ BOOL LLPanelFriends::postBuild() updateFriends(LLFriendObserver::ADD); refreshUI(); + // primary sort = online status, secondary sort = name + mFriendsList->sortByColumn("friend_name", TRUE); + mFriendsList->sortByColumn("icon_online_status", TRUE); + return TRUE; } @@ -222,64 +222,63 @@ void LLPanelFriends::addFriend(const std::string& name, const LLUUID& agent_id) element["columns"][LIST_FRIEND_NAME]["font"] = "SANSSERIF"; element["columns"][LIST_FRIEND_NAME]["font-style"] = "NORMAL"; element["columns"][LIST_ONLINE_STATUS]["column"] = "icon_online_status"; - element["columns"][LIST_ONLINE_STATUS]["type"] = "text"; + element["columns"][LIST_ONLINE_STATUS]["type"] = "icon"; if (online) { element["columns"][LIST_FRIEND_NAME]["font-style"] = "BOLD"; - element["columns"][LIST_ONLINE_STATUS]["type"] = "icon"; element["columns"][LIST_ONLINE_STATUS]["value"] = gViewerArt.getString("icon_avatar_online.tga"); } - element["columns"][LIST_VISIBLE_ONLINE]["column"] = "icon_visible_online"; - element["columns"][LIST_VISIBLE_ONLINE]["type"] = "text"; - if(relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS)) - { - element["columns"][LIST_VISIBLE_ONLINE]["type"] = "icon"; - element["columns"][LIST_VISIBLE_ONLINE]["value"] = gViewerArt.getString("ff_visible_online.tga"); - } + element["columns"][LIST_VISIBLE_ONLINE]["type"] = "checkbox"; + element["columns"][LIST_VISIBLE_ONLINE]["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS); + element["columns"][LIST_VISIBLE_MAP]["column"] = "icon_visible_map"; - element["columns"][LIST_VISIBLE_MAP]["type"] = "text"; - if(relationInfo->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION)) - { - element["columns"][LIST_VISIBLE_MAP]["type"] = "icon"; - element["columns"][LIST_VISIBLE_MAP]["value"] = gViewerArt.getString("ff_visible_map.tga"); - } + element["columns"][LIST_VISIBLE_MAP]["type"] = "checkbox"; + element["columns"][LIST_VISIBLE_MAP]["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION); + element["columns"][LIST_EDIT_MINE]["column"] = "icon_edit_mine"; - element["columns"][LIST_EDIT_MINE]["type"] = "text"; - if(relationInfo->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS)) - { - element["columns"][LIST_EDIT_MINE]["type"] = "icon"; - element["columns"][LIST_EDIT_MINE]["value"] = gViewerArt.getString("ff_edit_mine.tga"); - } + element["columns"][LIST_EDIT_MINE]["type"] = "checkbox"; + element["columns"][LIST_EDIT_MINE]["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS); + element["columns"][LIST_EDIT_THEIRS]["column"] = "icon_edit_theirs"; - element["columns"][LIST_EDIT_THEIRS]["type"] = "text"; - if(relationInfo->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS)) - { - element["columns"][LIST_EDIT_THEIRS]["type"] = "icon"; - element["columns"][LIST_EDIT_THEIRS]["value"] = gViewerArt.getString("ff_edit_theirs.tga"); - } + element["columns"][LIST_EDIT_THEIRS]["type"] = "checkbox"; + element["columns"][LIST_EDIT_THEIRS]["enabled"] = ""; + element["columns"][LIST_EDIT_THEIRS]["value"] = relationInfo->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS); + + element["columns"][LIST_FRIEND_UPDATE_GEN]["column"] = "friend_last_update_generation"; + element["columns"][LIST_FRIEND_UPDATE_GEN]["value"] = relationInfo->getChangeSerialNum(); + mFriendsList->addElement(element, ADD_BOTTOM); } +// propagate actual relationship to UI +void LLPanelFriends::updateFriendItem(LLScrollListItem* itemp, const LLRelationship* info) +{ + if (!itemp) return; + if (!info) return; + + itemp->getColumn(LIST_ONLINE_STATUS)->setValue(info->isOnline() ? gViewerArt.getString("icon_avatar_online.tga") : LLString()); + // render name of online friends in bold text + ((LLScrollListText*)itemp->getColumn(LIST_FRIEND_NAME))->setFontStyle(info->isOnline() ? LLFontGL::BOLD : LLFontGL::NORMAL); + itemp->getColumn(LIST_VISIBLE_ONLINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS)); + itemp->getColumn(LIST_VISIBLE_MAP)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION)); + itemp->getColumn(LIST_EDIT_MINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS)); + itemp->getColumn(LIST_FRIEND_UPDATE_GEN)->setValue(info->getChangeSerialNum()); + + // enable this item, in case it was disabled after user input + itemp->setEnabled(TRUE); + + // changed item in place, need to request sort + mFriendsList->sortItems(); +} + void LLPanelFriends::refreshRightsChangeList() { LLDynamicArray<LLUUID> friends = getSelectedIDs(); S32 num_selected = friends.size(); - LLSD row; bool can_offer_teleport = num_selected >= 1; - - // aggregate permissions over all selected friends - bool friends_see_online = true; - bool friends_see_on_map = true; - bool friends_modify_objects = true; - - // do at least some of the friends selected have these rights? - bool some_friends_see_online = false; - bool some_friends_see_on_map = false; - bool some_friends_modify_objects = false; - bool selected_friends_online = true; LLTextBox* processing_label = LLUICtrlFactory::getTextBoxByName(this, "process_rights_label"); @@ -294,12 +293,9 @@ void LLPanelFriends::refreshRightsChangeList() num_selected = 0; } } - else + else if(processing_label) { - if(processing_label) - { - processing_label->setVisible(false); - } + processing_label->setVisible(false); } const LLRelationship* friend_status = NULL; @@ -308,20 +304,6 @@ void LLPanelFriends::refreshRightsChangeList() friend_status = LLAvatarTracker::instance().getBuddyInfo(*itr); if (friend_status) { - bool can_see_online = friend_status->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS); - bool can_see_on_map = friend_status->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION); - bool can_modify_objects = friend_status->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS); - - // aggregate rights of this friend into total selection - friends_see_online &= can_see_online; - friends_see_on_map &= can_see_on_map; - friends_modify_objects &= can_modify_objects; - - // can at least one of your selected friends do any of these? - some_friends_see_online |= can_see_online; - some_friends_see_on_map |= can_see_on_map; - some_friends_modify_objects |= can_modify_objects; - if(!friend_status->isOnline()) { can_offer_teleport = false; @@ -331,44 +313,13 @@ void LLPanelFriends::refreshRightsChangeList() else // missing buddy info, don't allow any operations { can_offer_teleport = false; - - friends_see_online = false; - friends_see_on_map = false; - friends_modify_objects = false; - - some_friends_see_online = false; - some_friends_see_on_map = false; - some_friends_modify_objects = false; } } - - // seeing a friend on the map requires seeing online status as a prerequisite - friends_see_on_map &= friends_see_online; - - mMenuState = 0; - - // make checkboxes visible after we have finished processing rights - childSetVisible("online_status_cb", mAllowRightsChange); - childSetVisible("map_status_cb", mAllowRightsChange); - childSetVisible("modify_status_cb", mAllowRightsChange); - if (num_selected == 0) // nothing selected { childSetEnabled("im_btn", FALSE); childSetEnabled("offer_teleport_btn", FALSE); - - childSetEnabled("online_status_cb", FALSE); - childSetValue("online_status_cb", FALSE); - childSetTentative("online_status_cb", FALSE); - - childSetEnabled("map_status_cb", FALSE); - childSetValue("map_status_cb", FALSE); - childSetTentative("map_status_cb", FALSE); - - childSetEnabled("modify_status_cb", FALSE); - childSetValue("modify_status_cb", FALSE); - childSetTentative("modify_status_cb", FALSE); } else // we have at least one friend selected... { @@ -376,61 +327,76 @@ void LLPanelFriends::refreshRightsChangeList() // to be consistent with context menus in inventory and because otherwise // offline friends would be silently dropped from the session childSetEnabled("im_btn", selected_friends_online || num_selected == 1); - childSetEnabled("offer_teleport_btn", can_offer_teleport); - - childSetEnabled("online_status_cb", TRUE); - childSetValue("online_status_cb", some_friends_see_online); - childSetTentative("online_status_cb", some_friends_see_online != friends_see_online); - if (friends_see_online) - { - mMenuState |= LLRelationship::GRANT_ONLINE_STATUS; - } - - childSetEnabled("map_status_cb", TRUE); - childSetValue("map_status_cb", some_friends_see_on_map); - childSetTentative("map_status_cb", some_friends_see_on_map != friends_see_on_map); - if(friends_see_on_map) - { - mMenuState |= LLRelationship::GRANT_MAP_LOCATION; - } - - // for now, don't allow modify rights change for multiple select - childSetEnabled("modify_status_cb", num_selected == 1); - childSetValue("modify_status_cb", some_friends_modify_objects); - childSetTentative("modify_status_cb", some_friends_modify_objects != friends_modify_objects); - if(friends_modify_objects) - { - mMenuState |= LLRelationship::GRANT_MODIFY_OBJECTS; - } } } +struct SortFriendsByID +{ + bool SortFriendsByID::operator() (const LLScrollListItem* const a, const LLScrollListItem* const b) const + { + return a->getValue().asUUID() < b->getValue().asUUID(); + } +}; + void LLPanelFriends::refreshNames() { LLDynamicArray<LLUUID> selected_ids = getSelectedIDs(); S32 pos = mFriendsList->getScrollPos(); - mFriendsList->operateOnAll(LLCtrlListInterface::OP_DELETE); - LLCollectAllBuddies collect; - LLAvatarTracker::instance().applyFunctor(collect); - LLCollectAllBuddies::buddy_map_t::const_iterator it = collect.mOnline.begin(); - LLCollectAllBuddies::buddy_map_t::const_iterator end = collect.mOnline.end(); + // get all buddies we know about + LLAvatarTracker::buddy_map_t all_buddies; + LLAvatarTracker::instance().copyBuddyList(all_buddies); - for ( ; it != end; ++it) - { - const std::string& name = it->first; - const LLUUID& agent_id = it->second; - addFriend(name, agent_id); - } - it = collect.mOffline.begin(); - end = collect.mOffline.end(); - for ( ; it != end; ++it) + // get all friends in list and sort by UUID + std::vector<LLScrollListItem*> items = mFriendsList->getAllData(); + std::sort(items.begin(), items.end(), SortFriendsByID()); + + std::vector<LLScrollListItem*>::iterator item_it = items.begin(); + std::vector<LLScrollListItem*>::iterator item_end = items.end(); + + LLAvatarTracker::buddy_map_t::iterator buddy_it; + for (buddy_it = all_buddies.begin() ; buddy_it != all_buddies.end(); ++buddy_it) { - const std::string& name = it->first; - const LLUUID& agent_id = it->second; - addFriend(name, agent_id); + // erase any items that reflect residents who are no longer buddies + while(item_it != item_end && buddy_it->first > (*item_it)->getValue().asUUID()) + { + mFriendsList->deleteItems((*item_it)->getValue()); + ++item_it; + } + + // update existing friends with new info + if (item_it != item_end && buddy_it->first == (*item_it)->getValue().asUUID()) + { + const LLRelationship* info = buddy_it->second; + if (!info) + { + ++item_it; + continue; + } + + S32 last_change_generation = (*item_it)->getColumn(LIST_FRIEND_UPDATE_GEN)->getValue().asInteger(); + if (last_change_generation < info->getChangeSerialNum()) + { + // update existing item in UI + updateFriendItem(mFriendsList->getItem(buddy_it->first), info); + } + ++item_it; + } + // add new friend to list + else + { + const LLUUID& buddy_id = buddy_it->first; + char first_name[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last_name[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + + gCacheName->getName(buddy_id, first_name, last_name); + std::ostringstream fullname; + fullname << first_name << " " << last_name; + addFriend(fullname.str(), buddy_id); + } } + mFriendsList->selectMultiple(selected_ids); mFriendsList->setScrollPos(pos); } @@ -451,7 +417,7 @@ void LLPanelFriends::refreshUI() } else { - childSetText("friend_name_label", mFriendsList->getFirstSelected()->getColumn(LIST_FRIEND_NAME)->getText() + "..."); + childSetText("friend_name_label", mFriendsList->getFirstSelected()->getColumn(LIST_FRIEND_NAME)->getValue().asString() + "..."); } } else @@ -493,6 +459,8 @@ void LLPanelFriends::onSelectName(LLUICtrl* ctrl, void* user_data) if(panelp) { panelp->refreshUI(); + // check to see if rights have changed + panelp->applyRightsToFriends(); } } @@ -687,35 +655,22 @@ void LLPanelFriends::onClickPay(void* user_data) } } -void LLPanelFriends::onClickOnlineStatus(LLUICtrl* ctrl, void* user_data) -{ - LLPanelFriends* panelp = (LLPanelFriends*)user_data; - - bool checked = ctrl->getValue(); - panelp->updateMenuState(LLRelationship::GRANT_ONLINE_STATUS, checked); - panelp->applyRightsToFriends(LLRelationship::GRANT_ONLINE_STATUS, checked); -} - -void LLPanelFriends::onClickMapStatus(LLUICtrl* ctrl, void* user_data) -{ - LLPanelFriends* panelp = (LLPanelFriends*)user_data; - bool checked = ctrl->getValue(); - panelp->updateMenuState(LLRelationship::GRANT_MAP_LOCATION, checked); - panelp->applyRightsToFriends(LLRelationship::GRANT_MAP_LOCATION, checked); -} - -void LLPanelFriends::onClickModifyStatus(LLUICtrl* ctrl, void* user_data) +void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command) { - LLPanelFriends* panelp = (LLPanelFriends*)user_data; - - bool checked = ctrl->getValue(); - LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs(); + if (ids.empty()) return; + LLStringBase<char>::format_map_t args; if(ids.size() > 0) { + // copy map of ids onto heap + rights_map_t* rights = new rights_map_t(ids); + // package with panel pointer + std::pair<LLPanelFriends*, rights_map_t*>* user_data = new std::pair<LLPanelFriends*, rights_map_t*>(this, rights); + + // for single friend, show their name if(ids.size() == 1) { - LLUUID agent_id = ids[0]; + LLUUID agent_id = ids.begin()->first; char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ if(gCacheName->getName(agent_id, first, last)) @@ -723,56 +678,174 @@ void LLPanelFriends::onClickModifyStatus(LLUICtrl* ctrl, void* user_data) args["[FIRST_NAME]"] = first; args["[LAST_NAME]"] = last; } - if(checked) gViewerWindow->alertXml("GrantModifyRights", args, handleModifyRights, user_data); - else gViewerWindow->alertXml("RevokeModifyRights", args, handleModifyRights, user_data); + if (command == GRANT) + { + gViewerWindow->alertXml("GrantModifyRights", args, modifyRightsConfirmation, user_data); + } + else + { + gViewerWindow->alertXml("RevokeModifyRights", args, modifyRightsConfirmation, user_data); + } + } + else + { + if (command == GRANT) + { + gViewerWindow->alertXml("GrantModifyRightsMultiple", args, modifyRightsConfirmation, user_data); + } + else + { + gViewerWindow->alertXml("RevokeModifyRightsMultiple", args, modifyRightsConfirmation, user_data); + } } - else return; } } -void LLPanelFriends::handleModifyRights(S32 option, void* user_data) +// static +void LLPanelFriends::modifyRightsConfirmation(S32 option, void* user_data) { - LLPanelFriends* panelp = (LLPanelFriends*)user_data; + std::pair<LLPanelFriends*, rights_map_t*>* data = (std::pair<LLPanelFriends*, rights_map_t*>*)user_data; + LLPanelFriends* panelp = data->first; if(panelp) { - if(!option) + if(0 == option) { - panelp->updateMenuState(LLRelationship::GRANT_MODIFY_OBJECTS, !((panelp->getMenuState() & LLRelationship::GRANT_MODIFY_OBJECTS) != 0)); - panelp->applyRightsToFriends(LLRelationship::GRANT_MODIFY_OBJECTS, ((panelp->getMenuState() & LLRelationship::GRANT_MODIFY_OBJECTS) != 0)); + panelp->sendRightsGrant(*(data->second)); + } + else + { + // need to resync view with model, since user cancelled operation + rights_map_t* rights = data->second; + rights_map_t::iterator rights_it; + for (rights_it = rights->begin(); rights_it != rights->end(); ++rights_it) + { + LLScrollListItem* itemp = panelp->mFriendsList->getItem(rights_it->first); + const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(rights_it->first); + panelp->updateFriendItem(itemp, info); + } } panelp->refreshUI(); } + + delete data->second; + delete data; } -void LLPanelFriends::updateMenuState(S32 flag, BOOL value) +void LLPanelFriends::applyRightsToFriends() { - if(value) mMenuState |= flag; - else mMenuState &= ~flag; + BOOL rights_changed = FALSE; + + // store modify rights separately for confirmation + rights_map_t rights_updates; + + BOOL need_confirmation = FALSE; + EGrantRevoke confirmation_type = GRANT; + + // this assumes that changes only happened to selected items + std::vector<LLScrollListItem*> selected = mFriendsList->getAllSelected(); + for(std::vector<LLScrollListItem*>::iterator itr = selected.begin(); itr != selected.end(); ++itr) + { + LLUUID id = (*itr)->getValue(); + const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(id); + if (buddy_relationship == NULL) continue; + + bool show_online_staus = (*itr)->getColumn(LIST_VISIBLE_ONLINE)->getValue().asBoolean(); + bool show_map_location = (*itr)->getColumn(LIST_VISIBLE_MAP)->getValue().asBoolean(); + bool allow_modify_objects = (*itr)->getColumn(LIST_EDIT_MINE)->getValue().asBoolean(); + + S32 rights = buddy_relationship->getRightsGrantedTo(); + if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS) != show_online_staus) + { + rights_changed = TRUE; + if(show_online_staus) + { + rights |= LLRelationship::GRANT_ONLINE_STATUS; + } + else + { + // ONLINE_STATUS necessary for MAP_LOCATION + rights &= ~LLRelationship::GRANT_ONLINE_STATUS; + rights &= ~LLRelationship::GRANT_MAP_LOCATION; + // propagate rights constraint to UI + (*itr)->getColumn(LIST_VISIBLE_MAP)->setValue(FALSE); + } + } + if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION) != show_map_location) + { + rights_changed = TRUE; + if(show_map_location) + { + // ONLINE_STATUS necessary for MAP_LOCATION + rights |= LLRelationship::GRANT_MAP_LOCATION; + rights |= LLRelationship::GRANT_ONLINE_STATUS; + (*itr)->getColumn(LIST_VISIBLE_ONLINE)->setValue(TRUE); + } + else + { + rights &= ~LLRelationship::GRANT_MAP_LOCATION; + } + } + + // now check for change in modify object rights, which requires confirmation + if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects) + { + rights_changed = TRUE; + need_confirmation = TRUE; + + if(allow_modify_objects) + { + rights |= LLRelationship::GRANT_MODIFY_OBJECTS; + confirmation_type = GRANT; + } + else + { + rights &= ~LLRelationship::GRANT_MODIFY_OBJECTS; + confirmation_type = REVOKE; + } + } + + if (rights_changed) + { + rights_updates.insert(std::make_pair(id, rights)); + // disable these ui elements until response from server + // to avoid race conditions + (*itr)->setEnabled(FALSE); + } + } + + // separately confirm grant and revoke of modify rights + if (need_confirmation) + { + confirmModifyRights(rights_updates, confirmation_type); + } + else + { + sendRightsGrant(rights_updates); + } } -void LLPanelFriends::applyRightsToFriends(S32 flag, BOOL value) +void LLPanelFriends::sendRightsGrant(rights_map_t& ids) { + if (ids.empty()) return; + LLMessageSystem* msg = gMessageSystem; + + // setup message header msg->newMessageFast(_PREHASH_GrantUserRights); msg->nextBlockFast(_PREHASH_AgentData); msg->addUUID(_PREHASH_AgentID, gAgent.getID()); msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID()); - LLDynamicArray<LLUUID> ids = getSelectedIDs(); - S32 rights; - for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr) + rights_map_t::iterator id_it; + rights_map_t::iterator end_it = ids.end(); + for(id_it = ids.begin(); id_it != end_it; ++id_it) { - rights = LLAvatarTracker::instance().getBuddyInfo(*itr)->getRightsGrantedTo(); - if(LLAvatarTracker::instance().getBuddyInfo(*itr)->isRightGrantedTo(flag) != (bool)value) - { - if(value) rights |= flag; - else rights &= ~flag; - msg->nextBlockFast(_PREHASH_Rights); - msg->addUUID(_PREHASH_AgentRelated, *itr); - msg->addS32(_PREHASH_RelatedRights, rights); - } + msg->nextBlockFast(_PREHASH_Rights); + msg->addUUID(_PREHASH_AgentRelated, id_it->first); + msg->addS32(_PREHASH_RelatedRights, id_it->second); } + mNumRightsChanged = ids.size(); gAgent.sendReliableMessage(); } diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h index 3d0b7a9bba..46e4eaaf79 100644 --- a/indra/newview/llfloaterfriends.h +++ b/indra/newview/llfloaterfriends.h @@ -40,6 +40,7 @@ #include "lltimer.h" class LLFriendObserver; +class LLRelationship; /** @@ -88,19 +89,27 @@ private: LIST_VISIBLE_ONLINE, LIST_VISIBLE_MAP, LIST_EDIT_MINE, - LIST_EDIT_THEIRS + LIST_EDIT_THEIRS, + LIST_FRIEND_UPDATE_GEN }; // protected members - + typedef std::map<LLUUID, S32> rights_map_t; void reloadNames(); void refreshNames(); void refreshUI(); void refreshRightsChangeList(); - void applyRightsToFriends(S32 flag, BOOL value); - void updateMenuState(S32 flag, BOOL value); - S32 getMenuState() { return mMenuState; } + void applyRightsToFriends(); void addFriend(const std::string& name, const LLUUID& agent_id); + void updateFriendItem(LLScrollListItem* itemp, const LLRelationship* relationship); + + typedef enum + { + GRANT, + REVOKE + } EGrantRevoke; + void confirmModifyRights(rights_map_t& ids, EGrantRevoke command); + void sendRightsGrant(rights_map_t& ids); // return LLUUID::null if nothing is selected LLDynamicArray<LLUUID> getSelectedIDs(); @@ -119,12 +128,10 @@ private: static void onClickOfferTeleport(void* user_data); static void onClickPay(void* user_data); - static void onClickOnlineStatus(LLUICtrl* ctrl, void* user_data); - static void onClickMapStatus(LLUICtrl* ctrl, void* user_data); static void onClickModifyStatus(LLUICtrl* ctrl, void* user_data); static void handleRemove(S32 option, void* user_data); - static void handleModifyRights(S32 option, void* user_data); + static void modifyRightsConfirmation(S32 option, void* user_data); private: // member data @@ -132,7 +139,6 @@ private: LLUUID mAddFriendID; LLString mAddFriendName; LLScrollListCtrl* mFriendsList; - S32 mMenuState; BOOL mShowMaxSelectWarning; BOOL mAllowRightsChange; S32 mNumRightsChanged; diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp index 0ce91ef740..9f1624d20c 100644 --- a/indra/newview/llfloaterinspect.cpp +++ b/indra/newview/llfloaterinspect.cpp @@ -262,6 +262,7 @@ void LLFloaterInspect::refresh() void LLFloaterInspect::onFocusReceived() { gToolMgr->setTransientTool(gToolInspect); + LLFloater::onFocusReceived(); } void LLFloaterInspect::dirty() diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 3b96a4ce5e..2a352dfc3d 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1045,8 +1045,10 @@ BOOL LLPanelLandObjects::postBuild() mSelectedObjects = LLUICtrlFactory::getTextBoxByName(this, "selected_objects_text"); mCleanOtherObjectsTime = LLUICtrlFactory::getLineEditorByName(this, "clean other time"); - mCleanOtherObjectsTime->setFocusLostCallback(onLostFocus); + + mCleanOtherObjectsTime->setFocusLostCallback(onLostFocus, this); mCleanOtherObjectsTime->setCommitCallback(onCommitClean); + childSetPrevalidate("clean other time", LLLineEditor::prevalidateNonNegativeS32); childSetUserData("clean other time", this); @@ -1135,7 +1137,7 @@ void LLPanelLandObjects::onDoubleClickOwner(void *userdata) return; } // Is this a group? - BOOL is_group = cell->getText() == OWNER_GROUP; + BOOL is_group = cell->getValue().asString() == OWNER_GROUP; if (is_group) { LLFloaterGroupInfo::showFromUUID(owner_id); @@ -1180,19 +1182,16 @@ void LLPanelLandObjects::refresh() } else { - S32 sw_max = 0; - S32 sw_total = 0; - S32 max = 0; - S32 total = 0; - S32 owned = 0; - S32 group = 0; - S32 other = 0; - S32 selected = 0; - F32 parcel_object_bonus = 0.f; - - gParcelMgr->getPrimInfo(sw_max, sw_total, - max, total, owned, group, other, selected, - parcel_object_bonus, mOtherTime); + S32 sw_max = parcel->getSimWideMaxPrimCapacity(); + S32 sw_total = parcel->getSimWidePrimCount(); + S32 max = llround(parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus()); + S32 total = parcel->getPrimCount(); + S32 owned = parcel->getOwnerPrimCount(); + S32 group = parcel->getGroupPrimCount(); + S32 other = parcel->getOtherPrimCount(); + S32 selected = parcel->getSelectedPrimCount(); + F32 parcel_object_bonus = parcel->getParcelPrimBonus(); + mOtherTime = parcel->getCleanOtherTime(); // Can't have more than region max tasks, regardless of parcel // object bonus factor. @@ -1442,14 +1441,6 @@ void LLPanelLandObjects::onClickReturnOwnerList(void* userdata) { LLPanelLandObjects *self = (LLPanelLandObjects *)userdata; - S32 sw_max, sw_total; - S32 max, total; - S32 owned, group, other, selected; - F32 parcel_object_bonus; - S32 other_time; - - gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time); - LLParcel* parcelp = self->mParcel->getParcel(); if (!parcelp) return; @@ -1632,11 +1623,11 @@ void LLPanelLandObjects::onCommitList(LLUICtrl* ctrl, void* data) return; } // Is this a group? - self->mSelectedIsGroup = cell->getText() == OWNER_GROUP; + self->mSelectedIsGroup = cell->getValue().asString() == OWNER_GROUP; cell = item->getColumn(2); - self->mSelectedName = cell->getText(); + self->mSelectedName = cell->getValue().asString(); cell = item->getColumn(3); - self->mSelectedCount = atoi(cell->getText().c_str()); + self->mSelectedCount = atoi(cell->getValue().asString().c_str()); // Set the selection, and enable the return button. self->mSelectedOwners.clear(); @@ -1700,18 +1691,14 @@ void LLPanelLandObjects::onClickShowOtherObjects(void* userdata) // static void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata) { - S32 sw_max=0, sw_total=0; - S32 max=0, total=0; - S32 owned=0, group=0, other=0, selected=0; - F32 parcel_object_bonus=0; - S32 other_time=0; - - gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time); + S32 owned = 0; LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata; LLParcel* parcel = panelp->mParcel->getParcel(); if (!parcel) return; + owned = parcel->getOwnerPrimCount(); + send_parcel_select_objects(parcel->getLocalID(), RT_OWNER); LLUUID owner_id = parcel->getOwnerID(); @@ -1739,14 +1726,6 @@ void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata) // static void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata) { - S32 sw_max=0, sw_total=0; - S32 max=0, total=0; - S32 owned=0, group=0, other=0, selected=0; - F32 parcel_object_bonus=0; - S32 other_time=0; - - gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time); - LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata; LLParcel* parcel = panelp->mParcel->getParcel(); if (!parcel) return; @@ -1758,7 +1737,7 @@ void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata) LLStringBase<char>::format_map_t args; args["[NAME]"] = group_name; - args["[N]"] = llformat("%d",group); + args["[N]"] = llformat("%d", parcel->getGroupPrimCount()); // create and show confirmation textbox gViewerWindow->alertXml("ReturnObjectsDeededToGroup", args, callbackReturnGroupObjects, userdata); @@ -1767,17 +1746,13 @@ void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata) // static void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata) { - S32 sw_max=0, sw_total=0; - S32 max=0, total=0; - S32 owned=0, group=0, other=0, selected=0; - F32 parcel_object_bonus=0; - S32 other_time=0; - - gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time); + S32 other = 0; LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata; LLParcel* parcel = panelp->mParcel->getParcel(); if (!parcel) return; + + other = parcel->getOtherPrimCount(); send_parcel_select_objects(parcel->getLocalID(), RT_OTHER); @@ -1817,9 +1792,9 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata) } // static -void LLPanelLandObjects::onLostFocus(LLUICtrl *caller, void* user_data) +void LLPanelLandObjects::onLostFocus(LLFocusableElement* caller, void* user_data) { - onCommitClean(caller, user_data); + onCommitClean((LLUICtrl*)caller, user_data); } // static @@ -2408,6 +2383,13 @@ void LLPanelLandMedia::refresh() mCheckSoundLocal->set( parcel->getSoundLocal() ); mCheckSoundLocal->setEnabled( can_change_media ); + LLViewerRegion* selection_region = gParcelMgr->getSelectionRegion(); + BOOL region_allows_voice = FALSE; + if (selection_region) + { + region_allows_voice = selection_region->isVoiceEnabled(); + } + if(parcel->getVoiceEnabled()) { if(parcel->getVoiceUseEstateChannel()) @@ -2420,7 +2402,7 @@ void LLPanelLandMedia::refresh() mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatDisable); } - mRadioVoiceChat->setEnabled( can_change_media ); + mRadioVoiceChat->setEnabled( can_change_media && region_allows_voice ); // don't display urls if you're not able to change it // much requested change in forums so people can't 'steal' urls @@ -2535,7 +2517,7 @@ void LLPanelLandMedia::onClickStopMedia ( void* data ) void LLPanelLandMedia::onClickStartMedia ( void* data ) { // force a commit - gFocusMgr.setKeyboardFocus ( NULL, NULL ); + gFocusMgr.setKeyboardFocus ( NULL ); // force a reload LLMediaEngine::getInstance ()->convertImageAndLoadUrl ( true, false, std::string()); diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index fa941caf78..4bb88aa127 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -257,7 +257,7 @@ public: static void onDoubleClickOwner(void*); static void onCommitList(LLUICtrl* ctrl, void* data); - static void onLostFocus(LLUICtrl* caller, void* user_data); + static void onLostFocus(LLFocusableElement* caller, void* user_data); static void onCommitClean(LLUICtrl* caller, void* user_data); static void processParcelObjectOwnersReply(LLMessageSystem *msg, void **); diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp index a00f512515..5306ce11b1 100644 --- a/indra/newview/llfloaterpostcard.cpp +++ b/indra/newview/llfloaterpostcard.cpp @@ -137,8 +137,7 @@ BOOL LLFloaterPostcard::postBuild() MsgField->setWordWrap(TRUE); // For the first time a user focusess to .the msg box, all text will be selected. - MsgField->setFocusChangedCallback(onMsgFormFocusRecieved); - MsgField->setCallbackUserData(this); + MsgField->setFocusChangedCallback(onMsgFormFocusRecieved, this); } childSetFocus("to_form", TRUE); @@ -347,7 +346,7 @@ void LLFloaterPostcard::updateUserInfo(const char *email) } } -void LLFloaterPostcard::onMsgFormFocusRecieved(LLUICtrl* receiver, void* data) +void LLFloaterPostcard::onMsgFormFocusRecieved(LLFocusableElement* receiver, void* data) { LLFloaterPostcard* self = (LLFloaterPostcard *)data; if(self) diff --git a/indra/newview/llfloaterpostcard.h b/indra/newview/llfloaterpostcard.h index 78da8b55d8..287d34c706 100644 --- a/indra/newview/llfloaterpostcard.h +++ b/indra/newview/llfloaterpostcard.h @@ -65,7 +65,7 @@ public: static void updateUserInfo(const char *email); - static void onMsgFormFocusRecieved(LLUICtrl* receiver, void* data); + static void onMsgFormFocusRecieved(LLFocusableElement* receiver, void* data); static void missingSubjMsgAlertCallback(S32 option, void* data); void sendPostcard(); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 3306142856..eaf7832eab 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -161,50 +161,55 @@ bool estate_dispatch_initialized = false; /// LLFloaterRegionInfo ///---------------------------------------------------------------------------- -LLFloaterRegionInfo* LLFloaterRegionInfo::sInstance = NULL; //S32 LLFloaterRegionInfo::sRequestSerial = 0; LLUUID LLFloaterRegionInfo::sRequestInvoice; -LLFloaterRegionInfo::LLFloaterRegionInfo(const LLRect& rect) : - LLFloater("regioninfo", rect, "Region/Estate") +LLFloaterRegionInfo::LLFloaterRegionInfo(const LLSD& seed) { - LLRect tr(0, rect.getHeight() - LLFLOATER_HEADER_SIZE, rect.getWidth(), 0); - mTab = new LLTabContainer("tab", tr, LLTabContainer::TOP, NULL,NULL,""); - mTab->setBorderVisible(FALSE); - addChild(mTab); + gUICtrlFactory->buildFloater(this, "floater_region_info.xml", NULL, FALSE); +} + +BOOL LLFloaterRegionInfo::postBuild() +{ + mTab = gUICtrlFactory->getTabContainerByName(this, "region_panels"); // contruct the panels - LLPanel* panel; + LLPanelRegionInfo* panel; panel = new LLPanelRegionGeneralInfo; - mInfoPanels.push_back((LLPanelRegionInfo*)panel); + mInfoPanels.push_back(panel); gUICtrlFactory->buildPanel(panel, "panel_region_general.xml"); mTab->addTabPanel(panel, panel->getLabel(), TRUE); panel = new LLPanelRegionDebugInfo; - mInfoPanels.push_back((LLPanelRegionInfo*)panel); + mInfoPanels.push_back(panel); gUICtrlFactory->buildPanel(panel, "panel_region_debug.xml"); mTab->addTabPanel(panel, panel->getLabel(), FALSE); panel = new LLPanelRegionTextureInfo; - mInfoPanels.push_back((LLPanelRegionInfo*)panel); + mInfoPanels.push_back(panel); gUICtrlFactory->buildPanel(panel, "panel_region_texture.xml"); mTab->addTabPanel(panel, panel->getLabel(), FALSE); panel = new LLPanelRegionTerrainInfo; - mInfoPanels.push_back((LLPanelRegionInfo*)panel); + mInfoPanels.push_back(panel); gUICtrlFactory->buildPanel(panel, "panel_region_terrain.xml"); mTab->addTabPanel(panel, panel->getLabel(), FALSE); panel = new LLPanelEstateInfo; - mInfoPanels.push_back((LLPanelRegionInfo*)panel); + mInfoPanels.push_back(panel); gUICtrlFactory->buildPanel(panel, "panel_region_estate.xml"); mTab->addTabPanel(panel, panel->getLabel(), FALSE); panel = new LLPanelEstateCovenant; - mInfoPanels.push_back((LLPanelRegionInfo*)panel); + mInfoPanels.push_back(panel); gUICtrlFactory->buildPanel(panel, "panel_region_covenant.xml"); mTab->addTabPanel(panel, panel->getLabel(), FALSE); + gMessageSystem->setHandlerFunc( + "EstateOwnerMessage", + &processEstateOwnerRequest); + + return TRUE; } LLFloaterRegionInfo::~LLFloaterRegionInfo() @@ -212,23 +217,20 @@ LLFloaterRegionInfo::~LLFloaterRegionInfo() sInstance = NULL; } -// static -void LLFloaterRegionInfo::show(LLViewerRegion* region) +void LLFloaterRegionInfo::onOpen() { - if (!sInstance) - { - LLRect rect = gSavedSettings.getRect("FloaterRegionInfo"); - S32 left, top; - gFloaterView->getNewFloaterPosition(&left, &top); - rect.translate(left,top); - sInstance = new LLFloaterRegionInfo(rect); - gMessageSystem->setHandlerFunc( - "EstateOwnerMessage", - &processEstateOwnerRequest); - } - sInstance->open(); /* Flawfinder: ignore*/ - sInstance->refreshFromRegion(region); + LLRect rect = gSavedSettings.getRect("FloaterRegionInfo"); + S32 left, top; + gFloaterView->getNewFloaterPosition(&left, &top); + rect.translate(left,top); + + requestRegionInfo(); + refreshFromRegion(gAgent.getRegion()); + LLFloater::onOpen(); +} +void LLFloaterRegionInfo::requestRegionInfo() +{ // Must allow anyone to request the RegionInfo data // so non-owners/non-gods can see the values. // Therefore can't use an EstateOwnerMessage JC @@ -242,18 +244,6 @@ void LLFloaterRegionInfo::show(LLViewerRegion* region) } // static -void LLFloaterRegionInfo::show(void*) -{ - show(gAgent.getRegion()); -} - -// static -LLFloaterRegionInfo* LLFloaterRegionInfo::getInstance() -{ - return sInstance; -} - -// static void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**) { static LLDispatcher dispatch; @@ -264,7 +254,7 @@ void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**) LLPanelEstateInfo::initDispatch(dispatch); } - LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(sInstance, "tab"); + LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(sInstance, "region_panels"); if (!tab) return; LLPanelEstateInfo* panel = (LLPanelEstateInfo*)LLUICtrlFactory::getPanelByName(tab, "Estate"); @@ -293,7 +283,7 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) llinfos << "LLFloaterRegionInfo::processRegionInfo" << llendl; if(!sInstance) return; - LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(sInstance, "tab"); + LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(sInstance, "region_panels"); if(!tab) return; // extract message @@ -376,7 +366,7 @@ LLPanelEstateInfo* LLFloaterRegionInfo::getPanelEstate() { LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance(); if (!floater) return NULL; - LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(floater, "tab"); + LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(floater, "region_panels"); if (!tab) return NULL; LLPanelEstateInfo* panel = (LLPanelEstateInfo*)LLUICtrlFactory::getPanelByName(tab,"Estate"); return panel; @@ -387,7 +377,7 @@ LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant() { LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance(); if (!floater) return NULL; - LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(floater, "tab"); + LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(floater, "region_panels"); if (!tab) return NULL; LLPanelEstateCovenant* panel = (LLPanelEstateCovenant*)LLUICtrlFactory::getPanelByName(tab, "Covenant"); return panel; @@ -1241,7 +1231,7 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance(); if (!floater) return true; - LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(floater, "tab"); + LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(floater, "region_panels"); if (!tab) return true; LLPanelEstateInfo* panel = (LLPanelEstateInfo*)LLUICtrlFactory::getPanelByName(tab, "Estate"); @@ -2803,7 +2793,7 @@ bool LLDispatchSetEstateOwner::operator()( LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance(); if (!floater) return true; - LLTabContainer* tab = (LLTabContainer*)(floater->getChildByName("tab")); + LLTabContainer* tab = (LLTabContainer*)(floater->getChildByName("region_panels")); if (!tab) return true; LLPanelEstateInfo* panel = (LLPanelEstateInfo*)(tab->getChildByName("Estate")); diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index abf4789b6d..6f9ed1fc34 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -58,14 +58,15 @@ class LLPanelRegionTerrainInfo; class LLPanelEstateInfo; class LLPanelEstateCovenant; -class LLFloaterRegionInfo : public LLFloater +class LLFloaterRegionInfo : public LLFloater, public LLUISingleton<LLFloaterRegionInfo> { + friend class LLUISingleton<LLFloaterRegionInfo>; public: ~LLFloaterRegionInfo(); - static void show(LLViewerRegion* region); - static void show(void*); - static LLFloaterRegionInfo* getInstance(); + /*virtual*/ void onOpen(); + /*virtual*/ BOOL postBuild(); + static void processEstateOwnerRequest(LLMessageSystem* msg, void**); // get and process region info if necessary. @@ -82,15 +83,14 @@ public: // from LLPanel virtual void refresh(); + void requestRegionInfo(); + protected: - LLFloaterRegionInfo(const LLRect& rect); + LLFloaterRegionInfo(const LLSD& seed); void refreshFromRegion(LLViewerRegion* region); - // static data - static LLFloaterRegionInfo* sInstance; - // member data - LLTabContainer* mTab; + LLTabContainerCommon* mTab; typedef std::vector<LLPanelRegionInfo*> info_panels_t; info_panels_t mInfoPanels; //static S32 sRequestSerial; // serial # of last EstateOwnerRequest diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp index 9d600befdb..80a686d162 100644 --- a/indra/newview/llfloaterscriptdebug.cpp +++ b/indra/newview/llfloaterscriptdebug.cpp @@ -177,7 +177,7 @@ LLFloaterScriptDebugOutput::LLFloaterScriptDebugOutput(const LLUUID& object_id) mHistoryEditor->setWordWrap( TRUE ); mHistoryEditor->setFollowsAll(); mHistoryEditor->setEnabled( FALSE ); - mHistoryEditor->setTakesFocus( TRUE ); // We want to be able to cut or copy from the history. + mHistoryEditor->setTabStop( TRUE ); // We want to be able to cut or copy from the history. addChild(mHistoryEditor); } @@ -200,7 +200,7 @@ void LLFloaterScriptDebugOutput::init(const LLString& title, BOOL resizable, mHistoryEditor->setWordWrap( TRUE ); mHistoryEditor->setFollowsAll(); mHistoryEditor->setEnabled( FALSE ); - mHistoryEditor->setTakesFocus( TRUE ); // We want to be able to cut or copy from the history. + mHistoryEditor->setTabStop( TRUE ); // We want to be able to cut or copy from the history. addChild(mHistoryEditor); } diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 22581c6576..d03ce373cc 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -942,7 +942,7 @@ void commit_select_component(LLUICtrl *ctrl, void *data) //forfeit focus if (gFocusMgr.childHasKeyboardFocus(floaterp)) { - gFocusMgr.setKeyboardFocus(NULL, NULL); + gFocusMgr.setKeyboardFocus(NULL); } BOOL select_individuals = floaterp->mCheckSelectIndividual->get(); @@ -992,4 +992,5 @@ void LLFloaterTools::setEditTool(void* tool_pointer) void LLFloaterTools::onFocusReceived() { gToolMgr->setCurrentToolset(gBasicToolset); + LLFloater::onFocusReceived(); } diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index e3f236becc..6bbb748a10 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -257,8 +257,8 @@ void LLFloaterTopObjects::updateSelectionInfo() std::string object_id_string = object_id.asString(); childSetValue("id_editor", LLSD(object_id_string)); - childSetValue("object_name_editor", list->getFirstSelected()->getColumn(1)->getText()); - childSetValue("owner_name_editor", list->getFirstSelected()->getColumn(2)->getText()); + childSetValue("object_name_editor", list->getFirstSelected()->getColumn(1)->getValue().asString()); + childSetValue("owner_name_editor", list->getFirstSelected()->getColumn(2)->getValue().asString()); } // static @@ -451,8 +451,8 @@ void LLFloaterTopObjects::showBeacon() LLScrollListItem* first_selected = list->getFirstSelected(); if (!first_selected) return; - LLString name = first_selected->getColumn(1)->getText(); - LLString pos_string = first_selected->getColumn(3)->getText(); + LLString name = first_selected->getColumn(1)->getValue().asString(); + LLString pos_string = first_selected->getColumn(3)->getValue().asString(); F32 x, y, z; S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z); diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 4c03a15619..b1bbb341fd 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -234,7 +234,7 @@ BOOL LLFloaterWorldMap::postBuild() childSetAction("DoSearch", onLocationCommit, this); - childSetFocusChangedCallback("location", updateSearchEnabled); + childSetFocusChangedCallback("location", onLocationFocusChanged, this); LLLineEditor *location_editor = LLUICtrlFactory::getLineEditorByName(this, "location"); if (location_editor) @@ -1221,6 +1221,12 @@ void LLFloaterWorldMap::onAvatarComboCommit( LLUICtrl* ctrl, void* userdata ) } } +//static +void LLFloaterWorldMap::onLocationFocusChanged( LLFocusableElement* focus, void* userdata ) +{ + updateSearchEnabled((LLUICtrl*)focus, userdata); +} + // static void LLFloaterWorldMap::updateSearchEnabled( LLUICtrl* ctrl, void* userdata ) { diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index c069b40929..6f3c583557 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -153,6 +153,7 @@ protected: void teleportToAvatar(); static void updateSearchEnabled( LLUICtrl* ctrl, void* userdata ); + static void onLocationFocusChanged( LLFocusableElement* ctrl, void* userdata ); static void onLocationCommit( void* userdata ); static void onCommitLocation( LLUICtrl* ctrl, void* userdata ); static void onCommitSearchResult( LLUICtrl* ctrl, void* userdata ); diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 2577474e24..deffca3b79 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -94,7 +94,7 @@ void copy_selected_item(void* user_data); void open_selected_items(void* user_data); void properties_selected_items(void* user_data); void paste_items(void* user_data); -void renamer_focus_lost( LLUICtrl* handler, void* user_data ); +void renamer_focus_lost( LLFocusableElement* handler, void* user_data ); ///---------------------------------------------------------------------------- /// Class LLFolderViewItem @@ -693,7 +693,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) // Release keyboard focus, so that if stuff is dropped into the // world, pressing the delete key won't blow away the inventory // item. - gViewerWindow->setKeyboardFocus(NULL, NULL); + gViewerWindow->setKeyboardFocus(NULL); return gToolDragAndDrop->handleHover( x, y, mask ); } @@ -3164,7 +3164,7 @@ void LLFolderView::draw() } if(gViewerWindow->hasKeyboardFocus(this) && !getVisible()) { - gViewerWindow->setKeyboardFocus( NULL, NULL ); + gViewerWindow->setKeyboardFocus( NULL ); } // while dragging, update selection rendering to reflect single/multi drag status @@ -3656,7 +3656,7 @@ void LLFolderView::startRenamingSelectedItem( void ) mRenamer->setVisible( TRUE ); // set focus will fail unless item is visible mRenamer->setFocus( TRUE ); - mRenamer->setFocusLostCallback(renamer_focus_lost); + mRenamer->setLostTopCallback(onRenamerLost); gViewerWindow->setTopCtrl( mRenamer ); } } @@ -3730,7 +3730,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent ) { if( gViewerWindow->childHasKeyboardFocus( this ) ) { - gViewerWindow->setKeyboardFocus( NULL, NULL ); + gViewerWindow->setKeyboardFocus( NULL ); } } mSearchString.clear(); @@ -4438,12 +4438,10 @@ bool LLInventorySort::operator()(LLFolderViewItem* a, LLFolderViewItem* b) } } -void renamer_focus_lost( LLUICtrl* ctrl, void* userdata) +//static +void LLFolderView::onRenamerLost( LLUICtrl* renamer, void* user_data) { - if( ctrl ) - { - ctrl->setVisible( FALSE ); - } + renamer->setVisible(FALSE); } void delete_selected_item(void* user_data) diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index dd0dd21705..9fcf94d802 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -876,6 +876,8 @@ protected: LLScrollableContainerView* mScrollContainer; // NULL if this is not a child of a scroll container. static void commitRename( LLUICtrl* renamer, void* user_data ); + static void onRenamerLost( LLUICtrl* renamer, void* user_data); + void finishRenamingItem( void ); void revertRenamingItem( void ); diff --git a/indra/newview/llhudview.cpp b/indra/newview/llhudview.cpp index e40e84b9da..7f549bb2eb 100644 --- a/indra/newview/llhudview.cpp +++ b/indra/newview/llhudview.cpp @@ -52,8 +52,8 @@ LLHUDView *gHUDView = NULL; const S32 HUD_ARROW_SIZE = 32; -LLHUDView::LLHUDView(const std::string& name, const LLRect& rect) -: LLView(name, rect, FALSE) +LLHUDView::LLHUDView() +: LLPanel() { } LLHUDView::~LLHUDView() diff --git a/indra/newview/llhudview.h b/indra/newview/llhudview.h index b2353ad5df..cbefdc121e 100644 --- a/indra/newview/llhudview.h +++ b/indra/newview/llhudview.h @@ -32,16 +32,16 @@ #ifndef LL_LLHUDVIEW_H #define LL_LLHUDVIEW_H -#include "llview.h" +#include "llpanel.h" #include "v4color.h" class LLVector3d; class LLHUDView -: public LLView +: public LLPanel { public: - LLHUDView(const std::string& name, const LLRect& rect); + LLHUDView(); virtual ~LLHUDView(); virtual EWidgetType getWidgetType() const; diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 810d3a26a1..b1fefc4f5d 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -63,6 +63,7 @@ #include "llviewerstats.h" #include "llviewercontrol.h" #include "llvieweruictrlfactory.h" +#include "llviewerwindow.h" #include "lllogchat.h" #include "llfloaterhtml.h" #include "llweb.h" @@ -92,10 +93,14 @@ static LLString sSessionStartString = "Starting session with [NAME] please wait. LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap; LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap; LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL; +LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL; -void session_starter_helper(const LLUUID& temp_session_id, - const LLUUID& other_participant_id, - EInstantMessage im_type) +BOOL LLVoiceChannel::sSuspended = FALSE; + +void session_starter_helper( + const LLUUID& temp_session_id, + const LLUUID& other_participant_id, + EInstantMessage im_type) { LLMessageSystem *msg = gMessageSystem; @@ -122,47 +127,111 @@ void session_starter_helper(const LLUUID& temp_session_id, msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); } +void start_deprecated_conference_chat( + const LLUUID& temp_session_id, + const LLUUID& creator_id, + const LLUUID& other_participant_id, + const LLSD& agents_to_invite) +{ + U8* bucket; + U8* pos; + S32 count; + S32 bucket_size; + + // *FIX: this could suffer from endian issues + count = agents_to_invite.size(); + bucket_size = UUID_BYTES * count; + bucket = new U8[bucket_size]; + pos = bucket; + + for(S32 i = 0; i < count; ++i) + { + LLUUID agent_id = agents_to_invite[i].asUUID(); + + memcpy(pos, &agent_id, UUID_BYTES); + pos += UUID_BYTES; + } + + session_starter_helper( + temp_session_id, + other_participant_id, + IM_SESSION_CONFERENCE_START); + + gMessageSystem->addBinaryDataFast( + _PREHASH_BinaryBucket, + bucket, + bucket_size); + + gAgent.sendReliableMessage(); + + delete[] bucket; +} + +class LLStartConferenceChatResponder : public LLHTTPClient::Responder +{ +public: + LLStartConferenceChatResponder( + const LLUUID& temp_session_id, + const LLUUID& creator_id, + const LLUUID& other_participant_id, + const LLSD& agents_to_invite) + { + mTempSessionID = temp_session_id; + mCreatorID = creator_id; + mOtherParticipantID = other_participant_id; + mAgents = agents_to_invite; + } + + virtual void error(U32 statusNum, const std::string& reason) + { + //try an "old school" way. + if ( statusNum == 400 ) + { + start_deprecated_conference_chat( + mTempSessionID, + mCreatorID, + mOtherParticipantID, + mAgents); + } + + //else throw an error back to the client? + //in theory we should have just have these error strings + //etc. set up in this file as opposed to the IMMgr, + //but the error string were unneeded here previously + //and it is not worth the effort switching over all + //the possible different language translations + } + +private: + LLUUID mTempSessionID; + LLUUID mCreatorID; + LLUUID mOtherParticipantID; + + LLSD mAgents; +}; + // Returns true if any messages were sent, false otherwise. // Is sort of equivalent to "does the server need to do anything?" -bool send_start_session_messages(const LLUUID& temp_session_id, - const LLUUID& other_participant_id, - const LLDynamicArray<LLUUID>& ids, - EInstantMessage dialog) +bool send_start_session_messages( + const LLUUID& temp_session_id, + const LLUUID& other_participant_id, + const LLDynamicArray<LLUUID>& ids, + EInstantMessage dialog) { - if ( (dialog == IM_SESSION_GROUP_START) || - (dialog == IM_SESSION_CONFERENCE_START) ) + if ( dialog == IM_SESSION_GROUP_START ) { - S32 count = ids.size(); - S32 bucket_size = UUID_BYTES * count; - U8* bucket; - U8* pos; - - session_starter_helper(temp_session_id, - other_participant_id, - dialog); + session_starter_helper( + temp_session_id, + other_participant_id, + dialog); switch(dialog) { case IM_SESSION_GROUP_START: - gMessageSystem->addBinaryDataFast(_PREHASH_BinaryBucket, - EMPTY_BINARY_BUCKET, - EMPTY_BINARY_BUCKET_SIZE); - break; - case IM_SESSION_CONFERENCE_START: - bucket = new U8[bucket_size]; - pos = bucket; - - // *FIX: this could suffer from endian issues - for(S32 i = 0; i < count; ++i) - { - memcpy(pos, &(ids.get(i)), UUID_BYTES); - pos += UUID_BYTES; - } - gMessageSystem->addBinaryDataFast(_PREHASH_BinaryBucket, - bucket, - bucket_size); - delete[] bucket; - + gMessageSystem->addBinaryDataFast( + _PREHASH_BinaryBucket, + EMPTY_BINARY_BUCKET, + EMPTY_BINARY_BUCKET_SIZE); break; default: break; @@ -171,6 +240,44 @@ bool send_start_session_messages(const LLUUID& temp_session_id, return true; } + else if ( dialog == IM_SESSION_CONFERENCE_START ) + { + LLSD agents; + for (int i = 0; i < (S32) ids.size(); i++) + { + agents.append(ids.get(i)); + } + + //we have a new way of starting conference calls now + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + std::string url = region->getCapability( + "ChatSessionRequest"); + LLSD data; + data["method"] = "start conference"; + data["session-id"] = temp_session_id; + + data["params"] = agents; + + LLHTTPClient::post( + url, + data, + new LLStartConferenceChatResponder( + temp_session_id, + gAgent.getID(), + other_participant_id, + data["params"])); + } + else + { + start_deprecated_conference_chat( + temp_session_id, + gAgent.getID(), + other_participant_id, + agents); + } + } return false; } @@ -194,8 +301,20 @@ void LLVoiceCallCapResponder::error(U32 status, const std::string& reason) << status << ": " << reason << ")" << llendl; LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID); - if (channelp) + if ( channelp ) { + if ( 403 == status ) + { + LLNotifyBox::showXml( + "VoiceNotAllowed", + channelp->getNotifyArgs()); + } + else + { + LLNotifyBox::showXml( + "VoiceCallGenericError", + channelp->getNotifyArgs()); + } channelp->deactivate(); } } @@ -242,10 +361,6 @@ LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const LLString& session LLVoiceChannel::~LLVoiceChannel() { - // CANNOT do this here, since it will crash on quit in the LLVoiceChannelProximal singleton destructor. - // Do it in all other subclass destructors instead. - // deactivate(); - // Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed. if(gVoiceClient) { @@ -266,7 +381,19 @@ void LLVoiceChannel::setChannelInfo( if (mState == STATE_NO_CHANNEL_INFO) { - if(!mURI.empty() && !mCredentials.empty()) + if (mURI.empty()) + { + LLNotifyBox::showXml("VoiceChannelJoinFailed", mNotifyArgs); + llwarns << "Received empty URI for channel " << mSessionName << llendl; + deactivate(); + } + else if (mCredentials.empty()) + { + LLNotifyBox::showXml("VoiceChannelJoinFailed", mNotifyArgs); + llwarns << "Received empty credentials for channel " << mSessionName << llendl; + deactivate(); + } + else { setState(STATE_READY); @@ -279,12 +406,6 @@ void LLVoiceChannel::setChannelInfo( activate(); } } - else - { - //*TODO: notify user - llwarns << "Received invalid credentials for channel " << mSessionName << llendl; - deactivate(); - } } } @@ -325,7 +446,7 @@ void LLVoiceChannel::handleStatusChange(EStatusType type) } break; case STATUS_LEFT_CHANNEL: - if (callStarted() && !mIgnoreNextSessionLeave) + if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended) { // if forceably removed from channel // update the UI and revert to default channel @@ -496,6 +617,38 @@ void LLVoiceChannel::initClass() sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance(); } + +//static +void LLVoiceChannel::suspend() +{ + if (!sSuspended) + { + sSuspendedVoiceChannel = sCurrentVoiceChannel; + sSuspended = TRUE; + } +} + +//static +void LLVoiceChannel::resume() +{ + if (sSuspended) + { + if (gVoiceClient->voiceEnabled()) + { + if (sSuspendedVoiceChannel) + { + sSuspendedVoiceChannel->activate(); + } + else + { + LLVoiceChannelProximal::getInstance()->activate(); + } + } + sSuspended = FALSE; + } +} + + // // LLVoiceChannelGroup // @@ -507,11 +660,6 @@ LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const LLStrin mIsRetrying = FALSE; } -LLVoiceChannelGroup::~LLVoiceChannelGroup() -{ - deactivate(); -} - void LLVoiceChannelGroup::deactivate() { if (callStarted()) @@ -635,6 +783,7 @@ void LLVoiceChannelGroup::handleError(EStatusType status) } break; + case ERROR_UNKNOWN: default: break; @@ -677,11 +826,6 @@ LLVoiceChannelProximal::LLVoiceChannelProximal() : activate(); } -LLVoiceChannelProximal::~LLVoiceChannelProximal() -{ - // DO NOT call deactivate() here, since this will only happen at atexit() time. -} - BOOL LLVoiceChannelProximal::isActive() { return callStarted() && LLVoiceClient::getInstance()->inProximalChannel(); @@ -725,6 +869,9 @@ void LLVoiceChannelProximal::handleStatusChange(EStatusType status) case STATUS_LEFT_CHANNEL: // do not notify user when leaving proximal channel return; + case STATUS_VOICE_DISABLED: + gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs); + return; default: break; } @@ -762,29 +909,26 @@ void LLVoiceChannelProximal::deactivate() } } + // // LLVoiceChannelP2P // LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const LLString& session_name, const LLUUID& other_user_id) : LLVoiceChannelGroup(session_id, session_name), - mOtherUserID(other_user_id) + mOtherUserID(other_user_id), + mReceivedCall(FALSE) { // make sure URI reflects encoded version of other user's agent id setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id)); } -LLVoiceChannelP2P::~LLVoiceChannelP2P() -{ - deactivate(); -} - void LLVoiceChannelP2P::handleStatusChange(EStatusType type) { // status updates switch(type) { case STATUS_LEFT_CHANNEL: - if (callStarted() && !mIgnoreNextSessionLeave) + if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended) { if (mState == STATE_RINGING) { @@ -832,6 +976,7 @@ void LLVoiceChannelP2P::activate() // no session handle yet, we're starting the call if (mSessionHandle.empty()) { + mReceivedCall = FALSE; LLVoiceClient::getInstance()->callUser(mOtherUserID); } // otherwise answering the call @@ -879,24 +1024,37 @@ void LLVoiceChannelP2P::setSessionHandle(const LLString& handle) mSessionHandle = handle; // The URI of a p2p session should always be the other end's SIP URI. setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID)); - + mReceivedCall = TRUE; + if (needs_activate) { activate(); } } +void LLVoiceChannelP2P::setState(EState state) +{ + // you only "answer" voice invites in p2p mode + // so provide a special purpose message here + if (mReceivedCall && state == STATE_RINGING) + { + gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs); + mState = state; + return; + } + LLVoiceChannel::setState(state); +} + + // // LLFloaterIMPanel // LLFloaterIMPanel::LLFloaterIMPanel( - const std::string& name, - const LLRect& rect, const std::string& session_label, const LLUUID& session_id, const LLUUID& other_participant_id, EInstantMessage dialog) : - LLFloater(name, rect, session_label), + LLFloater(session_label, LLRect(), session_label), mInputEditor(NULL), mHistoryEditor(NULL), mSessionUUID(session_id), @@ -909,6 +1067,7 @@ LLFloaterIMPanel::LLFloaterIMPanel( mOtherTyping(FALSE), mTypingLineStartIndex(0), mSentTypingState(TRUE), + mNumUnreadMessages(0), mShowSpeakersOnConnect(TRUE), mAutoConnect(FALSE), mSpeakerPanel(NULL), @@ -919,14 +1078,12 @@ LLFloaterIMPanel::LLFloaterIMPanel( } LLFloaterIMPanel::LLFloaterIMPanel( - const std::string& name, - const LLRect& rect, const std::string& session_label, const LLUUID& session_id, const LLUUID& other_participant_id, const LLDynamicArray<LLUUID>& ids, EInstantMessage dialog) : - LLFloater(name, rect, session_label), + LLFloater(session_label, LLRect(), session_label), mInputEditor(NULL), mHistoryEditor(NULL), mSessionUUID(session_id), @@ -952,13 +1109,15 @@ LLFloaterIMPanel::LLFloaterIMPanel( void LLFloaterIMPanel::init(const LLString& session_label) { + mSessionLabel = session_label; + LLString xml_filename; switch(mDialog) { case IM_SESSION_GROUP_START: mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this); xml_filename = "floater_instant_message_group.xml"; - mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, session_label); + mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel); break; case IM_SESSION_INVITE: mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this); @@ -970,21 +1129,21 @@ void LLFloaterIMPanel::init(const LLString& session_label) { xml_filename = "floater_instant_message_ad_hoc.xml"; } - mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, session_label); + mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel); break; case IM_SESSION_P2P_INVITE: xml_filename = "floater_instant_message.xml"; - mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, session_label, mOtherParticipantUUID); + mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID); break; case IM_SESSION_CONFERENCE_START: mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this); xml_filename = "floater_instant_message_ad_hoc.xml"; - mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, session_label); + mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel); break; // just received text from another user case IM_NOTHING_SPECIAL: xml_filename = "floater_instant_message.xml"; - mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, session_label, mOtherParticipantUUID); + mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID); break; default: llwarns << "Unknown session type" << llendl; @@ -999,15 +1158,14 @@ void LLFloaterIMPanel::init(const LLString& session_label) &getFactoryMap(), FALSE); - setLabel(session_label); - setTitle(session_label); + setTitle(mSessionLabel); mInputEditor->setMaxTextLength(1023); // enable line history support for instant message bar mInputEditor->setEnableLineHistory(TRUE); if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) { - LLLogChat::loadHistory(session_label, + LLLogChat::loadHistory(mSessionLabel, &chatFromLogFile, (void *)this); } @@ -1060,16 +1218,12 @@ BOOL LLFloaterIMPanel::postBuild() { requires("chat_editor", WIDGET_TYPE_LINE_EDITOR); requires("im_history", WIDGET_TYPE_TEXT_EDITOR); - requires("live_help_dialog", WIDGET_TYPE_TEXT_BOX); - requires("title_string", WIDGET_TYPE_TEXT_BOX); - requires("typing_start_string", WIDGET_TYPE_TEXT_BOX); - requires("session_start_string", WIDGET_TYPE_TEXT_BOX); if (checkRequirements()) { mInputEditor = LLUICtrlFactory::getLineEditorByName(this, "chat_editor"); - mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived ); - mInputEditor->setFocusLostCallback( onInputEditorFocusLost ); + mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived, this ); + mInputEditor->setFocusLostCallback( onInputEditorFocusLost, this ); mInputEditor->setKeystrokeCallback( onInputEditorKeystroke ); mInputEditor->setCommitCallback( onCommitChat ); mInputEditor->setCallbackUserData(this); @@ -1084,6 +1238,7 @@ BOOL LLFloaterIMPanel::postBuild() childSetAction("send_btn", onClickSend, this); childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this); + childSetAction("moderator_kick_speaker", onKickSpeaker, this); //LLButton* close_btn = LLUICtrlFactory::getButtonByName(this, "close_btn"); //close_btn->setClickedCallback(&LLFloaterIMPanel::onClickClose, this); @@ -1094,17 +1249,11 @@ BOOL LLFloaterIMPanel::postBuild() { childSetEnabled("profile_btn", FALSE); } - LLTextBox* title = LLUICtrlFactory::getTextBoxByName(this, "title_string"); - sTitleString = title->getText(); - - LLTextBox* typing_start = LLUICtrlFactory::getTextBoxByName(this, "typing_start_string"); - - sTypingStartString = typing_start->getText(); - - LLTextBox* session_start = LLUICtrlFactory::getTextBoxByName( - this, - "session_start_string"); - sSessionStartString = session_start->getText(); + + sTitleString = getFormattedUIString("title_string"); + sTypingStartString = getFormattedUIString("typing_start_string"); + sSessionStartString = getFormattedUIString("session_start_string"); + if (mSpeakerPanel) { mSpeakerPanel->refreshSpeakers(); @@ -1112,7 +1261,7 @@ BOOL LLFloaterIMPanel::postBuild() if (mDialog == IM_NOTHING_SPECIAL) { - childSetCommitCallback("mute_btn", onClickMuteVoice, this); + childSetAction("mute_btn", onClickMuteVoice, this); childSetCommitCallback("speaker_volume", onVolumeChange, this); } @@ -1131,7 +1280,7 @@ void* LLFloaterIMPanel::createSpeakersPanel(void* data) } //static -void LLFloaterIMPanel::onClickMuteVoice(LLUICtrl* source, void* user_data) +void LLFloaterIMPanel::onClickMuteVoice(void* user_data) { LLFloaterIMPanel* floaterp = (LLFloaterIMPanel*)user_data; if (floaterp) @@ -1171,10 +1320,22 @@ void LLFloaterIMPanel::draw() && LLVoiceClient::voiceEnabled(); // hide/show start call and end call buttons - childSetVisible("end_call_btn", mVoiceChannel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); - childSetVisible("start_call_btn", mVoiceChannel->getState() < LLVoiceChannel::STATE_CALL_STARTED); + childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); + childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() < LLVoiceChannel::STATE_CALL_STARTED); childSetEnabled("start_call_btn", enable_connect); childSetEnabled("send_btn", !childGetValue("chat_editor").asString().empty()); + + LLPointer<LLSpeaker> self_speaker = mSpeakers->findSpeaker(gAgent.getID()); + if (self_speaker.notNull() && self_speaker->mModeratorMutedText) + { + mInputEditor->setEnabled(FALSE); + mInputEditor->setLabel(getFormattedUIString("muted_text_label")); + } + else + { + mInputEditor->setEnabled(TRUE); + mInputEditor->setLabel(getFormattedUIString("default_text_label")); + } if (mAutoConnect && enable_connect) { @@ -1215,11 +1376,11 @@ void LLFloaterIMPanel::draw() else { // refresh volume and mute checkbox - childSetEnabled("speaker_volume", mVoiceChannel->isActive()); + childSetVisible("speaker_volume", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive()); childSetValue("speaker_volume", gVoiceClient->getUserVolume(mOtherParticipantUUID)); childSetValue("mute_btn", gMuteListp->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat)); - childSetEnabled("mute_btn", mVoiceChannel->isActive()); + childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive()); } LLFloater::draw(); } @@ -1235,7 +1396,6 @@ public: void error(U32 statusNum, const std::string& reason) { llinfos << "Error inviting all agents to session" << llendl; - //throw something back to the viewer here? } @@ -1243,6 +1403,48 @@ private: LLUUID mSessionID; }; +class LLSessionImmediateInviteResponder : public LLHTTPClient::Responder +{ +public: + LLSessionImmediateInviteResponder( + const LLUUID& session_id, + const std::string& chat_req_url, + const LLSD& post_data) + { + mSessionID = session_id; + mURL = chat_req_url; + mPostData = post_data; + } + + void error(U32 statusNum, const std::string& reason) + { + if ( statusNum == 400 ) + { + //hrm 400 indicates invalid parameters...more + //than likely the method doesn't exist + //so try a soon to be deprecated old school way of doing this + mPostData["method"] = "invite"; + + LLHTTPClient::post( + mURL, + mPostData, + new LLSessionInviteResponder(mSessionID)); + } + else + { + //throw something back to the viewer here? + llinfos << "Error inviting all agents to session" << llendl; + } + } + +private: + LLUUID mSessionID; + LLSD mPostData; + + std::string mURL; +}; + + BOOL LLFloaterIMPanel::inviteToSession(const LLDynamicArray<LLUUID>& ids) { LLViewerRegion* region = gAgent.getRegion(); @@ -1267,12 +1469,15 @@ BOOL LLFloaterIMPanel::inviteToSession(const LLDynamicArray<LLUUID>& ids) data["params"].append(ids.get(i)); } - data["method"] = "invite"; + data["method"] = "immediate invite"; data["session-id"] = mSessionUUID; LLHTTPClient::post( url, data, - new LLSessionInviteResponder(mSessionUUID)); + new LLSessionImmediateInviteResponder( + mSessionUUID, + url, + data)); } else @@ -1289,6 +1494,15 @@ BOOL LLFloaterIMPanel::inviteToSession(const LLDynamicArray<LLUUID>& ids) void LLFloaterIMPanel::addHistoryLine(const LLUUID& source, const std::string &utf8msg, const LLColor4& color, bool log_to_file) { + // start tab flashing when receiving im for background session from user + LLMultiFloater* hostp = getHost(); + if( !isInVisibleChain() + && hostp + && source != gAgent.getID()) + { + hostp->setFloaterFlashing(this, TRUE); + } + addHistoryLine(utf8msg, color, log_to_file); mSpeakers->speakerChatted(source); mSpeakers->setSpeakerTyping(source, FALSE); @@ -1296,14 +1510,6 @@ void LLFloaterIMPanel::addHistoryLine(const LLUUID& source, const std::string &u void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4& color, bool log_to_file) { - LLMultiFloater* hostp = getHost(); - if( !getVisible() && hostp && log_to_file) - { - // Only flash for logged ("real") messages - LLTabContainer* parent = (LLTabContainer*) getParent(); - parent->setTabPanelFlashing( this, TRUE ); - } - // Now we're adding the actual line of text, so erase the // "Foo is typing..." text segment, and the optional timestamp // if it was present. JC @@ -1330,6 +1536,11 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4 LLLogChat::saveHistory(getTitle(),histstr); } + + if (!isInVisibleChain()) + { + mNumUnreadMessages++; + } } @@ -1340,10 +1551,7 @@ void LLFloaterIMPanel::setVisible(BOOL b) LLMultiFloater* hostp = getHost(); if( b && hostp ) { - LLTabContainer* parent = (LLTabContainer*) getParent(); - - // When this tab is displayed, you can stop flashing. - parent->setTabPanelFlashing( this, FALSE ); + hostp->setFloaterFlashing(this, FALSE); /* Don't change containing floater title - leave it "Instant Message" JC LLUIString title = sTitleString; @@ -1392,7 +1600,7 @@ BOOL LLFloaterIMPanel::handleKeyHere( KEY key, MASK mask, BOOL called_from_paren else if ( KEY_ESCAPE == key ) { handled = TRUE; - gFocusMgr.setKeyboardFocus(NULL, NULL); + gFocusMgr.setKeyboardFocus(NULL); // Close talk panel with escape if( !gSavedSettings.getBOOL("PinTalkViewOpen") ) @@ -1573,14 +1781,14 @@ void LLFloaterIMPanel::onCommitChat(LLUICtrl* caller, void* userdata) } // static -void LLFloaterIMPanel::onInputEditorFocusReceived( LLUICtrl* caller, void* userdata ) +void LLFloaterIMPanel::onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ) { LLFloaterIMPanel* self= (LLFloaterIMPanel*) userdata; self->mHistoryEditor->setCursorAndScrollToEnd(); } // static -void LLFloaterIMPanel::onInputEditorFocusLost(LLUICtrl* caller, void* userdata) +void LLFloaterIMPanel::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata) { LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; self->setTyping(FALSE); @@ -1628,6 +1836,14 @@ void LLFloaterIMPanel::onClose(bool app_quitting) destroy(); } +void LLFloaterIMPanel::onVisibilityChange(BOOL new_visibility) +{ + if (new_visibility) + { + mNumUnreadMessages = 0; + } +} + void deliver_message(const std::string& utf8_text, const LLUUID& im_session_id, const LLUUID& other_participant_id, @@ -1739,19 +1955,37 @@ void LLFloaterIMPanel::sendMsg() mSentTypingState = TRUE; } -void LLFloaterIMPanel::updateSpeakersList(LLSD speaker_updates) -{ - mSpeakers->processSpeakerListUpdate(speaker_updates); +void LLFloaterIMPanel::updateSpeakersList(const LLSD& speaker_updates) +{ + mSpeakers->updateSpeakers(speaker_updates); } -void LLFloaterIMPanel::setSpeakersListFromMap(LLSD speaker_map) +void LLFloaterIMPanel::processSessionUpdate(const LLSD& session_update) { - mSpeakers->processSpeakerMap(speaker_map); + if ( + session_update.has("moderated_mode") && + session_update["moderated_mode"].has("voice") ) + { + BOOL voice_moderated = session_update["moderated_mode"]["voice"]; + + if (voice_moderated) + { + setTitle(mSessionLabel + LLString(" ") + getFormattedUIString("moderated_chat_label")); + } + else + { + setTitle(mSessionLabel); + } + + + //update the speakers dropdown too + mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated); + } } -void LLFloaterIMPanel::setSpeakersList(LLSD speaker_list) +void LLFloaterIMPanel::setSpeakers(const LLSD& speaker_list) { - mSpeakers->processSpeakerList(speaker_list); + mSpeakers->setSpeakers(speaker_list); } void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id) @@ -1897,5 +2131,77 @@ void LLFloaterIMPanel::chatFromLogFile(LLString line, void* userdata) //self->addHistoryLine(line, LLColor4::grey, FALSE); self->mHistoryEditor->appendColoredText(line, false, true, LLColor4::grey); +} + +void LLFloaterIMPanel::showSessionStartError( + const std::string& error_string) +{ + //the error strings etc. should be really be static and local + //to this file instead of in the LLFloaterIM + //but they were in llimview.cpp first and unfortunately + //some translations into non English languages already occurred + //thus making it a tad harder to change over to a + //"correct" solution. The best solution + //would be to store all of the misc. strings into + //their own XML file which would be read in by any LLIMPanel + //post build function instead of repeating the same info + //in the group, adhoc and normal IM xml files. + LLString::format_map_t args; + args["[REASON]"] = + LLFloaterIM::sErrorStringsMap[error_string]; + args["[RECIPIENT]"] = getTitle(); + gViewerWindow->alertXml( + "ChatterBoxSessionStartError", + args, + onConfirmForceCloseError, + this); } + +void LLFloaterIMPanel::showSessionEventError( + const std::string& event_string, + const std::string& error_string) +{ + LLString::format_map_t args; + args["[REASON]"] = + LLFloaterIM::sErrorStringsMap[error_string]; + args["[EVENT]"] = + LLFloaterIM::sEventStringsMap[event_string]; + args["[RECIPIENT]"] = getTitle(); + + gViewerWindow->alertXml( + "ChatterBoxSessionEventError", + args); +} + +void LLFloaterIMPanel::showSessionForceClose( + const std::string& reason_string) +{ + LLString::format_map_t args; + + args["[NAME]"] = getTitle(); + args["[REASON]"] = LLFloaterIM::sForceCloseSessionMap[reason_string]; + + gViewerWindow->alertXml( + "ForceCloseChatterBoxSession", + args, + LLFloaterIMPanel::onConfirmForceCloseError, + this); + +} + +//static +void LLFloaterIMPanel::onKickSpeaker(void* user_data) +{ + +} + +void LLFloaterIMPanel::onConfirmForceCloseError(S32 option, void* data) +{ + //only 1 option really + LLFloaterIMPanel* floater = ((LLFloaterIMPanel*) data); + + if ( floater ) floater->close(FALSE); +} + + diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index c1ad18dd3c..ef36ff4a33 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -74,14 +74,20 @@ public: virtual void getChannelInfo(); virtual BOOL isActive(); virtual BOOL callStarted(); + + const LLUUID getSessionID() { return mSessionID; } EState getState() { return mState; } void updateSessionID(const LLUUID& new_session_id); + const LLString::format_map_t& getNotifyArgs() { return mNotifyArgs; } static LLVoiceChannel* getChannelByID(const LLUUID& session_id); static LLVoiceChannel* getChannelByURI(LLString uri); static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; } static void initClass(); + + static void suspend(); + static void resume(); protected: virtual void setState(EState state); @@ -103,13 +109,14 @@ protected: static voice_channel_map_uri_t sVoiceChannelURIMap; static LLVoiceChannel* sCurrentVoiceChannel; + static LLVoiceChannel* sSuspendedVoiceChannel; + static BOOL sSuspended; }; class LLVoiceChannelGroup : public LLVoiceChannel { public: LLVoiceChannelGroup(const LLUUID& session_id, const LLString& session_name); - virtual ~LLVoiceChannelGroup(); /*virtual*/ void handleStatusChange(EStatusType status); /*virtual*/ void handleError(EStatusType status); @@ -132,8 +139,7 @@ class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoice { public: LLVoiceChannelProximal(); - virtual ~LLVoiceChannelProximal(); - + /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); /*virtual*/ void handleStatusChange(EStatusType status); /*virtual*/ void handleError(EStatusType status); @@ -147,7 +153,6 @@ class LLVoiceChannelP2P : public LLVoiceChannelGroup { public: LLVoiceChannelP2P(const LLUUID& session_id, const LLString& session_name, const LLUUID& other_user_id); - virtual ~LLVoiceChannelP2P(); /*virtual*/ void handleStatusChange(EStatusType status); /*virtual*/ void handleError(EStatusType status); @@ -156,9 +161,13 @@ public: void setSessionHandle(const LLString& handle); +protected: + virtual void setState(EState state); + private: LLString mSessionHandle; LLUUID mOtherUserID; + BOOL mReceivedCall; }; class LLFloaterIMPanel : public LLFloater @@ -170,15 +179,11 @@ public: // the default. For example, if you open a session though a // calling card, a new session id will be generated, but the // target_id will be the agent referenced by the calling card. - LLFloaterIMPanel(const std::string& name, - const LLRect& rect, - const std::string& session_label, + LLFloaterIMPanel(const std::string& session_label, const LLUUID& session_id, const LLUUID& target_id, EInstantMessage dialog); - LLFloaterIMPanel(const std::string& name, - const LLRect& rect, - const std::string& session_label, + LLFloaterIMPanel(const std::string& session_label, const LLUUID& session_id, const LLUUID& target_id, const LLDynamicArray<LLUUID>& ids, @@ -189,8 +194,8 @@ public: // Check typing timeout timer. /*virtual*/ void draw(); - /*virtual*/ void onClose(bool app_quitting = FALSE); + /*virtual*/ void onVisibilityChange(BOOL new_visibility); // add target ids to the session. // Return TRUE if successful, otherwise FALSE. @@ -209,14 +214,16 @@ public: void selectNone(); void setVisible(BOOL b); + S32 getNumUnreadMessages() { return mNumUnreadMessages; } + BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, LLString& tooltip_msg); - static void onInputEditorFocusReceived( LLUICtrl* caller, void* userdata ); - static void onInputEditorFocusLost(LLUICtrl* caller, void* userdata); + static void onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ); + static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); static void onCommitChat(LLUICtrl* caller, void* userdata); static void onTabClick( void* userdata ); @@ -229,16 +236,17 @@ public: static void onClickSend( void* userdata ); static void onClickToggleActiveSpeakers( void* userdata ); static void* createSpeakersPanel(void* data); + static void onKickSpeaker(void* user_data); //callbacks for P2P muting and volume control - static void onClickMuteVoice(LLUICtrl* source, void* user_data); + static void onClickMuteVoice(void* user_data); static void onVolumeChange(LLUICtrl* source, void* user_data); const LLUUID& getSessionID() const { return mSessionUUID; } const LLUUID& getOtherParticipantID() const { return mOtherParticipantUUID; } - void updateSpeakersList(LLSD speaker_updates); - void setSpeakersListFromMap(LLSD speaker_list); - void setSpeakersList(LLSD speaker_list); + void updateSpeakersList(const LLSD& speaker_updates); + void processSessionUpdate(const LLSD& update); + void setSpeakers(const LLSD& speaker_list); LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; } EInstantMessage getDialogType() const { return mDialog; } @@ -250,6 +258,15 @@ public: void processIMTyping(const LLIMInfo* im_info, BOOL typing); static void chatFromLogFile(LLString line, void* userdata); + //show error statuses to the user + void showSessionStartError(const std::string& error_string); + void showSessionEventError( + const std::string& event_string, + const std::string& error_string); + void showSessionForceClose(const std::string& reason); + + static void onConfirmForceCloseError(S32 option, void* data); + private: // called by constructors void init(const LLString& session_label); @@ -289,6 +306,7 @@ private: // 911 ==> Gaurdian_Angel_Group_ID ^ gAgent.getID() LLUUID mSessionUUID; + LLString mSessionLabel; LLVoiceChannel* mVoiceChannel; BOOL mSessionInitialized; @@ -318,6 +336,8 @@ private: // Where does the "Starting session..." line start? S32 mSessionStartMsgPos; + S32 mNumUnreadMessages; + BOOL mSentTypingState; BOOL mShowSpeakersOnConnect; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 9c37f1f333..f93f5810c5 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -46,7 +46,6 @@ #include "llagent.h" #include "llcallingcard.h" #include "llchat.h" -#include "llviewerwindow.h" #include "llresmgr.h" #include "llfloaterchat.h" #include "llfloaterchatterbox.h" @@ -65,6 +64,7 @@ #include "llcallingcard.h" #include "lltoolbar.h" #include "llviewermessage.h" +#include "llviewerwindow.h" #include "llnotify.h" #include "llviewerregion.h" @@ -84,11 +84,12 @@ LLIMMgr* gIMMgr = NULL; //*FIXME: make these all either UIStrings or Strings static LLString sOnlyUserMessage; static LLUIString sOfflineMessage; - -static std::map<std::string,LLString> sEventStringsMap; -static std::map<std::string,LLString> sErrorStringsMap; -static std::map<std::string,LLString> sForceCloseSessionMap; static LLUIString sInviteMessage; + +std::map<std::string,LLString> LLFloaterIM::sEventStringsMap; +std::map<std::string,LLString> LLFloaterIM::sErrorStringsMap; +std::map<std::string,LLString> LLFloaterIM::sForceCloseSessionMap; + // // Helper Functions // @@ -160,22 +161,54 @@ BOOL LLFloaterIM::postBuild() sOnlyUserMessage = getFormattedUIString("only_user_message"); sOfflineMessage = getUIString("offline_message"); - sErrorStringsMap["generic"] = - getFormattedUIString("generic_request_error"); - sErrorStringsMap["unverified"] = - getFormattedUIString("insufficient_perms_error"); - sErrorStringsMap["no_user_911"] = - getFormattedUIString("user_no_help"); + sInviteMessage = getUIString("invite_message"); - sEventStringsMap["add"] = - getFormattedUIString("add_session_event"); - sEventStringsMap["message"] = - getFormattedUIString("message_session_event"); + if ( sErrorStringsMap.find("generic") == sErrorStringsMap.end() ) + { + sErrorStringsMap["generic"] = + getFormattedUIString("generic_request_error"); + } - sForceCloseSessionMap["removed"] = - getFormattedUIString("removed_from_group"); + if ( sErrorStringsMap.find("unverified") == + sErrorStringsMap.end() ) + { + sErrorStringsMap["unverified"] = + getFormattedUIString("insufficient_perms_error"); + } + + if ( sErrorStringsMap.end() == + sErrorStringsMap.find("does not exist") ) + { + sErrorStringsMap["does not exist"] = + getFormattedUIString("session_does_not_exist_error"); + } + + if ( sEventStringsMap.end() == sEventStringsMap.find("add") ) + { + sEventStringsMap["add"] = + getFormattedUIString("add_session_event"); + } + + if ( sEventStringsMap.end() == sEventStringsMap.find("message") ) + { + sEventStringsMap["message"] = + getFormattedUIString("message_session_event"); + } + + if ( sForceCloseSessionMap.end() == + sForceCloseSessionMap.find("removed") ) + { + sForceCloseSessionMap["removed"] = + getFormattedUIString("removed_from_group"); + } + + if ( sForceCloseSessionMap.end() == + sForceCloseSessionMap.find("no ability") ) + { + sForceCloseSessionMap["no ability"] = + getFormattedUIString("close_on_no_ability"); + } - sInviteMessage = getUIString("invite_message"); return TRUE; } @@ -205,21 +238,31 @@ protected: class LLIMMgr::LLIMSessionInvite { public: - LLIMSessionInvite(const LLUUID& session_id, const LLString& session_name, const LLUUID& caller_id,const LLString& caller_name, EInstantMessage type, const LLString& session_handle, const LLString& notify_box) : - mSessionID(session_id), - mSessionName(session_name), - mCallerID(caller_id), - mCallerName(caller_name), - mType(type), - mSessionHandle(session_handle), - mNotifyBox(notify_box) - {}; + LLIMSessionInvite( + const LLUUID& session_id, + const LLString& session_name, + const LLUUID& caller_id, + const LLString& caller_name, + EInstantMessage type, + EInvitationType inv_type, + const LLString& session_handle, + const LLString& notify_box) : + mSessionID(session_id), + mSessionName(session_name), + mCallerID(caller_id), + mCallerName(caller_name), + mType(type), + mInvType(inv_type), + mSessionHandle(session_handle), + mNotifyBox(notify_box) + {}; LLUUID mSessionID; LLString mSessionName; LLUUID mCallerID; LLString mCallerName; EInstantMessage mType; + EInvitationType mInvType; LLString mSessionHandle; LLString mNotifyBox; }; @@ -309,7 +352,7 @@ LLIMMgr::LLIMMgr() : LLFloaterIM* dummy_floater = new LLFloaterIM(); delete dummy_floater; - mPendingVoiceInvitations = LLSD::emptyMap(); + mPendingInvitations = LLSD::emptyMap(); mPendingAgentListUpdates = LLSD::emptyMap(); } @@ -413,7 +456,6 @@ void LLIMMgr::addMessage( if ( is_from_system ) // chat came from system { floater->addHistoryLine( - other_participant_id, msg, gSavedSettings.getColor4("SystemChatColor")); } @@ -521,9 +563,10 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name, // the session, dialog specifies the type of session. If the session // exists, it is brought forward. Specifying id = NULL results in an // im session to everyone. Returns the uuid of the session. -LLUUID LLIMMgr::addSession(const std::string& name, - EInstantMessage dialog, - const LLUUID& other_participant_id) +LLUUID LLIMMgr::addSession( + const std::string& name, + EInstantMessage dialog, + const LLUUID& other_participant_id) { LLUUID session_id = computeSessionID(dialog, other_participant_id); @@ -533,15 +576,16 @@ LLUUID LLIMMgr::addSession(const std::string& name, LLDynamicArray<LLUUID> ids; ids.put(other_participant_id); - floater = createFloater(session_id, - other_participant_id, - name, - ids, - dialog, - TRUE); + floater = createFloater( + session_id, + other_participant_id, + name, + ids, + dialog, + TRUE); noteOfflineUsers(floater, ids); - LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater); + LLFloaterChatterBox::showInstance(session_id); } else { @@ -554,36 +598,43 @@ LLUUID LLIMMgr::addSession(const std::string& name, // Adds a session using the given session_id. If the session already exists // the dialog type is assumed correct. Returns the uuid of the session. -LLUUID LLIMMgr::addSession(const std::string& name, - EInstantMessage dialog, - const LLUUID& other_participant_id, - const LLDynamicArray<LLUUID>& ids) +LLUUID LLIMMgr::addSession( + const std::string& name, + EInstantMessage dialog, + const LLUUID& other_participant_id, + const LLDynamicArray<LLUUID>& ids) { if (0 == ids.getLength()) { return LLUUID::null; } - LLUUID session_id = computeSessionID(dialog, - other_participant_id); + LLUUID session_id = computeSessionID( + dialog, + other_participant_id); LLFloaterIMPanel* floater = findFloaterBySession(session_id); if(!floater) { // On creation, use the first element of ids as the // "other_participant_id" - floater = createFloater(session_id, - other_participant_id, - name, - ids, - dialog, - TRUE); + floater = createFloater( + session_id, + other_participant_id, + name, + ids, + dialog, + TRUE); if ( !floater ) return LLUUID::null; noteOfflineUsers(floater, ids); + LLFloaterChatterBox::showInstance(session_id); + } + else + { + floater->open(); } - LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater); //mTabContainer->selectTabPanel(panel); floater->setInputFocus(TRUE); return floater->getSessionID(); @@ -599,6 +650,9 @@ void LLIMMgr::removeSession(const LLUUID& session_id) mFloaters.erase(floater->getHandle()); LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater); //mTabContainer->removeTabPanel(floater); + + clearPendingInviation(session_id); + clearPendingAgentListUpdates(session_id); } } @@ -608,9 +662,10 @@ void LLIMMgr::inviteToSession( const LLUUID& caller_id, const LLString& caller_name, EInstantMessage type, + EInvitationType inv_type, const LLString& session_handle) { - //ignore voice invites from voice-muted residents + //ignore invites from muted residents if (gMuteListp->isMuted(caller_id)) { return; @@ -621,17 +676,26 @@ void LLIMMgr::inviteToSession( BOOL ad_hoc_invite = FALSE; if(type == IM_SESSION_P2P_INVITE) { + //P2P is different...they only have voice invitations notify_box_type = "VoiceInviteP2P"; } - else if (gAgent.isInGroup(session_id)) + else if ( gAgent.isInGroup(session_id) ) { + //only really old school groups have voice invitations notify_box_type = "VoiceInviteGroup"; } - else + else if ( inv_type == INVITATION_TYPE_VOICE ) { + //else it's an ad-hoc + //and a voice ad-hoc notify_box_type = "VoiceInviteAdHoc"; ad_hoc_invite = TRUE; } + else if ( inv_type == INVITATION_TYPE_IMMEDIATE ) + { + notify_box_type = "InviteAdHoc"; + ad_hoc_invite = TRUE; + } LLIMSessionInvite* invite = new LLIMSessionInvite( session_id, @@ -639,6 +703,7 @@ void LLIMMgr::inviteToSession( caller_id, caller_name, type, + inv_type, session_handle, notify_box_type); @@ -666,7 +731,7 @@ void LLIMMgr::inviteToSession( } } - if ( !mPendingVoiceInvitations.has(session_id.asString()) ) + if ( !mPendingInvitations.has(session_id.asString()) ) { if (caller_name.empty()) { @@ -684,7 +749,7 @@ void LLIMMgr::inviteToSession( (void*)invite); } - mPendingVoiceInvitations[session_id.asString()] = LLSD(); + mPendingInvitations[session_id.asString()] = LLSD(); } } @@ -699,10 +764,11 @@ void LLIMMgr::onInviteNameLookup(const LLUUID& id, const char* first, const char LLString::format_map_t args; args["[NAME]"] = invite->mCallerName; - LLNotifyBox::showXml(invite->mNotifyBox, - args, - inviteUserResponse, - (void*)invite); + LLNotifyBox::showXml( + invite->mNotifyBox, + args, + inviteUserResponse, + (void*)invite); } class LLViewerChatterBoxInvitationAcceptResponder : @@ -711,10 +777,10 @@ class LLViewerChatterBoxInvitationAcceptResponder : public: LLViewerChatterBoxInvitationAcceptResponder( const LLUUID& session_id, - bool is_voice_invitation) + LLIMMgr::EInvitationType invitation_type) { mSessionID = session_id; - mIsVoiceInvitiation = is_voice_invitation; + mInvitiationType = invitation_type; } void result(const LLSD& content) @@ -738,48 +804,67 @@ public: //but unfortunately, our base that we are receiving here //may not be the most up to date. It was accurate at //some point in time though. - floaterp->setSpeakersList(content["agents"]); + floaterp->setSpeakers(content); //we now have our base of users in the session //that was accurate at some point, but maybe not now //so now we apply all of the udpates we've received //in case of race conditions - - //reapplying a user entrance will do nothing - //reapplying a user leaving will not have the user - //in our base. So it's all good floaterp->updateSpeakersList( gIMMgr->getPendingAgentListUpdates(mSessionID)); - if ( mIsVoiceInvitiation ) + if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE ) { floaterp->requestAutoConnect(); LLFloaterIMPanel::onClickStartCall(floaterp); // always open IM window when connecting to voice LLFloaterChatterBox::showInstance(TRUE); } + else if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE ) + { + LLFloaterChatterBox::showInstance(TRUE); + } } gIMMgr->clearPendingAgentListUpdates(mSessionID); - if ( mIsVoiceInvitiation ) - { - gIMMgr->clearPendingVoiceInviation(mSessionID); - } + gIMMgr->clearPendingInviation(mSessionID); } } void error(U32 statusNum, const std::string& reason) { + //throw something back to the viewer here? - if ( gIMMgr && mIsVoiceInvitiation ) + if ( gIMMgr ) { - gIMMgr->clearPendingVoiceInviation(mSessionID); + gIMMgr->clearPendingAgentListUpdates(mSessionID); + gIMMgr->clearPendingInviation(mSessionID); + + LLFloaterIMPanel* floaterp = + gIMMgr->findFloaterBySession(mSessionID); + + if (floaterp) + { + std::string error_string; + + if ( 404 == statusNum ) + { + error_string = "does not exist"; + } + else + { + error_string = "generic_request_error"; + } + + floaterp->showSessionStartError( + error_string); + } } } private: LLUUID mSessionID; - bool mIsVoiceInvitiation; + LLIMMgr::EInvitationType mInvitiationType; }; //static @@ -807,10 +892,11 @@ void LLIMMgr::inviteUserResponse(S32 option, void* user_data) im_floater->requestAutoConnect(); LLFloaterIMPanel::onClickStartCall(im_floater); // always open IM window when connecting to voice - LLFloaterChatterBox::showInstance(TRUE); + LLFloaterChatterBox::showInstance(invitep->mSessionID); } - - gIMMgr->clearPendingVoiceInviation(invitep->mSessionID); + + gIMMgr->clearPendingAgentListUpdates(invitep->mSessionID); + gIMMgr->clearPendingInviation(invitep->mSessionID); } else { @@ -830,34 +916,50 @@ void LLIMMgr::inviteUserResponse(S32 option, void* user_data) data, new LLViewerChatterBoxInvitationAcceptResponder( invitep->mSessionID, - true)); + invitep->mInvType)); } } break; case 2: // mute (also implies ignore, so this falls through to the "ignore" case below) + { + // mute the sender of this invite + if (!gMuteListp->isMuted(invitep->mCallerID)) { - // mute the sender of this invite - if (!gMuteListp->isMuted(invitep->mCallerID)) - { - LLMute mute(invitep->mCallerID, invitep->mCallerName, LLMute::AGENT); - gMuteListp->add(mute); - } + LLMute mute(invitep->mCallerID, invitep->mCallerName, LLMute::AGENT); + gMuteListp->add(mute); } + } /* FALLTHROUGH */ - case 1: // ignore + case 1: // decline + { + if (invitep->mType == IM_SESSION_P2P_INVITE) { - if (invitep->mType == IM_SESSION_P2P_INVITE) + if(gVoiceClient) { - if(gVoiceClient) - { - gVoiceClient->declineInvite(invitep->mSessionHandle); - } + gVoiceClient->declineInvite(invitep->mSessionHandle); } } - break; + else + { + std::string url = gAgent.getRegion()->getCapability( + "ChatSessionRequest"); + + LLSD data; + data["method"] = "decline invitation"; + data["session-id"] = invitep->mSessionID; + LLHTTPClient::post( + url, + data, + NULL); + } } + gIMMgr->clearPendingAgentListUpdates(invitep->mSessionID); + gIMMgr->clearPendingInviation(invitep->mSessionID); + break; + } + delete invitep; } @@ -869,11 +971,11 @@ void LLIMMgr::setFloaterOpen(BOOL set_open) { if (set_open) { - LLFloaterChatterBox::showInstance(LLSD()); + LLFloaterChatterBox::showInstance(); } else { - LLFloaterChatterBox::hideInstance(LLSD()); + LLFloaterChatterBox::hideInstance(); } } @@ -932,11 +1034,11 @@ BOOL LLIMMgr::hasSession(const LLUUID& session_id) return (findFloaterBySession(session_id) != NULL); } -void LLIMMgr::clearPendingVoiceInviation(const LLUUID& session_id) +void LLIMMgr::clearPendingInviation(const LLUUID& session_id) { - if ( mPendingVoiceInvitations.has(session_id.asString()) ) + if ( mPendingInvitations.has(session_id.asString()) ) { - mPendingVoiceInvitations.erase(session_id.asString()); + mPendingInvitations.erase(session_id.asString()); } } @@ -958,13 +1060,57 @@ void LLIMMgr::addPendingAgentListUpdates( { LLSD::map_const_iterator iter; - for ( iter = updates.beginMap(); - iter != updates.endMap(); - iter++) + if ( !mPendingAgentListUpdates.has(session_id.asString()) ) { - //we only want to include the last update for a given agent - mPendingAgentListUpdates[session_id.asString()][iter->first] = - iter->second; + //this is a new agent list update for this session + mPendingAgentListUpdates[session_id.asString()] = LLSD::emptyMap(); + } + + if ( + updates.has("agent_updates") && + updates["agent_updates"].isMap() && + updates.has("updates") && + updates["updates"].isMap() ) + { + //new school update + LLSD update_types = LLSD::emptyArray(); + LLSD::array_iterator array_iter; + + update_types.append("agent_updates"); + update_types.append("updates"); + + for ( + array_iter = update_types.beginArray(); + array_iter != update_types.endArray(); + ++array_iter) + { + //we only want to include the last update for a given agent + for ( + iter = updates[array_iter->asString()].beginMap(); + iter != updates[array_iter->asString()].endMap(); + ++iter) + { + mPendingAgentListUpdates[session_id.asString()][array_iter->asString()][iter->first] = + iter->second; + } + } + } + else if ( + updates.has("updates") && + updates["updates"].isMap() ) + { + //old school update where the SD contained just mappings + //of agent_id -> "LEAVE"/"ENTER" + + //only want to keep last update for each agent + for ( + iter = updates["updates"].beginMap(); + iter != updates["updates"].endMap(); + ++iter) + { + mPendingAgentListUpdates[session_id.asString()]["updates"][iter->first] = + iter->second; + } } } @@ -995,8 +1141,6 @@ LLFloaterIMPanel* LLIMMgr::createFloater( llinfos << "LLIMMgr::createFloater: from " << other_participant_id << " in session " << session_id << llendl; LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label, - LLRect(), - session_label, session_id, other_participant_id, dialog); @@ -1022,8 +1166,6 @@ LLFloaterIMPanel* LLIMMgr::createFloater( llinfos << "LLIMMgr::createFloater: from " << other_participant_id << " in session " << session_id << llendl; LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label, - LLRect(), - session_label, session_id, other_participant_id, ids, @@ -1034,8 +1176,9 @@ LLFloaterIMPanel* LLIMMgr::createFloater( return floater; } -void LLIMMgr::noteOfflineUsers(LLFloaterIMPanel* floater, - const LLDynamicArray<LLUUID>& ids) +void LLIMMgr::noteOfflineUsers( + LLFloaterIMPanel* floater, + const LLDynamicArray<LLUUID>& ids) { S32 count = ids.count(); if(count == 0) @@ -1099,14 +1242,6 @@ LLFloaterChatterBox* LLIMMgr::getFloater() return LLFloaterChatterBox::getInstance(LLSD()); } -void onConfirmForceCloseError(S32 option, void* data) -{ - //only 1 option really - LLFloaterIMPanel* floater = ((LLFloaterIMPanel*) data); - - if ( floater ) floater->close(FALSE); -} - class LLViewerChatterBoxSessionStartReply : public LLHTTPNode { public: @@ -1141,7 +1276,16 @@ public: LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id); if (floaterp) { - floaterp->setSpeakersList(body["agents"]); + floaterp->setSpeakers(body); + + //apply updates we've possibly received previously + floaterp->updateSpeakersList( + gIMMgr->getPendingAgentListUpdates(session_id)); + + if ( body.has("session_info") ) + { + floaterp->processSessionUpdate(body["session_info"]); + } //aply updates we've possibly received previously floaterp->updateSpeakersList( @@ -1155,20 +1299,14 @@ public: //floater LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(temp_session_id); - if (floater) - { - LLString::format_map_t args; - args["[REASON]"] = - sErrorStringsMap[body["error"].asString()]; - args["[RECIPIENT]"] = floater->getTitle(); - - gViewerWindow->alertXml("ChatterBoxSessionStartError", - args, - onConfirmForceCloseError, - floater); + if ( floater ) + { + floater->showSessionStartError(body["error"].asString()); } } + + gIMMgr->clearPendingAgentListUpdates(session_id); } }; @@ -1200,17 +1338,12 @@ public: //throw an error dialog LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); + if (floater) { - LLString::format_map_t args; - args["[REASON]"] = - sErrorStringsMap[body["error"].asString()]; - args["[EVENT]"] = - sEventStringsMap[body["event"].asString()]; - args["[RECIPIENT]"] = floater->getTitle(); - - gViewerWindow->alertXml("ChatterBoxSessionEventError", - args); + floater->showSessionEventError( + body["event"].asString(), + body["error"].asString()); } } } @@ -1234,15 +1367,7 @@ public: if ( floater ) { - LLString::format_map_t args; - - args["[NAME]"] = floater->getTitle(); - args["[REASON]"] = sForceCloseSessionMap[reason]; - - gViewerWindow->alertXml("ForceCloseChatterBoxSession", - args, - onConfirmForceCloseError, - floater); + floater->showSessionForceClose(reason); } } }; @@ -1258,7 +1383,8 @@ public: LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID()); if (floaterp) { - floaterp->updateSpeakersList(input["body"]["updates"]); + floaterp->updateSpeakersList( + input["body"]); } else { @@ -1267,11 +1393,28 @@ public: //a start or an acceptance of an invitation. Race condition. gIMMgr->addPendingAgentListUpdates( input["body"]["session_id"].asUUID(), - input["body"]["updates"]); + input["body"]); + } + } +}; + +class LLViewerChatterBoxSessionUpdate : public LLHTTPNode +{ +public: + virtual void post( + ResponsePtr responder, + const LLSD& context, + const LLSD& input) const + { + LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID()); + if (floaterp) + { + floaterp->processSessionUpdate(input["body"]["info"]); } } }; + class LLViewerChatterBoxInvitation : public LLHTTPNode { public: @@ -1281,6 +1424,8 @@ public: const LLSD& context, const LLSD& input) const { + //for backwards compatiblity reasons...we need to still + //check for 'text' or 'voice' invitations...bleh if ( input["body"].has("instantmessage") ) { LLString capability = input["body"]["capabilities"]["call"].asString(); @@ -1397,8 +1542,8 @@ public: url, data, new LLViewerChatterBoxInvitationAcceptResponder( - input["body"]["session_id"], - false)); + input["body"]["session_id"].asUUID(), + LLIMMgr::INVITATION_TYPE_INSTANT_MESSAGE)); } } //end if invitation has instant message else if ( input["body"].has("voice") ) @@ -1419,7 +1564,18 @@ public: input["body"]["session_name"].asString(), input["body"]["from_id"].asUUID(), input["body"]["from_name"].asString(), - IM_SESSION_INVITE); + IM_SESSION_INVITE, + LLIMMgr::INVITATION_TYPE_VOICE); + } + else if ( input["body"].has("immediate") ) + { + gIMMgr->inviteToSession( + input["body"]["session_id"].asUUID(), + input["body"]["session_name"].asString(), + input["body"]["from_id"].asUUID(), + input["body"]["from_name"].asString(), + IM_SESSION_INVITE, + LLIMMgr::INVITATION_TYPE_IMMEDIATE); } } }; @@ -1440,6 +1596,10 @@ LLHTTPRegistration<LLViewerChatterBoxSessionAgentListUpdates> gHTTPRegistrationMessageChatterboxsessionagentlistupdates( "/message/ChatterBoxSessionAgentListUpdates"); +LLHTTPRegistration<LLViewerChatterBoxSessionUpdate> + gHTTPRegistrationMessageChatterBoxSessionUpdate( + "/message/ChatterBoxSessionUpdate"); + LLHTTPRegistration<LLViewerChatterBoxInvitation> gHTTPRegistrationMessageChatterBoxInvitation( "/message/ChatterBoxInvitation"); diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index f5356ef926..11a6905a63 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -45,6 +45,13 @@ class LLFloaterIM; class LLIMMgr : public LLSingleton<LLIMMgr> { public: + enum EInvitationType + { + INVITATION_TYPE_INSTANT_MESSAGE = 0, + INVITATION_TYPE_VOICE = 1, + INVITATION_TYPE_IMMEDIATE = 2 + }; + LLIMMgr(); virtual ~LLIMMgr(); @@ -96,12 +103,14 @@ public: // deleted. void removeSession(const LLUUID& session_id); - void inviteToSession(const LLUUID& session_id, - const LLString& session_name, - const LLUUID& caller, - const LLString& caller_name, - EInstantMessage type, - const LLString& session_handle = LLString::null); + void inviteToSession( + const LLUUID& session_id, + const LLString& session_name, + const LLUUID& caller, + const LLString& caller_name, + EInstantMessage type, + EInvitationType inv_type, + const LLString& session_handle = LLString::null); //Updates a given session's session IDs. Does not open, //create or do anything new. If the old session doesn't @@ -147,7 +156,7 @@ public: static LLUUID computeSessionID(EInstantMessage dialog, const LLUUID& other_participant_id); - void clearPendingVoiceInviation(const LLUUID& session_id); + void clearPendingInviation(const LLUUID& session_id); LLSD getPendingAgentListUpdates(const LLUUID& session_id); void addPendingAgentListUpdates( @@ -155,6 +164,9 @@ public: const LLSD& updates); void clearPendingAgentListUpdates(const LLUUID& session_id); + //HACK: need a better way of enumerating existing session, or listening to session create/destroy events + const std::set<LLViewHandle>& getIMFloaterHandles() { return mFloaters; } + private: class LLIMSessionInvite; @@ -193,7 +205,7 @@ private: // An IM has been received that you haven't seen yet. BOOL mIMReceived; - LLSD mPendingVoiceInvitations; + LLSD mPendingInvitations; LLSD mPendingAgentListUpdates; }; @@ -203,6 +215,10 @@ class LLFloaterIM : public LLMultiFloater public: LLFloaterIM(); /*virtual*/ BOOL postBuild(); + + static std::map<std::string,LLString> sEventStringsMap; + static std::map<std::string,LLString> sErrorStringsMap; + static std::map<std::string,LLString> sForceCloseSessionMap; }; // Globals diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 9c9b1ad257..d8841afe22 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3165,7 +3165,7 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model std::string(), cb); } - gFocusMgr.setKeyboardFocus(NULL, NULL); + gFocusMgr.setKeyboardFocus(NULL); } else if ("detach" == action) { diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index ca65b879bc..7b27a830c4 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -2606,7 +2606,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) // } // // // restore keyboard focus - // gFocusMgr.setKeyboardFocus(focus_view, callback); + // gFocusMgr.setKeyboardFocus(focus_view); //} } diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp index 20c4a25003..30106443c0 100644 --- a/indra/newview/lljoystickbutton.cpp +++ b/indra/newview/lljoystickbutton.cpp @@ -607,26 +607,26 @@ void LLJoystickCameraRotate::draw() { LLGLSUIDefault gls_ui; - gl_draw_image( 0, 0, mImageUnselected ); + mImageUnselected->draw( 0, 0 ); if( mInTop ) { - drawRotatedImage( mImageSelected, 0 ); + drawRotatedImage( mImageSelected->getImage(), 0 ); } if( mInRight ) { - drawRotatedImage( mImageSelected, 1 ); + drawRotatedImage( mImageSelected->getImage(), 1 ); } if( mInBottom ) { - drawRotatedImage( mImageSelected, 2 ); + drawRotatedImage( mImageSelected->getImage(), 2 ); } if( mInLeft ) { - drawRotatedImage( mImageSelected, 3 ); + drawRotatedImage( mImageSelected->getImage(), 3 ); } if (sDebugRects) @@ -801,7 +801,7 @@ void LLJoystickCameraZoom::draw() } else { - gl_draw_image( 0, 0, mImageUnselected ); + mImageUnselected->draw( 0, 0 ); } if (sDebugRects) diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 4d02af8fae..60d39b62bd 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -52,10 +52,11 @@ #include <boost/tokenizer.hpp> #include "llcrc.h" +#include "lldir.h" #include "lldispatcher.h" +#include "llsdserialize.h" #include "llxfermanager.h" #include "message.h" -#include "lldir.h" #include "llagent.h" #include "llfloatermute.h" @@ -67,6 +68,9 @@ LLMuteList* gMuteListp = NULL; +std::map<LLUUID, F32> LLMuteList::sUserVolumeSettings; + + // "emptymutelist" class LLDispatchEmptyMuteList : public LLDispatchHandler { @@ -168,6 +172,24 @@ LLMuteList::LLMuteList() : msg->setHandlerFuncFast(_PREHASH_UseCachedMuteList, processUseCachedMuteList); gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList); + + // load per-resident voice volume information + // conceptually, this is part of the mute list information, although it is only stored locally + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml"); + + LLSD settings_llsd; + llifstream file; + file.open(filename.c_str()); + if (file.is_open()) + { + LLSDSerialize::fromXML(settings_llsd, file); + } + + for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); + iter != settings_llsd.endMap(); ++iter) + { + sUserVolumeSettings.insert(std::make_pair(LLUUID(iter->first), (F32)iter->second.asReal())); + } } //----------------------------------------------------------------------------- @@ -175,6 +197,17 @@ LLMuteList::LLMuteList() : //----------------------------------------------------------------------------- LLMuteList::~LLMuteList() { + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml"); + LLSD settings_llsd; + + for(user_volume_map_t::iterator iter = sUserVolumeSettings.begin(); iter != sUserVolumeSettings.end(); ++iter) + { + settings_llsd[iter->first.asString()] = iter->second; + } + + llofstream file; + file.open(filename.c_str()); + LLSDSerialize::toPrettyXML(settings_llsd, file); } BOOL LLMuteList::isLinden(const LLString& name) const @@ -588,6 +621,25 @@ void LLMuteList::cache(const LLUUID& agent_id) } } +void LLMuteList::setSavedResidentVolume(const LLUUID& id, F32 volume) +{ + // store new value in volume settings file + sUserVolumeSettings[id] = volume; +} + +F32 LLMuteList::getSavedResidentVolume(const LLUUID& id) +{ + const F32 DEFAULT_VOLUME = 0.5f; + + user_volume_map_t::iterator found_it = sUserVolumeSettings.find(id); + if (found_it != sUserVolumeSettings.end()) + { + return found_it->second; + } + //FIXME: assumes default, should get this from somewhere + return DEFAULT_VOLUME; +} + //----------------------------------------------------------------------------- // Static message handlers diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 23e0620ade..413a2933b3 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -112,6 +112,9 @@ public: // call this method on logout to save everything. void cache(const LLUUID& agent_id); + void setSavedResidentVolume(const LLUUID& id, F32 volume); + F32 getSavedResidentVolume(const LLUUID& id); + private: BOOL loadFromFile(const LLString& filename); BOOL saveToFile(const LLString& filename); @@ -155,6 +158,9 @@ private: BOOL mIsLoaded; friend class LLDispatchEmptyMuteList; + + typedef std::map<LLUUID, F32> user_volume_map_t; + static user_volume_map_t sUserVolumeSettings; }; class LLMuteListObserver diff --git a/indra/newview/llnameeditor.cpp b/indra/newview/llnameeditor.cpp index ba1280550f..1ca702b0a7 100644 --- a/indra/newview/llnameeditor.cpp +++ b/indra/newview/llnameeditor.cpp @@ -53,7 +53,7 @@ LLNameEditor::LLNameEditor(const std::string& name, const LLRect& rect, S32 max_text_length, void (*commit_callback)(LLUICtrl* caller, void* user_data), void (*keystroke_callback)(LLLineEditor* caller, void* user_data), - void (*focus_lost_callback)(LLUICtrl* caller, void* user_data), + void (*focus_lost_callback)(LLFocusableElement* caller, void* user_data), void* userdata, LLLinePrevalidateFunc prevalidate_func, LLViewBorder::EBevel border_bevel, diff --git a/indra/newview/llnameeditor.h b/indra/newview/llnameeditor.h index 526b76b9c0..9c89454c33 100644 --- a/indra/newview/llnameeditor.h +++ b/indra/newview/llnameeditor.h @@ -53,7 +53,7 @@ public: S32 max_text_length = 254, void (*commit_callback)(LLUICtrl* caller, void* user_data) = NULL, void (*keystroke_callback)(LLLineEditor* caller, void* user_data) = NULL, - void (*focus_lost_callback)(LLUICtrl* caller, void* user_data) = NULL, + void (*focus_lost_callback)(LLFocusableElement* caller, void* user_data) = NULL, void* userdata = NULL, LLLinePrevalidateFunc prevalidate_func = NULL, LLViewBorder::EBevel border_bevel = LLViewBorder::BEVEL_IN, diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index adcc141bb1..a47721be9d 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -224,7 +224,7 @@ LLScrollListItem* LLNameListCtrl::addElement(const LLSD& value, EAddPosition pos LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex); ((LLScrollListText*)cell)->setText( fullname ); - updateMaxContentWidth(item); + calcMaxContentWidth(item); // this column is resizable LLScrollListColumn* columnp = getColumn(mNameColumnIndex); @@ -277,7 +277,7 @@ void LLNameListCtrl::refresh(const LLUUID& id, const char* first, cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex); ((LLScrollListText*)cell)->setText( fullname ); - updateMaxContentWidth(item); + calcMaxContentWidth(item); } } } diff --git a/indra/newview/lloverlaybar.cpp b/indra/newview/lloverlaybar.cpp index 15c993e552..e7c313638b 100644 --- a/indra/newview/lloverlaybar.cpp +++ b/indra/newview/lloverlaybar.cpp @@ -39,6 +39,7 @@ #include "audioengine.h" #include "llagent.h" #include "llbutton.h" +#include "llchatbar.h" #include "llfocusmgr.h" #include "llimview.h" #include "llmediaengine.h" @@ -71,37 +72,14 @@ extern S32 MENU_BAR_HEIGHT; // -//static -void* LLOverlayBar::createMasterRemote(void* userdata) -{ - LLOverlayBar *self = (LLOverlayBar*)userdata; - self->mMasterRemote = new LLMediaRemoteCtrl ( "master_volume", - "volume", - LLRect(), - "panel_master_volume.xml"); - return self->mMasterRemote; -} void* LLOverlayBar::createMediaRemote(void* userdata) { LLOverlayBar *self = (LLOverlayBar*)userdata; - self->mMediaRemote = new LLMediaRemoteCtrl ( "media_remote", - "media", - LLRect(), - "panel_media_remote.xml"); + self->mMediaRemote = new LLMediaRemoteCtrl (); return self->mMediaRemote; } -void* LLOverlayBar::createMusicRemote(void* userdata) -{ - LLOverlayBar *self = (LLOverlayBar*)userdata; - self->mMusicRemote = new LLMediaRemoteCtrl ( "music_remote", - "music", - LLRect(), - "panel_music_remote.xml" ); - return self->mMusicRemote; -} - void* LLOverlayBar::createVoiceRemote(void* userdata) { LLOverlayBar *self = (LLOverlayBar*)userdata; @@ -109,13 +87,14 @@ void* LLOverlayBar::createVoiceRemote(void* userdata) return self->mVoiceRemote; } +void* LLOverlayBar::createChatBar(void* userdata) +{ + gChatBar = new LLChatBar(); + return gChatBar; +} - - -LLOverlayBar::LLOverlayBar(const std::string& name, const LLRect& rect) - : LLPanel(name, rect, FALSE), // not bordered - mMasterRemote(NULL), - mMusicRemote(NULL), +LLOverlayBar::LLOverlayBar() + : LLPanel(), mMediaRemote(NULL), mVoiceRemote(NULL), mMediaState(STOPPED), @@ -127,25 +106,27 @@ LLOverlayBar::LLOverlayBar(const std::string& name, const LLRect& rect) mBuilt = false; LLCallbackMap::map_t factory_map; - factory_map["master_volume"] = LLCallbackMap(LLOverlayBar::createMasterRemote, this); factory_map["media_remote"] = LLCallbackMap(LLOverlayBar::createMediaRemote, this); - factory_map["music_remote"] = LLCallbackMap(LLOverlayBar::createMusicRemote, this); factory_map["voice_remote"] = LLCallbackMap(LLOverlayBar::createVoiceRemote, this); + factory_map["chat_bar"] = LLCallbackMap(LLOverlayBar::createChatBar, this); gUICtrlFactory->buildPanel(this, "panel_overlaybar.xml", &factory_map); - +} + +BOOL LLOverlayBar::postBuild() +{ childSetAction("IM Received",onClickIMReceived,this); childSetAction("Set Not Busy",onClickSetNotBusy,this); childSetAction("Release Keys",onClickReleaseKeys,this); childSetAction("Mouselook",onClickMouselook,this); childSetAction("Stand Up",onClickStandUp,this); + childSetVisible("chat_bar", gSavedSettings.getBOOL("ChatVisible")); mIsFocusRoot = TRUE; mBuilt = true; - // make overlay bar conform to window size - setRect(rect); layoutButtons(); + return TRUE; } LLOverlayBar::~LLOverlayBar() @@ -176,146 +157,45 @@ void LLOverlayBar::reshape(S32 width, S32 height, BOOL called_from_parent) void LLOverlayBar::layoutButtons() { - S32 width = mRect.getWidth(); - if (width > 1024) width = 1024; - - S32 count = getChildCount(); - const S32 PAD = gSavedSettings.getS32("StatusBarPad"); - - const S32 num_media_controls = 3; - S32 media_remote_width = mMediaRemote ? mMediaRemote->getRect().getWidth() : 0; - S32 music_remote_width = mMusicRemote ? mMusicRemote->getRect().getWidth() : 0; - S32 voice_remote_width = mVoiceRemote ? mVoiceRemote->getRect().getWidth() : 0; - S32 master_remote_width = mMasterRemote ? mMasterRemote->getRect().getWidth() : 0; - - // total reserved width for all media remotes - const S32 ENDPAD = 20; - S32 remote_total_width = media_remote_width + PAD + music_remote_width + PAD + voice_remote_width + PAD + master_remote_width + ENDPAD; + LLView* state_buttons_panel = getChildByName("state_buttons", TRUE); - // calculate button widths - F32 segment_width = (F32)(width - remote_total_width) / (F32)(count - num_media_controls); - - S32 btn_width = lltrunc(segment_width - PAD); - - // Evenly space all views - LLRect r; - S32 i = 0; - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) + if (state_buttons_panel) { - LLView *view = *child_iter; - r = view->getRect(); - r.mLeft = (width) - llround(remote_total_width + (i-num_media_controls+1)*segment_width); - r.mRight = r.mLeft + btn_width; - view->setRect(r); - i++; - } + LLViewQuery query; + LLWidgetTypeFilter widget_filter(WIDGET_TYPE_BUTTON); + query.addPreFilter(LLVisibleFilter::getInstance()); + query.addPreFilter(LLEnabledFilter::getInstance()); + query.addPreFilter(&widget_filter); - // Fix up remotes to have constant width because they can't shrink - S32 right = mRect.getWidth() - remote_total_width - PAD; - if (mMediaRemote) - { - r = mMediaRemote->getRect(); - r.mLeft = right + PAD; - right = r.mLeft + media_remote_width; - r.mRight = right; - mMediaRemote->setRect(r); - } - if (mMusicRemote) - { - r = mMusicRemote->getRect(); - r.mLeft = right + PAD; - right = r.mLeft + music_remote_width; - r.mRight = right; - mMusicRemote->setRect(r); - } - if (mVoiceRemote) - { - r = mVoiceRemote->getRect(); - r.mLeft = right + PAD; - right = r.mLeft + voice_remote_width; - r.mRight = right; - mVoiceRemote->setRect(r); - } - if (mMasterRemote) - { - r = mMasterRemote->getRect(); - r.mLeft = right + PAD; - right = r.mLeft + master_remote_width; - r.mRight = right; - mMasterRemote->setRect(r); - } - - updateRect(); -} + child_list_t button_list = query(state_buttons_panel); -void LLOverlayBar::draw() -{ - // retrieve rounded rect image - LLUUID image_id; - image_id.set(gViewerArt.getString("rounded_square.tga")); - LLViewerImage* imagep = gImageList.getImage(image_id, MIPMAP_FALSE, TRUE); + const S32 MAX_BAR_WIDTH = 600; + S32 bar_width = llclamp(state_buttons_panel->getRect().getWidth(), 0, MAX_BAR_WIDTH); - if (imagep) - { - LLGLSTexture texture_enabled; - LLViewerImage::bindTexture(imagep); + // calculate button widths + const S32 MAX_BUTTON_WIDTH = 150; + S32 segment_width = llclamp(lltrunc((F32)(bar_width) / (F32)button_list.size()), 0, MAX_BUTTON_WIDTH); + S32 btn_width = segment_width - gSavedSettings.getS32("StatusBarPad"); - const S32 PAD = gSavedSettings.getS32("StatusBarPad"); + // Evenly space all buttons, starting from left + S32 left = 0; + S32 bottom = 1; - // draw rounded rect tabs behind all children - LLRect r; - // focus highlights - LLColor4 color = gColors.getColor("FloaterFocusBorderColor"); - glColor4fv(color.mV); - if(gFocusMgr.childHasKeyboardFocus(gBottomPanel)) - { - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) - { - LLView *view = *child_iter; - if(view->getEnabled() && view->getVisible()) - { - r = view->getRect(); - gl_segmented_rect_2d_tex(r.mLeft - PAD/3 - 1, - r.mTop + 3, - r.mRight + PAD/3 + 1, - r.mBottom, - imagep->getWidth(), - imagep->getHeight(), - 16, - ROUNDED_RECT_TOP); - } - } - } - - // main tabs - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) + for (child_list_reverse_iter_t child_iter = button_list.rbegin(); + child_iter != button_list.rend(); ++child_iter) { LLView *view = *child_iter; - if(view->getEnabled() && view->getVisible()) - { - r = view->getRect(); - // draw a nice little pseudo-3D outline - color = gColors.getColor("DefaultShadowDark"); - glColor4fv(color.mV); - gl_segmented_rect_2d_tex(r.mLeft - PAD/3 + 1, r.mTop + 2, r.mRight + PAD/3, r.mBottom, - imagep->getWidth(), imagep->getHeight(), 16, ROUNDED_RECT_TOP); - color = gColors.getColor("DefaultHighlightLight"); - glColor4fv(color.mV); - gl_segmented_rect_2d_tex(r.mLeft - PAD/3, r.mTop + 2, r.mRight + PAD/3 - 3, r.mBottom, - imagep->getWidth(), imagep->getHeight(), 16, ROUNDED_RECT_TOP); - // here's the main background. Note that it overhangs on the bottom so as to hide the - // focus highlight on the bottom panel, thus producing the illusion that the focus highlight - // continues around the tabs - color = gColors.getColor("FocusBackgroundColor"); - glColor4fv(color.mV); - gl_segmented_rect_2d_tex(r.mLeft - PAD/3 + 1, r.mTop + 1, r.mRight + PAD/3 - 1, r.mBottom - 1, - imagep->getWidth(), imagep->getHeight(), 16, ROUNDED_RECT_TOP); - } + LLRect r = view->getRect(); + r.setOriginAndSize(left, bottom, btn_width, r.getHeight()); + view->setRect(r); + left += segment_width; } } +} + +void LLOverlayBar::draw() +{ + childSetVisible("chat_bar", gSavedSettings.getBOOL("ChatVisible")); // draw children on top LLPanel::draw(); @@ -325,79 +205,74 @@ void LLOverlayBar::draw() // Per-frame updates of visibility void LLOverlayBar::refresh() { + BOOL buttons_changed = FALSE; + BOOL im_received = gIMMgr->getIMReceived(); - childSetVisible("IM Received", im_received); - childSetEnabled("IM Received", im_received); + LLButton* button = LLUICtrlFactory::getButtonByName(this, "IM Received"); + if (button && button->getVisible() != im_received) + { + button->setVisible(im_received); + sendChildToFront(button); + moveChildToBackOfTabGroup(button); + buttons_changed = TRUE; + } BOOL busy = gAgent.getBusy(); - childSetVisible("Set Not Busy", busy); - childSetEnabled("Set Not Busy", busy); + button = LLUICtrlFactory::getButtonByName(this, "Set Not Busy"); + if (button && button->getVisible() != busy) + { + button->setVisible(busy); + sendChildToFront(button); + moveChildToBackOfTabGroup(button); + buttons_changed = TRUE; + } BOOL controls_grabbed = gAgent.anyControlGrabbed(); + button = LLUICtrlFactory::getButtonByName(this, "Release Keys"); - childSetVisible("Release Keys", controls_grabbed); - childSetEnabled("Release Keys", controls_grabbed); - + if (button && button->getVisible() != controls_grabbed) + { + button->setVisible(controls_grabbed); + sendChildToFront(button); + moveChildToBackOfTabGroup(button); + buttons_changed = TRUE; + } BOOL mouselook_grabbed; mouselook_grabbed = gAgent.isControlGrabbed(CONTROL_ML_LBUTTON_DOWN_INDEX) || gAgent.isControlGrabbed(CONTROL_ML_LBUTTON_UP_INDEX); + button = LLUICtrlFactory::getButtonByName(this, "Mouselook"); - - childSetVisible("Mouselook", mouselook_grabbed); - childSetEnabled("Mouselook", mouselook_grabbed); + if (button && button->getVisible() != mouselook_grabbed) + { + button->setVisible(mouselook_grabbed); + sendChildToFront(button); + moveChildToBackOfTabGroup(button); + buttons_changed = TRUE; + } BOOL sitting = FALSE; if (gAgent.getAvatarObject()) { sitting = gAgent.getAvatarObject()->mIsSitting; - childSetVisible("Stand Up", sitting); - childSetEnabled("Stand Up", sitting); - } + button = LLUICtrlFactory::getButtonByName(this, "Stand Up"); - if ( mMusicRemote && gAudiop ) + if (button && button->getVisible() != sitting) { - LLParcel* parcel = gParcelMgr->getAgentParcel(); - if (!parcel - || parcel->getMusicURL().empty() - || !gSavedSettings.getBOOL("AudioStreamingMusic")) - { - mMusicRemote->setVisible(FALSE); - mMusicRemote->setEnabled(FALSE); - } - else - { - mMusicRemote->setVisible(TRUE); - mMusicRemote->setEnabled(TRUE); - } + button->setVisible(sitting); + sendChildToFront(button); + moveChildToBackOfTabGroup(button); + buttons_changed = TRUE; } - // if there is a url and a texture and media is enabled and available and media streaming is on... (phew!) - if ( mMediaRemote ) - { - if (LLMediaEngine::getInstance () && - LLMediaEngine::getInstance ()->getUrl ().length () && - LLMediaEngine::getInstance ()->getImageUUID ().notNull () && - LLMediaEngine::getInstance ()->isEnabled () && - LLMediaEngine::getInstance ()->isAvailable () && - gSavedSettings.getBOOL ( "AudioStreamingVideo" ) ) - { - // display remote control - mMediaRemote->setVisible ( TRUE ); - mMediaRemote->setEnabled ( TRUE ); - } - else - { - mMediaRemote->setVisible ( FALSE ); - mMediaRemote->setEnabled ( FALSE ); - } - } - if (mVoiceRemote) - { - mVoiceRemote->setVisible(LLVoiceClient::voiceEnabled()); - } - + // update "remotes" + childSetVisible("voice_remote_container", LLVoiceClient::voiceEnabled()); + enableMediaButtons(); + + moveChildToBackOfTabGroup(mMediaRemote); + moveChildToBackOfTabGroup(mVoiceRemote); + // turn off the whole bar in mouselook if (gAgent.cameraMouselook()) { @@ -407,6 +282,11 @@ void LLOverlayBar::refresh() { setVisible(TRUE); } + + if (buttons_changed) + { + layoutButtons(); + } } //----------------------------------------------------------------------- @@ -462,33 +342,25 @@ void LLOverlayBar::mediaPlay(void*) { return; } - gOverlayBar->mMediaState = PLAYING; // desired state - LLParcel* parcel = gParcelMgr->getAgentParcel(); - if (parcel) - { - LLString path(""); - LLMediaEngine::getInstance()->convertImageAndLoadUrl( true, false, path ); - } -} -//static -void LLOverlayBar::mediaPause(void*) -{ - if (!gOverlayBar) + + if (gOverlayBar->mMediaState != PLAYING) { - return; + gOverlayBar->mMediaState = PLAYING; // desired state + LLParcel* parcel = gParcelMgr->getAgentParcel(); + if (parcel) + { + LLString path(""); + LLMediaEngine::getInstance()->convertImageAndLoadUrl( true, false, path ); + } } - gOverlayBar->mMediaState = PAUSED; // desired state - LLMediaEngine::getInstance()->pause(); -} -//static -void LLOverlayBar::mediaStop(void*) -{ - if (!gOverlayBar) + else { - return; + gOverlayBar->mMediaState = PAUSED; // desired state + LLMediaEngine::getInstance()->pause(); } - gOverlayBar->mMediaState = STOPPED; // desired state - LLMediaEngine::getInstance()->stop(); + + //gOverlayBar->mMediaState = STOPPED; // desired state + //LLMediaEngine::getInstance()->stop(); } //static @@ -498,116 +370,75 @@ void LLOverlayBar::musicPlay(void*) { return; } - gOverlayBar->mMusicState = PLAYING; // desired state - if (gAudiop) + + if (gOverlayBar->mMusicState != PLAYING) { - LLParcel* parcel = gParcelMgr->getAgentParcel(); - if ( parcel ) + gOverlayBar->mMusicState = PLAYING; // desired state + if (gAudiop) { - // this doesn't work properly when crossing parcel boundaries - even when the - // stream is stopped, it doesn't return the right thing - commenting out for now. -// if ( gAudiop->isInternetStreamPlaying() == 0 ) + LLParcel* parcel = gParcelMgr->getAgentParcel(); + if ( parcel ) { - gAudiop->startInternetStream(parcel->getMusicURL().c_str()); + // this doesn't work properly when crossing parcel boundaries - even when the + // stream is stopped, it doesn't return the right thing - commenting out for now. + // if ( gAudiop->isInternetStreamPlaying() == 0 ) + { + gAudiop->startInternetStream(parcel->getMusicURL().c_str()); + } } } } -} -//static -void LLOverlayBar::musicPause(void*) -{ - if (!gOverlayBar) - { - return; - } - gOverlayBar->mMusicState = PAUSED; // desired state - if (gAudiop) - { - gAudiop->pauseInternetStream(1); - } -} -//static -void LLOverlayBar::musicStop(void*) -{ - if (!gOverlayBar) - { - return; - } - gOverlayBar->mMusicState = STOPPED; // desired state - if (gAudiop) + //else + //{ + // gOverlayBar->mMusicState = PAUSED; // desired state + // if (gAudiop) + // { + // gAudiop->pauseInternetStream(1); + // } + //} + else { - gAudiop->stopInternetStream(); + gOverlayBar->mMusicState = STOPPED; // desired state + if (gAudiop) + { + gAudiop->stopInternetStream(); + } } } -//static -void LLOverlayBar::enableMusicButtons(LLPanel* panel) -{ - BOOL play_enabled = FALSE; - BOOL play_visible = TRUE; - BOOL pause_visible = FALSE; - BOOL stop_enabled = FALSE; - if ( gAudiop && gOverlayBar && gSavedSettings.getBOOL("AudioStreamingMusic")) +void LLOverlayBar::enableMediaButtons() +{ + if (mMediaRemote) { - play_enabled = TRUE; - S32 is_playing = gAudiop->isInternetStreamPlaying(); - if (is_playing == 1) + // Music + LLParcel* parcel = gParcelMgr->getAgentParcel(); + if (parcel + && gAudiop + && !parcel->getMusicURL().empty() + && gSavedSettings.getBOOL("AudioStreamingMusic")) { - play_visible = FALSE; - pause_visible = TRUE; - stop_enabled = TRUE; + mMediaRemote->childSetEnabled("music_play", TRUE); } - else if (is_playing == 2) + else { - play_visible = TRUE; - pause_visible = FALSE; - stop_enabled = TRUE; + mMediaRemote->childSetEnabled("music_play", FALSE); } - } - panel->childSetEnabled("music_play", play_enabled); - panel->childSetEnabled("music_pause", play_enabled); - panel->childSetVisible("music_play", play_visible); - panel->childSetVisible("music_pause", pause_visible); - panel->childSetEnabled("music_stop", stop_enabled); -} -//static -void LLOverlayBar::enableMediaButtons(LLPanel* panel) -{ - // Media - BOOL play_enabled = FALSE; - BOOL play_visible = TRUE; - BOOL pause_visible = FALSE; - BOOL stop_enabled = FALSE; - - if ( LLMediaEngine::getInstance() && gOverlayBar && gSavedSettings.getBOOL("AudioStreamingVideo") ) - { - play_enabled = TRUE; - if (LLMediaEngine::getInstance()->getMediaRenderer()) + // Media + // if there is a url and a texture and media is enabled and available and media streaming is on... (phew!) + if (LLMediaEngine::getInstance() + && LLMediaEngine::getInstance()->getUrl ().length () + && LLMediaEngine::getInstance()->getImageUUID ().notNull () + && LLMediaEngine::getInstance()->isEnabled () + && LLMediaEngine::getInstance()->isAvailable () + && gSavedSettings.getBOOL ( "AudioStreamingVideo" ) ) { - if ( LLMediaEngine::getInstance()->getMediaRenderer()->isPlaying() || - LLMediaEngine::getInstance()->getMediaRenderer()->isLooping() ) - { - play_visible = FALSE; - pause_visible = TRUE; - stop_enabled = TRUE; - } - else if ( LLMediaEngine::getInstance()->getMediaRenderer()->isPaused() ) - { - play_visible = TRUE; - pause_visible = FALSE; - stop_enabled = TRUE; - } + mMediaRemote->childSetEnabled("media_play", TRUE); + } + else + { + mMediaRemote->childSetEnabled("media_play", FALSE); } } - panel->childSetEnabled("media_play", play_enabled); - panel->childSetEnabled("media_pause", play_enabled); - panel->childSetVisible("media_play", play_visible); - panel->childSetVisible("media_pause", pause_visible); - panel->childSetEnabled("media_stop", stop_enabled); } -void LLOverlayBar::toggleAudioVolumeFloater(void* user_data) -{ - LLFloaterAudioVolume::toggleInstance(LLSD()); -} diff --git a/indra/newview/lloverlaybar.h b/indra/newview/lloverlaybar.h index 229346340a..18ff07e71b 100644 --- a/indra/newview/lloverlaybar.h +++ b/indra/newview/lloverlaybar.h @@ -54,7 +54,7 @@ class LLOverlayBar : public LLPanel { public: - LLOverlayBar(const std::string& name, const LLRect& rect ); + LLOverlayBar(); ~LLOverlayBar(); virtual EWidgetType getWidgetType() const; @@ -63,6 +63,7 @@ public: /*virtual*/ void refresh(); /*virtual*/ void draw(); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); + /*virtual*/ BOOL postBuild(); void layoutButtons(); @@ -79,27 +80,16 @@ public: //static media helper functions static void mediaPlay(void*); - static void mediaPause(void*); - static void mediaStop(void*); - static void musicPlay(void*); - static void musicPause(void*); - static void musicStop(void*); - static void toggleAudioVolumeFloater(void*); - - static void enableMediaButtons(LLPanel* panel); - static void enableMusicButtons(LLPanel* panel); - protected: - static void* createMasterRemote(void* userdata); - static void* createMusicRemote(void* userdata); static void* createMediaRemote(void* userdata); static void* createVoiceRemote(void* userdata); + static void* createChatBar(void* userdata); + + void enableMediaButtons(); protected: - LLMediaRemoteCtrl* mMasterRemote; - LLMediaRemoteCtrl* mMusicRemote; LLMediaRemoteCtrl* mMediaRemote; LLVoiceRemoteCtrl* mVoiceRemote; bool mBuilt; // dialog constructed yet? diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index c090fd9749..46af3ec74f 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -1638,7 +1638,7 @@ void LLPanelAvatar::onClickMute(void *userdata) if (name_edit) { std::string agent_name = name_edit->getText(); - gFloaterMute->show(); + LLFloaterMute::showInstance(); if (gMuteListp->isMuted(agent_id)) { diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 7163a71bc3..7263b11d96 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -189,14 +189,14 @@ BOOL LLPanelClassified::postBuild() mNameEditor = LLViewerUICtrlFactory::getLineEditorByName(this, "given_name_editor"); mNameEditor->setMaxTextLength(DB_PARCEL_NAME_LEN); mNameEditor->setCommitOnFocusLost(TRUE); - mNameEditor->setFocusReceivedCallback(onFocusReceived); + mNameEditor->setFocusReceivedCallback(onFocusReceived, this); mNameEditor->setCommitCallback(onCommitAny); mNameEditor->setCallbackUserData(this); mNameEditor->setPrevalidate( LLLineEditor::prevalidateASCII ); mDescEditor = LLUICtrlFactory::getTextEditorByName(this, "desc_editor"); mDescEditor->setCommitOnFocusLost(TRUE); - mDescEditor->setFocusReceivedCallback(onFocusReceived); + mDescEditor->setFocusReceivedCallback(onFocusReceived, this); mDescEditor->setCommitCallback(onCommitAny); mDescEditor->setCallbackUserData(this); mDescEditor->setTabToNextField(TRUE); @@ -929,10 +929,10 @@ void LLPanelClassified::onCommitAny(LLUICtrl* ctrl, void* data) } // static -void LLPanelClassified::onFocusReceived(LLUICtrl* ctrl, void* data) +void LLPanelClassified::onFocusReceived(LLFocusableElement* ctrl, void* data) { // allow the data to be saved - onCommitAny(ctrl, data); + onCommitAny((LLUICtrl*)ctrl, data); } diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h index a2bb29b224..8884d1a25e 100644 --- a/indra/newview/llpanelclassified.h +++ b/indra/newview/llpanelclassified.h @@ -111,7 +111,7 @@ protected: static void onClickProfile(void* data); static void onClickSet(void* data); - static void onFocusReceived(LLUICtrl* ctrl, void* data); + static void onFocusReceived(LLFocusableElement* ctrl, void* data); static void onCommitAny(LLUICtrl* ctrl, void* data); void sendClassifiedClickMessage(const char* type); diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 8dbe72fdfe..8ce2ae5d9c 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -870,7 +870,7 @@ void LLPanelFace::onClickApply(void* userdata) { LLPanelFace* self = (LLPanelFace*) userdata; - gFocusMgr.setKeyboardFocus( NULL, NULL ); + gFocusMgr.setKeyboardFocus( NULL ); //F32 repeats_per_meter = self->mCtrlRepeatsPerMeter->get(); F32 repeats_per_meter = (F32)self->childGetValue( "rptctrl" ).asReal();//self->mCtrlRepeatsPerMeter->get(); diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 3ad65b5e68..31688256f5 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -114,8 +114,8 @@ BOOL LLPanelGroupGeneral::postBuild() if(mEditCharter) { mEditCharter->setCommitCallback(onCommitAny); - mEditCharter->setFocusReceivedCallback(onCommitAny); - mEditCharter->setFocusChangedCallback(onCommitAny); + mEditCharter->setFocusReceivedCallback(onFocusEdit, this); + mEditCharter->setFocusChangedCallback(onFocusEdit, this); mEditCharter->setCallbackUserData(this); } @@ -259,6 +259,14 @@ BOOL LLPanelGroupGeneral::postBuild() } // static +void LLPanelGroupGeneral::onFocusEdit(LLFocusableElement* ctrl, void* data) +{ + LLPanelGroupGeneral* self = (LLPanelGroupGeneral*)data; + self->mChanged = TRUE; + self->notifyObservers(); +} + +// static void LLPanelGroupGeneral::onCommitAny(LLUICtrl* ctrl, void* data) { LLPanelGroupGeneral* self = (LLPanelGroupGeneral*)data; diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h index e7a27b6c0b..b17a66d0a3 100644 --- a/indra/newview/llpanelgroupgeneral.h +++ b/indra/newview/llpanelgroupgeneral.h @@ -66,6 +66,7 @@ public: virtual void draw(); private: + static void onFocusEdit(LLFocusableElement* ctrl, void* data); static void onCommitAny(LLUICtrl* ctrl, void* data); static void onCommitUserOnly(LLUICtrl* ctrl, void* data); static void onCommitTitle(LLUICtrl* ctrl, void* data); diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp index 0152990798..dbe24d40e0 100644 --- a/indra/newview/llpanelgrouplandmoney.cpp +++ b/indra/newview/llpanelgrouplandmoney.cpp @@ -238,7 +238,7 @@ void LLPanelGroupLandMoney::impl::onMapButton() F32 global_x = 0.f; F32 global_y = 0.f; - sscanf(cellp->getText().c_str(), "%f %f", &global_x, &global_y); + sscanf(cellp->getValue().asString().c_str(), "%f %f", &global_x, &global_y); // Hack: Use the agent's z-height F64 global_z = gAgent.getPositionGlobal().mdV[VZ]; diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index ce824cbb6d..a67692afa6 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -790,7 +790,6 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl, { row["columns"][column_index]["column"] = "checkbox"; row["columns"][column_index]["type"] = "checkbox"; - row["columns"][column_index]["value"] = (*ra_it)->mName; check_box_index = column_index; ++column_index; } @@ -1058,7 +1057,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect() if (mi == gdatap->mMembers.end()) continue; LLGroupMemberData* member_data = (*mi).second; // Is the member an owner? - if ( member_data->isInRole(gdatap->mOwnerRole) ) + if ( member_data && member_data->isInRole(gdatap->mOwnerRole) ) { // Can't remove other owners. cb_enable = FALSE; @@ -1870,7 +1869,7 @@ BOOL LLPanelGroupRolesSubTab::postBuildSubTab(LLView* root) mRoleDescription->setCommitOnFocusLost(TRUE); mRoleDescription->setCallbackUserData(this); mRoleDescription->setCommitCallback(onDescriptionCommit); - mRoleDescription->setFocusReceivedCallback(onDescriptionCommit); + mRoleDescription->setFocusReceivedCallback(onDescriptionFocus, this); setFooterEnabled(FALSE); @@ -2329,6 +2328,16 @@ void LLPanelGroupRolesSubTab::onPropertiesKey(LLLineEditor* ctrl, void* user_dat } // static +void LLPanelGroupRolesSubTab::onDescriptionFocus(LLFocusableElement* ctrl, void* user_data) +{ + LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data); + if (!self) return; + + self->mHasRoleChange = TRUE; + self->notifyObservers(); +} + +// static void LLPanelGroupRolesSubTab::onDescriptionCommit(LLUICtrl* ctrl, void* user_data) { LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data); diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index b0b635eb57..13d64d4edb 100644 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -256,6 +256,7 @@ public: static void onPropertiesKey(LLLineEditor*, void*); static void onDescriptionCommit(LLUICtrl*, void*); + static void onDescriptionFocus(LLFocusableElement*, void*); static void onMemberVisibilityChange(LLUICtrl*, void*); void handleMemberVisibilityChange(bool value); diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index bc297354f7..74936dce0c 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -496,7 +496,7 @@ void LLPanelLogin::show(const LLRect &rect, void (*callback)(S32 option, void* user_data), void* callback_data) { - new LLPanelLogin(rect, show_server, callback, callback_data); + new LLPanelLogin(rect, show_server, callback, callback_data); LLWebBrowserCtrl* web_browser = LLUICtrlFactory::getWebBrowserCtrlByName(sInstance, "login_html"); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index c3d949d3df..2463e62d7f 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -350,7 +350,7 @@ void LLPanelObject::getState( ) //forfeit focus if (gFocusMgr.childHasKeyboardFocus(this)) { - gFocusMgr.setKeyboardFocus(NULL, NULL); + gFocusMgr.setKeyboardFocus(NULL); } // Disable all text input fields diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index c288c6aaed..e7b5e79377 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -171,7 +171,7 @@ void LLPanelVolume::getState( ) //forfeit focus if (gFocusMgr.childHasKeyboardFocus(this)) { - gFocusMgr.setKeyboardFocus(NULL, NULL); + gFocusMgr.setKeyboardFocus(NULL); } // Disable all text input fields diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 9fa364a339..61bda9dfc0 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -1607,7 +1607,7 @@ void LLPreviewGesture::onClickAdd(void* data) if (!library_item) return; const LLScrollListCell* library_cell = library_item->getColumn(0); - const std::string& library_text = library_cell->getText(); + const std::string& library_text = library_cell->getValue().asString(); self->addStep(library_text); diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 6c377009f2..06286927d4 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -960,7 +960,7 @@ void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data) S32 row = 0; S32 column = 0; const LLScrollListCell* cell = item->getColumn(0); - LLString line(cell->getText()); + LLString line(cell->getValue().asString()); line.erase(0, 1); LLString::replaceChar(line, ',',' '); LLString::replaceChar(line, ')',' '); diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp index fae04871be..b92a6d58c8 100644 --- a/indra/newview/llpreviewsound.cpp +++ b/indra/newview/llpreviewsound.cpp @@ -106,7 +106,7 @@ void LLPreviewSound::auditionSound( void *userdata ) if(item && gAudiop) { LLVector3d lpos_global = gAgent.getPositionGlobal(); - F32 volume = SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX"); + F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX"); gAudiop->triggerSound(item->getAssetUUID(), gAgent.getID(), volume, lpos_global); } } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index f12f5763ef..b0b9fd33d1 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2304,7 +2304,7 @@ BOOL idle_startup() audio_update_volume(); // reset keyboard focus to sane state of pointing at world - gFocusMgr.setKeyboardFocus(NULL, NULL); + gFocusMgr.setKeyboardFocus(NULL); #if 0 // sjb: enable for auto-enabling timer display gDebugView->mFastTimerView->setVisible(TRUE); diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 4d49d33184..8c4fc833db 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -100,7 +100,6 @@ const LLColor4 SIM_WARN_COLOR(1.f, 1.f, 0.f, 1.f); const LLColor4 SIM_FULL_COLOR(1.f, 0.f, 0.f, 1.f); const F32 ICON_TIMER_EXPIRY = 3.f; // How long the balance and health icons should flash after a change. const F32 ICON_FLASH_FREQUENCY = 2.f; -const S32 GRAPHIC_FUDGE = 4; const S32 TEXT_HEIGHT = 18; static void onClickParcelInfo(void*); @@ -153,13 +152,13 @@ LLStatusBar::LLStatusBar(const std::string& name, const LLRect& rect) childSetAction("scriptout", onClickScriptDebug, this); childSetAction("health", onClickHealth, this); - childSetAction("fly", onClickFly, this); + childSetAction("no_fly", onClickFly, this); childSetAction("buyland", onClickBuyLand, this ); childSetAction("buycurrency", onClickBuyCurrency, this ); - childSetAction("build", onClickBuild, this ); - childSetAction("scripts", onClickScripts, this ); + childSetAction("no_build", onClickBuild, this ); + childSetAction("no_scripts", onClickScripts, this ); childSetAction("restrictpush", onClickPush, this ); - childSetAction("status_voice", onClickVoice, this ); + childSetAction("status_no_voice", onClickVoice, this ); childSetCommitCallback("search_editor", onCommitSearch, this); childSetAction("search_btn", onClickSearch, this); @@ -304,7 +303,7 @@ void LLStatusBar::refresh() // Health childGetRect( "health", buttonRect ); - r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); + r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect("health", r); x += buttonRect.getWidth(); @@ -324,27 +323,32 @@ void LLStatusBar::refresh() (parcel && !parcel->getAllowFly()) ) { // No Fly Zone - childGetRect( "fly", buttonRect ); - childSetVisible( "fly", true ); - r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); - childSetRect( "fly", r ); + childGetRect( "no_fly", buttonRect ); + childSetVisible( "no_fly", true ); + r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); + childSetRect( "no_fly", r ); x += buttonRect.getWidth(); } else { - childSetVisible("fly", false); + // Fly Zone + childSetVisible("no_fly", false); } BOOL no_build = parcel && !parcel->getAllowModify(); - childSetVisible("build", no_build); if (no_build) { - childGetRect( "build", buttonRect ); + childSetVisible("no_build", TRUE); + childGetRect( "no_build", buttonRect ); // No Build Zone - r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); - childSetRect( "build", r ); + r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); + childSetRect( "no_build", r ); x += buttonRect.getWidth(); } + else + { + childSetVisible("no_build", FALSE); + } BOOL no_scripts = FALSE; if((region @@ -354,35 +358,56 @@ void LLStatusBar::refresh() { no_scripts = TRUE; } - childSetVisible("scripts", no_scripts); if (no_scripts) { // No scripts - childGetRect( "scripts", buttonRect ); - r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); - childSetRect( "scripts", r ); + childSetVisible("no_scripts", TRUE); + childGetRect( "no_scripts", buttonRect ); + r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); + childSetRect( "no_scripts", r ); x += buttonRect.getWidth(); } + else + { + // Yes scripts + childSetVisible("no_scripts", FALSE); + } BOOL no_region_push = (region && region->getRestrictPushObject()); BOOL no_push = no_region_push || (parcel && parcel->getRestrictPushObject()); - childSetVisible("restrictpush", no_push); if (no_push) { + childSetVisible("restrictpush", TRUE); childGetRect( "restrictpush", buttonRect ); - r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); + r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "restrictpush", r ); x += buttonRect.getWidth(); } + else + { + childSetVisible("restrictpush", FALSE); + } + BOOL voice_enabled = gVoiceClient->voiceEnabled(); BOOL have_voice = parcel && parcel->getVoiceEnabled(); - childSetVisible("status_voice", have_voice); - if (have_voice) + if (!voice_enabled) { - childGetRect( "status_voice", buttonRect ); - r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); - childSetRect( "status_voice", r ); - x += buttonRect.getWidth(); + childSetVisible("status_no_voice", FALSE); + } + else + { + if (have_voice) + { + childSetVisible("status_no_voice", FALSE); + } + else if (!have_voice) + { + childSetVisible("status_no_voice", TRUE); + childGetRect( "status_no_voice", buttonRect ); + r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); + childSetRect( "status_no_voice", r ); + x += buttonRect.getWidth(); + } } BOOL canBuyLand = parcel @@ -512,7 +537,7 @@ void LLStatusBar::refresh() mTextParcelName->setText(location_name); // Adjust region name and parcel name - x += 4; + x += 8; const S32 PARCEL_RIGHT = llmin(mTextTime->getRect().mLeft, mTextParcelName->getTextPixelWidth() + x + 5); r.set(x+4, mRect.getHeight() - 2, PARCEL_RIGHT, 0); @@ -672,8 +697,7 @@ static void onClickPush(void* ) static void onClickVoice(void* ) { - LLNotifyBox::showXml("VoiceAvailablity"); - //LLFirstUse::useVoice(); + LLNotifyBox::showXml("NoVoice"); } static void onClickBuild(void*) @@ -708,7 +732,7 @@ static void onClickBuyLand(void*) void LLStatusBar::setupDate() { // fill the day array with what's in the xui - LLString day_list = childGetText("StatBarDaysOfWeek"); + LLString day_list = getFormattedUIString("StatBarDaysOfWeek"); size_t length = day_list.size(); // quick input check @@ -732,7 +756,7 @@ void LLStatusBar::setupDate() } // fill the day array with what's in the xui - LLString month_list = childGetText( "StatBarMonthsOfYear" ); + LLString month_list = getFormattedUIString( "StatBarMonthsOfYear" ); length = month_list.size(); // quick input check diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 06a4ea097f..465a40c1ef 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -373,7 +373,6 @@ public: { S32 line_height = (S32)(LLFontGL::sMonospace->getLineHeight() + .5f); setRect(LLRect(0,0,100,line_height * 4)); - updateRect(); } virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_TEX_MEM_BAR; }; diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp index e7a5445ef6..c80edd0eab 100644 --- a/indra/newview/lltoolbar.cpp +++ b/indra/newview/lltoolbar.cpp @@ -60,6 +60,11 @@ #include "llvieweruictrlfactory.h" #include "llviewerwindow.h" #include "lltoolgrab.h" +#include "llcombobox.h" +#include "llfloaterchat.h" +#include "llfloatermute.h" +#include "llimpanel.h" +#include "llscrolllistctrl.h" #if LL_DARWIN @@ -100,24 +105,20 @@ F32 LLToolBar::sInventoryAutoOpenTime = 1.f; // Functions // -LLToolBar::LLToolBar(const std::string& name, const LLRect& r) -: LLPanel(name, r, BORDER_NO) +LLToolBar::LLToolBar() +: LLPanel() #if LL_DARWIN , mResizeHandle(NULL) #endif // LL_DARWIN { setIsChrome(TRUE); - setFollows( FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM ); - - gUICtrlFactory->buildPanel(this, "panel_toolbar.xml"); - mIsFocusRoot = TRUE; - + setFocusRoot(TRUE); } BOOL LLToolBar::postBuild() { - childSetAction("communicate_btn", onClickCommunicate, this); + childSetCommitCallback("communicate_btn", onClickCommunicate, this); childSetControlName("communicate_btn", "ShowCommunicate"); childSetAction("chat_btn", onClickChat, this); @@ -270,29 +271,47 @@ void LLToolBar::layoutButtons() } #endif // LL_DARWIN + LLButton* chat_button = LLUICtrlFactory::getButtonByName(this, "chat_btn"); + if (chat_button) + { + width -= chat_button->getRect().getWidth() + pad; + } + // We actually want to extend "pad" pixels off the right edge of the // screen, such that the rightmost button is aligned. - F32 segment_width = (F32)(width + pad) / (F32)count; - S32 btn_width = lltrunc(segment_width - pad); + S32 segment_width = llround((F32)(width) / ((F32)count - 1.f)); + S32 btn_width = segment_width - pad; // Evenly space all views S32 height = -1; S32 i = count - 1; - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) + S32 x = pad; + for (child_list_const_reverse_iter_t child_iter = getChildList()->rbegin(); + child_iter != getChildList()->rend(); ++child_iter) { LLView *btn_view = *child_iter; - if(btn_view->getWidgetType() == WIDGET_TYPE_BUTTON) + if(btn_view->getWidgetType() == WIDGET_TYPE_BUTTON || btn_view->getWidgetType() == WIDGET_TYPE_FLYOUT_BUTTON) { if (height < 0) { height = btn_view->getRect().getHeight(); } - S32 x = llround(i*segment_width); - S32 y = 0; - LLRect r; - r.setOriginAndSize(x, y, btn_width, height); - btn_view->setRect(r); + + LLRect r; + + if (btn_view->getName() == "chat_btn") + { + r.setOriginAndSize(x, 0, btn_view->getRect().getWidth(), height); + x += btn_view->getRect().getWidth() + pad; + } + else + { + r.setOriginAndSize(x, 0, btn_width, height); + x += segment_width; + } + + btn_view->setOrigin(r.mLeft, r.mBottom); + btn_view->reshape(r.getWidth(), r.getHeight()); i--; } } @@ -321,6 +340,7 @@ void LLToolBar::refresh() childSetEnabled("build_btn", gParcelMgr->agentCanBuild() ); + // Check to see if we're in build mode BOOL build_mode = gToolMgr->inEdit(); // And not just clicking on a scripted object @@ -329,13 +349,135 @@ void LLToolBar::refresh() build_mode = FALSE; } gSavedSettings.setBOOL("BuildBtnState", build_mode); + + updateCommunicateList(); +} + +void LLToolBar::updateCommunicateList() +{ + LLFlyoutButton* communicate_button = (LLFlyoutButton*)getChildByName("communicate_btn", TRUE); + if (communicate_button) + { + LLSD selected = communicate_button->getValue(); + + communicate_button->removeall(); + + LLFloater* frontmost_floater = LLFloaterChatterBox::getInstance()->getActiveFloater(); + LLScrollListItem* itemp = NULL; + + itemp = communicate_button->add(LLFloaterMyFriends::getInstance()->getShortTitle(), LLSD("contacts"), ADD_TOP); + if (LLFloaterMyFriends::getInstance() == frontmost_floater) + { + ((LLScrollListText*)itemp->getColumn(0))->setFontStyle(LLFontGL::BOLD); + // make sure current tab is selected in list + if (selected.isUndefined()) + { + selected = itemp->getValue(); + } + } + itemp = communicate_button->add(LLFloaterChat::getInstance()->getShortTitle(), LLSD("local chat"), ADD_TOP); + if (LLFloaterChat::getInstance() == frontmost_floater) + { + ((LLScrollListText*)itemp->getColumn(0))->setFontStyle(LLFontGL::BOLD); + if (selected.isUndefined()) + { + selected = itemp->getValue(); + } + } + communicate_button->addSeparator(ADD_TOP); + communicate_button->add(getUIString("Redock Windows"), LLSD("redock"), ADD_TOP); + communicate_button->addSeparator(ADD_TOP); + communicate_button->add(LLFloaterMute::getInstance()->getShortTitle(), LLSD("mute list"), ADD_TOP); + + std::set<LLViewHandle>::const_iterator floater_handle_it; + + if (gIMMgr->getIMFloaterHandles().size() > 0) + { + communicate_button->addSeparator(ADD_TOP); + } + + for(floater_handle_it = gIMMgr->getIMFloaterHandles().begin(); floater_handle_it != gIMMgr->getIMFloaterHandles().end(); ++floater_handle_it) + { + LLFloaterIMPanel* im_floaterp = (LLFloaterIMPanel*)LLFloater::getFloaterByHandle(*floater_handle_it); + if (im_floaterp) + { + LLString floater_title = im_floaterp->getNumUnreadMessages() > 0 ? "*" : ""; + floater_title.append(im_floaterp->getShortTitle()); + itemp = communicate_button->add(floater_title, im_floaterp->getSessionID(), ADD_TOP); + if (im_floaterp == frontmost_floater) + { + ((LLScrollListText*)itemp->getColumn(0))->setFontStyle(LLFontGL::BOLD); + if (selected.isUndefined()) + { + selected = itemp->getValue(); + } + } + } + } + + communicate_button->setToggleState(gSavedSettings.getBOOL("ShowCommunicate")); + communicate_button->setValue(selected); + } } // static -void LLToolBar::onClickCommunicate(void* user_data) +void LLToolBar::onClickCommunicate(LLUICtrl* ctrl, void* user_data) { - LLFloaterChatterBox::toggleInstance(LLSD()); + LLToolBar* toolbar = (LLToolBar*)user_data; + LLFlyoutButton* communicate_button = (LLFlyoutButton*)toolbar->getChildByName("communicate_btn", TRUE); + + LLSD selected_option = communicate_button->getValue(); + + if (selected_option.asString() == "contacts") + { + LLFloaterMyFriends::showInstance(); + } + else if (selected_option.asString() == "local chat") + { + LLFloaterChat::showInstance(); + } + else if (selected_option.asString() == "redock") + { + LLFloaterChatterBox::getInstance()->addFloater(LLFloaterMyFriends::getInstance(), FALSE); + LLFloaterChatterBox::getInstance()->addFloater(LLFloaterChat::getInstance(), FALSE); + LLUUID session_to_show; + + std::set<LLViewHandle>::const_iterator floater_handle_it; + for(floater_handle_it = gIMMgr->getIMFloaterHandles().begin(); floater_handle_it != gIMMgr->getIMFloaterHandles().end(); ++floater_handle_it) + { + LLFloater* im_floaterp = LLFloater::getFloaterByHandle(*floater_handle_it); + if (im_floaterp) + { + if (im_floaterp->isFrontmost()) + { + session_to_show = ((LLFloaterIMPanel*)im_floaterp)->getSessionID(); + } + LLFloaterChatterBox::getInstance()->addFloater(im_floaterp, FALSE); + } + } + + LLFloaterChatterBox::showInstance(session_to_show); + } + else if (selected_option.asString() == "mute list") + { + LLFloaterMute::showInstance(); + } + else if (selected_option.isUndefined()) // user just clicked the communicate button, treat as toggle + { + if (LLFloaterChatterBox::getInstance()->getFloaterCount() == 0) + { + LLFloaterMyFriends::toggleInstance(); + } + else + { + LLFloaterChatterBox::toggleInstance(); + } + } + else // otherwise selection_option is a specific IM session id + { + LLFloaterChatterBox::showInstance(selected_option); + } } diff --git a/indra/newview/lltoolbar.h b/indra/newview/lltoolbar.h index c43c80b095..85adba8c55 100644 --- a/indra/newview/lltoolbar.h +++ b/indra/newview/lltoolbar.h @@ -47,7 +47,7 @@ class LLToolBar : public LLPanel { public: - LLToolBar(const std::string& name, const LLRect& rect ); + LLToolBar(); ~LLToolBar(); /*virtual*/ BOOL postBuild(); @@ -70,7 +70,7 @@ public: void refresh(); // callbacks - static void onClickCommunicate(void*); + static void onClickCommunicate(LLUICtrl*, void*); static void onClickChat(void* data); static void onClickAppearance(void* data); static void onClickClothing(void* data); @@ -86,8 +86,13 @@ public: static F32 sInventoryAutoOpenTime; private: + void updateCommunicateList(); + + +private: BOOL mInventoryAutoOpen; LLFrameTimer mInventoryAutoOpenTimer; + S32 mNumUnreadIMs; #if LL_DARWIN LLFakeResizeHandle *mResizeHandle; #endif // LL_DARWIN diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp index d26bdab921..a27053faa3 100644 --- a/indra/newview/lltoolplacer.cpp +++ b/indra/newview/lltoolplacer.cpp @@ -216,7 +216,7 @@ BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics ) // Play creation sound if (gAudiop) { - F32 volume = gSavedSettings.getF32("AudioLevelUI"); + F32 volume = gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI"); gAudiop->triggerSound( LLUUID(gSavedSettings.getString("UISndObjectCreate")), gAgent.getID(), volume); } diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index ac90a06a57..8e742bd655 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -122,8 +122,10 @@ void audio_update_volume(bool force_update) if (gAudiop) { F32 music_volume = gSavedSettings.getF32("AudioLevelMusic"); + BOOL music_muted = gSavedSettings.getBOOL("MuteMusic"); music_volume = mute_volume * master_volume * (music_volume*music_volume); - gAudiop->setInternetStreamGain ( music_volume ); + gAudiop->setInternetStreamGain ( music_muted ? 0.f : music_volume ); + } // Streaming Media @@ -131,7 +133,8 @@ void audio_update_volume(bool force_update) { F32 media_volume = gSavedSettings.getF32("AudioLevelMedia"); media_volume = mute_volume * master_volume * (media_volume*media_volume); - LLMediaEngine::getInstance()->setVolume(media_volume); + BOOL media_muted = gSavedSettings.getBOOL("MuteMedia"); + LLMediaEngine::getInstance()->setVolume(media_muted ? 0.f : media_volume); } // Voice @@ -139,8 +142,9 @@ void audio_update_volume(bool force_update) { F32 voice_volume = gSavedSettings.getF32("AudioLevelVoice"); voice_volume = mute_volume * master_volume * voice_volume; - gVoiceClient->setVoiceVolume(voice_volume); - gVoiceClient->setMicGain(gSavedSettings.getF32("AudioLevelMic")); + BOOL voice_mute = gSavedSettings.getBOOL("MuteVoice"); + gVoiceClient->setVoiceVolume(voice_mute ? 0.f : voice_volume); + gVoiceClient->setMicGain(voice_mute ? 0.f : gSavedSettings.getF32("AudioLevelMic")); if (!gViewerWindow->getActive() && (gSavedSettings.getBOOL("MuteWhenMinimized"))) { @@ -206,7 +210,7 @@ void audio_update_wind(bool force_update) // don't use the setter setMaxWindGain() because we don't // want to screw up the fade-in on startup by setting actual source gain // outside the fade-in. - gAudiop->mMaxWindGain = gSavedSettings.getF32("AudioLevelAmbient"); + gAudiop->mMaxWindGain = gSavedSettings.getBOOL("MuteAmbient") ? 0.f : gSavedSettings.getF32("AudioLevelAmbient"); last_camera_water_height = camera_water_height; gAudiop->updateWind(gRelativeWindVec, camera_water_height); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 2fccdcd153..fdc0047f95 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2103,7 +2103,7 @@ class LLObjectMute : public view_listener_t else { gMuteListp->add(mute); - gFloaterMute->show(); + LLFloaterMute::showInstance(); } return true; @@ -5309,7 +5309,7 @@ class LLShowFloater : public view_listener_t } else if (floater_name == "mute list") { - LLFloaterMute::toggle(NULL); + LLFloaterMute::toggleInstance(); } else if (floater_name == "camera controls") { @@ -5355,7 +5355,7 @@ class LLShowFloater : public view_listener_t } else if (floater_name == "about region") { - LLFloaterRegionInfo::show((void *)NULL); + LLFloaterRegionInfo::showInstance(); } else if (floater_name == "grid options") { @@ -5447,7 +5447,7 @@ class LLFloaterVisible : public view_listener_t } else if (floater_name == "mute list") { - new_value = LLFloaterMute::visible(NULL); + new_value = LLFloaterMute::instanceVisible(); } else if (floater_name == "camera controls") { @@ -6963,13 +6963,12 @@ void handle_grab_texture(void* data) if(view) { LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); - LLFocusMgr::FocusLostCallback callback = gFocusMgr.getFocusCallback(); view->getPanel()->setSelection(item_id, TAKE_FOCUS_NO); view->getPanel()->openSelected(); //LLInventoryView::dumpSelectionInformation((void*)view); // restore keyboard focus - gFocusMgr.setKeyboardFocus(focus_ctrl, callback); + gFocusMgr.setKeyboardFocus(focus_ctrl); } } else diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index ebb0da016f..8a4cd16c08 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -888,10 +888,8 @@ void open_offer(const std::vector<LLUUID>& items, const std::string& from_name) //highlight item LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); - LLFocusMgr::FocusLostCallback callback; - callback = gFocusMgr.getFocusCallback(); view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO); - gFocusMgr.setKeyboardFocus(focus_ctrl, callback); + gFocusMgr.setKeyboardFocus(focus_ctrl); } } @@ -920,7 +918,7 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, LLMute mute(blocked_id, from_name, type); if (gMuteListp->add(mute)) { - gFloaterMute->show(); + LLFloaterMute::showInstance(); gFloaterMute->selectMute(blocked_id); } @@ -2192,9 +2190,13 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) BOOL is_linden = FALSE; if (gMuteListp) { - is_muted = gMuteListp->isMuted(from_id, from_name, LLMute::flagTextChat) - || gMuteListp->isMuted(owner_id, LLMute::flagTextChat); - is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT && gMuteListp->isLinden(from_name); + is_muted = gMuteListp->isMuted( + from_id, + from_name, + LLMute::flagTextChat) + || gMuteListp->isMuted(owner_id, LLMute::flagTextChat); + is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT && + gMuteListp->isLinden(from_name); } BOOL is_audible = (CHAT_AUDIBLE_FULLY == chat.mAudible); @@ -2235,7 +2237,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) BOOL visible_in_chat_bubble = FALSE; std::string verb; - color.setVec(1,1,1,1); + color.setVec(1.f,1.f,1.f,1.f); msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, DB_CHAT_MSG_BUF_SIZE, mesg); BOOL ircstyle = FALSE; @@ -3332,7 +3334,7 @@ void process_sound_trigger(LLMessageSystem *msg, void **) return; } - F32 volume = gain * gSavedSettings.getF32("AudioLevelSFX"); + F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : (gain * gSavedSettings.getF32("AudioLevelSFX")); gAudiop->triggerSound(sound_id, owner_id, volume, pos_global); } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 4c6f27944f..9243263794 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2717,7 +2717,7 @@ BOOL LLViewerObject::updateLOD() // Update volume of looping sounds if (mAudioSourcep && mAudioSourcep->isLoop()) { - F32 volume = mAudioGain * gSavedSettings.getF32("AudioLevelSFX"); + F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : (mAudioGain * gSavedSettings.getF32("AudioLevelSFX")); mAudioSourcep->setGain(volume); } return FALSE; @@ -4228,7 +4228,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow { BOOL queue = flags & LL_SOUND_FLAG_QUEUE; mAudioGain = gain; - F32 volume = gain * gSavedSettings.getF32("AudioLevelSFX"); + F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : gain * gSavedSettings.getF32("AudioLevelSFX"); mAudioSourcep->setGain(volume); mAudioSourcep->setLoop(flags & LL_SOUND_FLAG_LOOP); mAudioSourcep->setSyncMaster(flags & LL_SOUND_FLAG_SYNC_MASTER); @@ -4267,7 +4267,7 @@ void LLViewerObject::adjustAudioGain(const F32 gain) if (mAudioSourcep) { mAudioGain = gain; - F32 volume = mAudioGain * gSavedSettings.getF32("AudioLevelSFX"); + F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : mAudioGain * gSavedSettings.getF32("AudioLevelSFX"); mAudioSourcep->setGain(volume); } } diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index b0d1d3daca..0ffa37525f 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -266,23 +266,6 @@ void LLViewerParcelMgr::getDisplayInfo(S32* area_out, S32* claim_out, *dwell_out = dwell; } -void LLViewerParcelMgr::getPrimInfo(S32 &sw_max, S32 &sw_total, S32 &max, S32 &total, S32 &owner, S32 &group, S32 &other, S32& selected, F32 &parcel_object_bonus, S32 &other_clean) -{ - if (mSelected && mCurrentParcel) - { - sw_max = mCurrentParcel->getSimWideMaxPrimCapacity(); - sw_total = mCurrentParcel->getSimWidePrimCount(); - max = llround(mCurrentParcel->getMaxPrimCapacity()*mCurrentParcel->getParcelPrimBonus()); - total = mCurrentParcel->getPrimCount(); - owner = mCurrentParcel->getOwnerPrimCount(); - group = mCurrentParcel->getGroupPrimCount(); - other = mCurrentParcel->getOtherPrimCount(); - selected = mCurrentParcel->getSelectedPrimCount(); - parcel_object_bonus = mCurrentParcel->getParcelPrimBonus(); - other_clean = mCurrentParcel->getCleanOtherTime(); - } -} - S32 LLViewerParcelMgr::getSelectedArea() const { S32 rv = 0; diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index 2dd4f28169..640c8c5c57 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -134,8 +134,6 @@ public: void getDisplayInfo(S32* area, S32* claim, S32* rent, BOOL* for_sale, F32* dwell); - void getPrimInfo(S32 &sw_max, S32 &sw_total, S32 &max, S32 &total, S32 &owner, S32 &group, S32 &other, S32& selected, F32 &parcel_object_bonus, S32 &other_clean); - // Returns selected area S32 getSelectedArea() const; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index ad4b6fd616..6001cd3e58 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -366,6 +366,11 @@ F32 LLViewerRegion::getWaterHeight() const return mLandp->getWaterHeight(); } +BOOL LLViewerRegion::isVoiceEnabled() const +{ + return (getRegionFlags() & REGION_FLAGS_ALLOW_VOICE); +} + void LLViewerRegion::setRegionFlags(U32 flags) { mRegionFlags = flags; diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index a0953e561e..e42c0015df 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -109,6 +109,8 @@ public: void setWaterHeight(F32 water_level); F32 getWaterHeight() const; + BOOL isVoiceEnabled() const; + void setBillableFactor(F32 billable_factor) { mBillableFactor = billable_factor; } F32 getBillableFactor() const { return mBillableFactor; } diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 81de1eb9a8..18f07efb44 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -605,54 +605,50 @@ void LLViewerTextEditor::makePristine() BOOL LLViewerTextEditor::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen) { - if (pointInView(x, y) && getVisible()) + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) { - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) + LLView *viewp = *child_iter; + S32 local_x = x - viewp->getRect().mLeft; + S32 local_y = y - viewp->getRect().mBottom; + if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) ) { - LLView *viewp = *child_iter; - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) ) - { - return TRUE; - } + return TRUE; } + } + + if( mSegments.empty() ) + { + return TRUE; + } - if( mSegments.empty() ) + LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); + if( cur_segment ) + { + BOOL has_tool_tip = FALSE; + if( cur_segment->getStyle().getIsEmbeddedItem() ) { - return TRUE; + LLWString wtip; + has_tool_tip = getEmbeddedItemToolTipAtPos(cur_segment->getStart(), wtip); + msg = wstring_to_utf8str(wtip); } - - LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); - if( cur_segment ) + else { - BOOL has_tool_tip = FALSE; - if( cur_segment->getStyle().getIsEmbeddedItem() ) - { - LLWString wtip; - has_tool_tip = getEmbeddedItemToolTipAtPos(cur_segment->getStart(), wtip); - msg = wstring_to_utf8str(wtip); - } - else - { - has_tool_tip = cur_segment->getToolTip( msg ); - } - if( has_tool_tip ) - { - // Just use a slop area around the cursor - // Convert rect local to screen coordinates - S32 SLOP = 8; - localPointToScreen( - x - SLOP, y - SLOP, - &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); - sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP; - sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP; - } + has_tool_tip = cur_segment->getToolTip( msg ); + } + if( has_tool_tip ) + { + // Just use a slop area around the cursor + // Convert rect local to screen coordinates + S32 SLOP = 8; + localPointToScreen( + x - SLOP, y - SLOP, + &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); + sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP; + sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP; } - return TRUE; } - return FALSE; + return TRUE; } BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) @@ -759,9 +755,9 @@ BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) handled = TRUE; } - if (mTakesFocus) + if (hasTabStop()) { - setFocus( TRUE ); + setFocus(TRUE); handled = TRUE; } @@ -1016,11 +1012,7 @@ BOOL LLViewerTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask) } } - if (mTakesFocus) - { - setFocus( TRUE ); - } - + setCursorAtLocalPos( x, y, FALSE ); deselect(); @@ -1390,7 +1382,7 @@ void LLViewerTextEditor::openEmbeddedSound( LLInventoryItem* item ) const F32 SOUND_GAIN = 1.0f; if(gAudiop) { - F32 volume = SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX"); + F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : (SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX")); gAudiop->triggerSound(item->getAssetUUID(), gAgentID, volume, lpos_global); } showCopyToInvDialog( item ); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index a3611b2272..4c96083337 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -266,6 +266,8 @@ const S32 PICK_DIAMETER = 2 * PICK_HALF_WIDTH+1; const F32 MIN_DISPLAY_SCALE = 0.85f; +const S32 CONSOLE_BOTTOM_PAD = 20; + #ifdef SABINRIG /// ALL RIG STUFF bool rigControl = false; @@ -663,18 +665,17 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask // Topmost view gets a chance before the hierarchy LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); - BOOL mouse_over_top_ctrl = FALSE; if (top_ctrl) { S32 local_x, local_y; top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); if (top_ctrl->pointInView(local_x, local_y)) { - mouse_over_top_ctrl = TRUE; - if(top_ctrl->handleMouseDown(local_x, local_y, mask)) - { - return TRUE; - } + return top_ctrl->handleMouseDown(local_x, local_y, mask); + } + else + { + setTopCtrl(NULL); } } @@ -686,11 +687,6 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask llinfos << "Left Mouse Down" << LLView::sMouseHandlerMessage << llendl; LLView::sMouseHandlerMessage = ""; } - if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl) - { - // always defocus top view if we click off of it - top_ctrl->setFocus(FALSE); - } return TRUE; } else if (LLView::sDebugMouseHandling) @@ -698,12 +694,6 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask llinfos << "Left Mouse Down not handled by view" << llendl; } - if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl) - { - // always defocus top view if we click off of it - top_ctrl->setFocus(FALSE); - } - if (gDisconnected) { return FALSE; @@ -716,7 +706,7 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask // This is necessary to force clicks in the world to cause edit // boxes that might have keyboard focus to relinquish it, and hence // cause a commit to update their value. JC - gFocusMgr.setKeyboardFocus(NULL, NULL); + gFocusMgr.setKeyboardFocus(NULL); return TRUE; } } @@ -760,18 +750,17 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma // Check for hit on UI. LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); - BOOL mouse_over_top_ctrl = FALSE; if (top_ctrl) { S32 local_x, local_y; top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); if (top_ctrl->pointInView(local_x, local_y)) { - mouse_over_top_ctrl = TRUE; - if(top_ctrl->handleDoubleClick(local_x, local_y, mask)) - { - return TRUE; - } + return top_ctrl->handleDoubleClick(local_x, local_y, mask); + } + else + { + setTopCtrl(NULL); } } @@ -782,11 +771,6 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma llinfos << "Left Mouse Down" << LLView::sMouseHandlerMessage << llendl; LLView::sMouseHandlerMessage = ""; } - if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl) - { - // always defocus top view if we click off of it - top_ctrl->setFocus(FALSE); - } return TRUE; } else if (LLView::sDebugMouseHandling) @@ -794,12 +778,6 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma llinfos << "Left Mouse Down not handled by view" << llendl; } - if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl) - { - // always defocus top view if we click off of it - top_ctrl->setFocus(FALSE); - } - // Why is this here? JC 9/3/2002 if (gNoRender) { @@ -970,18 +948,17 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK } LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); - BOOL mouse_over_top_ctrl = FALSE; if (top_ctrl) { S32 local_x, local_y; top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); if (top_ctrl->pointInView(local_x, local_y)) { - mouse_over_top_ctrl = TRUE; - if(top_ctrl->handleRightMouseDown(local_x, local_y, mask)) - { - return TRUE; - } + return top_ctrl->handleRightMouseDown(local_x, local_y, mask); + } + else + { + setTopCtrl(NULL); } } @@ -992,11 +969,6 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK llinfos << "Right Mouse Down" << LLView::sMouseHandlerMessage << llendl; LLView::sMouseHandlerMessage = ""; } - if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl) - { - // always defocus top view if we click off of it - top_ctrl->setFocus(FALSE); - } return TRUE; } else if (LLView::sDebugMouseHandling) @@ -1004,12 +976,6 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK llinfos << "Right Mouse Down not handled by view" << llendl; } - if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl) - { - // always defocus top view if we click off of it - top_ctrl->setFocus(FALSE); - } - if (gToolMgr) { if(gToolMgr->getCurrentTool()->handleRightMouseDown( x, y, mask ) ) @@ -1017,7 +983,7 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK // This is necessary to force clicks in the world to cause edit // boxes that might have keyboard focus to relinquish it, and hence // cause a commit to update their value. JC - gFocusMgr.setKeyboardFocus(NULL, NULL); + gFocusMgr.setKeyboardFocus(NULL); return TRUE; } } @@ -1266,7 +1232,7 @@ void LLViewerWindow::handleFocusLost(LLWindow *window) // JC - Leave keyboard focus, so if you're popping in and out editing // a script, you don't have to click in the editor again and again. - // gFocusMgr.setKeyboardFocus( NULL, NULL ); + // gFocusMgr.setKeyboardFocus( NULL ); gShowTextEditCursor = FALSE; // If losing focus while keys are down, reset them. @@ -1746,14 +1712,6 @@ void LLViewerWindow::initBase() gDebugView->setVisible(TRUE); mRootView->addChild(gDebugView); - // HUD elements just below floaters - LLRect hud_rect = full_window; - hud_rect.mTop -= 24; - hud_rect.mBottom += STATUS_BAR_HEIGHT; - gHUDView = new LLHUDView("hud_view", hud_rect); - gHUDView->setFollowsAll(); - mRootView->addChild(gHUDView); - // Add floater view at the end so it will be on top, and give it tab priority over others mRootView->addChild(gFloaterView, -1); mRootView->addChild(gSnapshotFloaterView); @@ -1871,27 +1829,10 @@ void LLViewerWindow::initWorldUI() S32 width = mRootView->getRect().getWidth(); LLRect full_window(0, height, width, 0); - if ( gToolBar == NULL ) // Don't re-enter if objects are alreay created + if ( gBottomPanel == NULL ) // Don't re-enter if objects are alreay created { - LLRect bar_rect(-1, STATUS_BAR_HEIGHT, width+1, -1); - gToolBar = new LLToolBar("toolbar", bar_rect); - - LLRect chat_bar_rect(-1,CHAT_BAR_HEIGHT, width+1, -1); - chat_bar_rect.translate(0, STATUS_BAR_HEIGHT-1); - gChatBar = new LLChatBar("chat", chat_bar_rect); - - bar_rect.translate(0, STATUS_BAR_HEIGHT-1); - bar_rect.translate(0, CHAT_BAR_HEIGHT-1); - gOverlayBar = new LLOverlayBar("overlay", bar_rect); - // panel containing chatbar, toolbar, and overlay, over floaters - LLRect bottom_rect(-1, 2*STATUS_BAR_HEIGHT + CHAT_BAR_HEIGHT, width+1, -1); - gBottomPanel = new LLBottomPanel("bottom panel", bottom_rect); - - // the order here is important - gBottomPanel->addChild(gChatBar); - gBottomPanel->addChild(gToolBar); - gBottomPanel->addChild(gOverlayBar); + gBottomPanel = new LLBottomPanel(mRootView->getRect()); mRootView->addChild(gBottomPanel); // View for hover information @@ -1933,8 +1874,7 @@ void LLViewerWindow::initWorldUI() mRootView->addChild(gMorphView); gMorphView->setVisible(FALSE); - gFloaterMute = new LLFloaterMute(); - gFloaterMute->setVisible(FALSE); + gFloaterMute = LLFloaterMute::getInstance(); LLWorldMapView::initClass(); @@ -2450,6 +2390,12 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if(LLMenuGL::getKeyboardMode()) LLMenuGL::setKeyboardMode(FALSE); + if (gFocusMgr.getTopCtrl()) + { + gFocusMgr.setTopCtrl(NULL); + return TRUE; + } + // *TODO: get this to play well with mouselook and hidden // cursor modes, etc, and re-enable. //if (gFocusMgr.getMouseCapture()) @@ -2979,23 +2925,9 @@ BOOL LLViewerWindow::handlePerFrameHover() } // Update rectangles for the various toolbars - if (gToolBar && gChatBar && gOverlayBar && gNotifyBoxView && gConsole) + if (gOverlayBar && gNotifyBoxView && gConsole) { LLRect bar_rect(-1, STATUS_BAR_HEIGHT, getWindowWidth()+1, -1); - if (gToolBar->getVisible()) - { - gToolBar->setRect(bar_rect); - bar_rect.translate(0, STATUS_BAR_HEIGHT-1); - } - - if (gChatBar->getVisible()) - { - // fix up the height - LLRect chat_bar_rect = bar_rect; - chat_bar_rect.mTop = chat_bar_rect.mBottom + CHAT_BAR_HEIGHT + 1; - gChatBar->setRect(chat_bar_rect); - bar_rect.translate(0, CHAT_BAR_HEIGHT-1); - } LLRect notify_box_rect = gNotifyBoxView->getRect(); notify_box_rect.mBottom = bar_rect.mBottom; @@ -3015,42 +2947,16 @@ BOOL LLViewerWindow::handlePerFrameHover() if (gOverlayBar->getVisible()) { - LLRect overlay_rect = bar_rect; - overlay_rect.mTop = overlay_rect.mBottom + OVERLAY_BAR_HEIGHT; - - // Fitt's Law: Push buttons flush with bottom of screen if - // nothing else visible. - if (!gToolBar->getVisible() - && !gChatBar->getVisible()) - { - // *NOTE: this is highly depenent on the XML - // describing the position of the buttons - overlay_rect.translate(0, 0); - } - - gOverlayBar->setRect(overlay_rect); - gOverlayBar->updateRect(); - bar_rect.translate(0, gOverlayBar->getRect().getHeight()); - - gFloaterView->setSnapOffsetBottom(OVERLAY_BAR_HEIGHT); + gFloaterView->setSnapOffsetBottom(gHUDView->getRect().mBottom); } else { gFloaterView->setSnapOffsetBottom(0); } - // fix rectangle of bottom panel focus indicator - if(gBottomPanel && gBottomPanel->getFocusIndicator()) - { - LLRect focus_rect = gBottomPanel->getFocusIndicator()->getRect(); - focus_rect.mTop = (gToolBar->getVisible() ? STATUS_BAR_HEIGHT : 0) + - (gChatBar->getVisible() ? CHAT_BAR_HEIGHT : 0) - 2; - gBottomPanel->getFocusIndicator()->setRect(focus_rect); - } - // Always update console LLRect console_rect = gConsole->getRect(); - console_rect.mBottom = bar_rect.mBottom + 8; + console_rect.mBottom = gHUDView->getRect().mBottom + CONSOLE_BOTTOM_PAD; gConsole->reshape(console_rect.getWidth(), console_rect.getHeight()); gConsole->setRect(console_rect); } @@ -3628,13 +3534,6 @@ void LLViewerWindow::performPick() // if you are the parent parent = objectp; } - std::vector<LLPointer<LLViewerObject>,std::allocator<LLPointer<LLViewerObject> > > children = parent->getChildren(); - for( std::vector<LLPointer<LLViewerObject>,std::allocator<LLPointer<LLViewerObject> > >::iterator i= children.begin(); i!= children.end(); ++i ) - { - //go through - LLViewerObject* foo = *i; - foo->getRotation(); - } if (objectp->mbCanSelect) { te_offset = (te_offset == 16) ? NO_FACE : te_offset; @@ -4561,9 +4460,9 @@ void LLViewerWindow::drawMouselookInstructions() // These functions are here only because LLViewerWindow used to do the work that gFocusMgr does now. // They let other objects continue to work without change. -void LLViewerWindow::setKeyboardFocus(LLUICtrl* new_focus,void (*on_focus_lost)(LLUICtrl* old_focus)) +void LLViewerWindow::setKeyboardFocus(LLUICtrl* new_focus) { - gFocusMgr.setKeyboardFocus( new_focus, on_focus_lost ); + gFocusMgr.setKeyboardFocus( new_focus ); } LLUICtrl* LLViewerWindow::getKeyboardFocus() @@ -5033,7 +4932,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, } mIgnoreActivate = FALSE; - gFocusMgr.setKeyboardFocus(keyboard_focus, NULL); + gFocusMgr.setKeyboardFocus(keyboard_focus); mWantFullscreen = mWindow->getFullscreen(); mShowFullscreenProgress = FALSE; @@ -5233,16 +5132,22 @@ LLAlertDialog* LLViewerWindow::alertXmlEditText(const std::string& xml_filename, //////////////////////////////////////////////////////////////////////////// -LLBottomPanel::LLBottomPanel(const LLString &name, const LLRect &rect) : - LLPanel(name, rect, FALSE), +LLBottomPanel::LLBottomPanel(const LLRect &rect) : + LLPanel("", rect, FALSE), mIndicator(NULL) { // bottom panel is focus root, so Tab moves through the toolbar and button bar, and overlay setFocusRoot(TRUE); - // don't capture mouse clicks that don't hit a child - setMouseOpaque(FALSE); - setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); + // flag this panel as chrome so buttons don't grab keyboard focus setIsChrome(TRUE); + + mFactoryMap["toolbar"] = LLCallbackMap(createToolBar, NULL); + mFactoryMap["overlay"] = LLCallbackMap(createOverlayBar, NULL); + mFactoryMap["hud"] = LLCallbackMap(createHUD, NULL); + gUICtrlFactory->buildPanel(this, "panel_bars.xml", &getFactoryMap()); + + setOrigin(rect.mLeft, rect.mBottom); + reshape(rect.getWidth(), rect.getHeight()); } void LLBottomPanel::setFocusIndicator(LLView * indicator) @@ -5260,3 +5165,25 @@ void LLBottomPanel::draw() } LLPanel::draw(); } + +void* LLBottomPanel::createHUD(void* data) +{ + delete gHUDView; + gHUDView = new LLHUDView(); + return gHUDView; +} + + +void* LLBottomPanel::createOverlayBar(void* data) +{ + delete gOverlayBar; + gOverlayBar = new LLOverlayBar(); + return gOverlayBar; +} + +void* LLBottomPanel::createToolBar(void* data) +{ + delete gToolBar; + gToolBar = new LLToolBar(); + return gToolBar; +} diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index faab518879..36225cb7d3 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -185,7 +185,7 @@ public: // Handle the application becoming active (frontmost) or inactive //BOOL handleActivate(BOOL activate); - void setKeyboardFocus(LLUICtrl* new_focus,void (*on_focus_lost)(LLUICtrl* old_focus)); // new_focus = NULL to release the focus. + void setKeyboardFocus(LLUICtrl* new_focus); // new_focus = NULL to release the focus. LLUICtrl* getKeyboardFocus(); BOOL hasKeyboardFocus( const LLUICtrl* possible_focus ) const; BOOL childHasKeyboardFocus( const LLView* parent ) const; @@ -363,10 +363,15 @@ protected: class LLBottomPanel : public LLPanel { public: - LLBottomPanel(const LLString& name, const LLRect& rect); + LLBottomPanel(const LLRect& rect); void setFocusIndicator(LLView * indicator); LLView * getFocusIndicator() { return mIndicator; } /*virtual*/ void draw(); + + static void* createHUD(void* data); + static void* createOverlayBar(void* data); + static void* createToolBar(void* data); + protected: LLView * mIndicator; }; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index fc159ddc48..c6a3ff192b 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3426,7 +3426,7 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) // AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED, // AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); - F32 gain = .30f * gSavedSettings.getF32("AudioLevelAmbient"); + F32 gain = gSavedSettings.getBOOL("MuteAmbient") ? 0.f : (.30f * gSavedSettings.getF32("AudioLevelAmbient")); LLUUID& step_sound_id = getStepSound(); LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent); @@ -4401,7 +4401,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL //else { LLUUID sound_id = LLUUID(gSavedSettings.getString("UISndTyping")); - F32 volume = gSavedSettings.getF32("AudioLevelSFX"); + F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : gSavedSettings.getF32("AudioLevelSFX"); gAudiop->triggerSound(sound_id, getID(), volume, char_pos_global); } } diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index cf6b13e74c..1cbb1adada 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -43,7 +43,6 @@ #include "llcallbacklist.h" #include "llviewerregion.h" #include "llviewernetwork.h" // for gGridChoice -#include "llfloateractivespeakers.h" // for LLSpeakerMgr #include "llbase64.h" #include "llviewercontrol.h" #include "llkeyboard.h" @@ -532,7 +531,7 @@ void LLVivoxProtocolParser::CharData(const char *buffer, int length) void LLVivoxProtocolParser::processResponse(std::string tag) { -// llinfos << tag << llendl; + //llinfos << tag << llendl; if (isEvent) { @@ -768,7 +767,7 @@ static HANDLE sGatewayHandle = 0; static bool isGatewayRunning() { bool result = false; - if(sGatewayHandle != 0) + if(sGatewayHandle != 0) { DWORD waitresult = WaitForSingleObject(sGatewayHandle, 0); if(waitresult != WAIT_OBJECT_0) @@ -854,7 +853,7 @@ LLVoiceClient::LLVoiceClient() setPTTKey(keyString); mPTTIsToggle = gSavedSettings.getBOOL("PushToTalkToggle"); mEarLocation = gSavedSettings.getS32("VoiceEarLocation"); - setVoiceVolume(gSavedSettings.getF32("AudioLevelVoice")); + setVoiceVolume(gSavedSettings.getBOOL("MuteVoice") ? 0.f : gSavedSettings.getF32("AudioLevelVoice")); std::string captureDevice = gSavedSettings.getString("VoiceInputAudioDevice"); setCaptureDevice(captureDevice); std::string renderDevice = gSavedSettings.getString("VoiceOutputAudioDevice"); @@ -876,7 +875,6 @@ LLVoiceClient::LLVoiceClient() mTuningMicVolumeDirty = true; mTuningSpeakerVolume = 0; mTuningSpeakerVolumeDirty = true; - mTuningCaptureRunning = false; // gMuteListp isn't set up at this point, so we defer this until later. // gMuteListp->addObserver(&mutelist_listener); @@ -1138,14 +1136,15 @@ const char *LLVoiceClient::state2string(LLVoiceClient::state inState) CASE(stateConnectorStart); CASE(stateConnectorStarting); CASE(stateConnectorStarted); - CASE(stateMicTuningNoLogin); CASE(stateLoginRetry); CASE(stateLoginRetryWait); CASE(stateNeedsLogin); CASE(stateLoggingIn); CASE(stateLoggedIn); CASE(stateNoChannel); - CASE(stateMicTuningLoggedIn); + CASE(stateMicTuningStart); + CASE(stateMicTuningRunning); + CASE(stateMicTuningStop); CASE(stateSessionCreate); CASE(stateSessionConnect); CASE(stateJoiningSession); @@ -1164,6 +1163,7 @@ const char *LLVoiceClient::state2string(LLVoiceClient::state inState) CASE(stateJoinSessionFailed); CASE(stateJoinSessionFailedWaiting); CASE(stateJail); + CASE(stateMicTuningNoLogin); } #undef CASE @@ -1483,7 +1483,8 @@ void LLVoiceClient::stateMachine() } else if(mTuningMode) { - setState(stateMicTuningNoLogin); + mTuningExitState = stateConnectorStart; + setState(stateMicTuningStart); } break; @@ -1515,24 +1516,63 @@ void LLVoiceClient::stateMachine() } break; - case stateMicTuningNoLogin: - case stateMicTuningLoggedIn: - { - // Both of these behave essentially the same. The only difference is where the exit transition goes to. - if(mTuningMode && mVoiceEnabled && !mSessionTerminateRequested) - { - if(!mTuningCaptureRunning) + case stateMicTuningStart: + if(mUpdateTimer.hasExpired()) + { + if(mCaptureDeviceDirty || mRenderDeviceDirty) + { + // These can't be changed while in tuning mode. Set them before starting. + std::ostringstream stream; + + if(mCaptureDeviceDirty) + { + buildSetCaptureDevice(stream); + } + + if(mRenderDeviceDirty) + { + buildSetRenderDevice(stream); + } + + mCaptureDeviceDirty = false; + mRenderDeviceDirty = false; + + if(!stream.str().empty()) + { + writeString(stream.str()); + } + + // This will come around again in the same state and start the capture, after the timer expires. + mUpdateTimer.start(); + mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS); + } + else { // duration parameter is currently unused, per Mike S. tuningCaptureStartSendMessage(10000); + + setState(stateMicTuningRunning); } - - if(mTuningMicVolumeDirty || mTuningSpeakerVolumeDirty || mCaptureDeviceDirty || mRenderDeviceDirty) + } + + break; + + case stateMicTuningRunning: + if(!mTuningMode || !mVoiceEnabled || mSessionTerminateRequested || mCaptureDeviceDirty || mRenderDeviceDirty) + { + // All of these conditions make us leave tuning mode. + setState(stateMicTuningStop); + } + else + { + // process mic/speaker volume changes + if(mTuningMicVolumeDirty || mTuningSpeakerVolumeDirty) { std::ostringstream stream; if(mTuningMicVolumeDirty) { + llinfos << "setting tuning mic level to " << mTuningMicVolume << llendl; stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetMicLevel.1\">" << "<Level>" << mTuningMicVolume << "</Level>" @@ -1547,20 +1587,8 @@ void LLVoiceClient::stateMachine() << "</Request>\n\n\n"; } - if(mCaptureDeviceDirty) - { - buildSetCaptureDevice(stream); - } - - if(mRenderDeviceDirty) - { - buildSetRenderDevice(stream); - } - mTuningMicVolumeDirty = false; mTuningSpeakerVolumeDirty = false; - mCaptureDeviceDirty = false; - mRenderDeviceDirty = false; if(!stream.str().empty()) { @@ -1568,23 +1596,19 @@ void LLVoiceClient::stateMachine() } } } - else - { - // transition out of mic tuning - if(mTuningCaptureRunning) - { - tuningCaptureStopSendMessage(); - } - - if(getState() == stateMicTuningNoLogin) - { - setState(stateConnectorStart); - } - else - { - setState(stateNoChannel); - } - } + break; + + case stateMicTuningStop: + { + // transition out of mic tuning + tuningCaptureStopSendMessage(); + + setState(mTuningExitState); + + // if we exited just to change devices, this will keep us from re-entering too fast. + mUpdateTimer.start(); + mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS); + } break; @@ -1654,7 +1678,8 @@ void LLVoiceClient::stateMachine() } else if(mTuningMode) { - setState(stateMicTuningLoggedIn); + mTuningExitState = stateNoChannel; + setState(stateMicTuningStart); } else if(!mNextSessionHandle.empty()) { @@ -1880,6 +1905,12 @@ void LLVoiceClient::stateMachine() case stateJail: // We have given up. Do nothing. break; + + case stateMicTuningNoLogin: + // *TODO: Implement me. + llwarns << "stateMicTuningNoLogin not handled" + << llendl; + break; } if(mParticipantMapChanged) @@ -2183,9 +2214,9 @@ bool LLVoiceClient::inTuningMode() bool result = false; switch(getState()) { - case stateMicTuningNoLogin: - case stateMicTuningLoggedIn: + case stateMicTuningRunning: result = true; + break; default: break; } @@ -2193,10 +2224,7 @@ bool LLVoiceClient::inTuningMode() } void LLVoiceClient::tuningRenderStartSendMessage(const std::string& name, bool loop) -{ - if(!inTuningMode()) - return; - +{ mTuningAudioFile = name; std::ostringstream stream; stream @@ -2210,9 +2238,6 @@ void LLVoiceClient::tuningRenderStartSendMessage(const std::string& name, bool l void LLVoiceClient::tuningRenderStopSendMessage() { - if(!inTuningMode()) - return; - std::ostringstream stream; stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.RenderAudioStop.1\">" @@ -2224,9 +2249,8 @@ void LLVoiceClient::tuningRenderStopSendMessage() void LLVoiceClient::tuningCaptureStartSendMessage(int duration) { - if(!inTuningMode()) - return; - + llinfos << "sending CaptureAudioStart" << llendl; + std::ostringstream stream; stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.CaptureAudioStart.1\">" @@ -2234,15 +2258,12 @@ void LLVoiceClient::tuningCaptureStartSendMessage(int duration) << "</Request>\n\n\n"; writeString(stream.str()); - - mTuningCaptureRunning = true; } void LLVoiceClient::tuningCaptureStopSendMessage() { - if(!inTuningMode()) - return; - + llinfos << "sending CaptureAudioStop" << llendl; + std::ostringstream stream; stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.CaptureAudioStop.1\">" @@ -2250,7 +2271,7 @@ void LLVoiceClient::tuningCaptureStopSendMessage() writeString(stream.str()); - mTuningCaptureRunning = false; + mTuningEnergy = 0.0f; } void LLVoiceClient::tuningSetMicVolume(float volume) @@ -2914,12 +2935,16 @@ void LLVoiceClient::sessionNewEvent( LLUUID caller_id; if(IDFromName(nameString, caller_id)) { - gIMMgr->inviteToSession(LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, caller_id), - LLString::null, - caller_id, - LLString::null, - IM_SESSION_P2P_INVITE, - eventSessionHandle); + gIMMgr->inviteToSession( + LLIMMgr::computeSessionID( + IM_SESSION_P2P_INVITE, + caller_id), + LLString::null, + caller_id, + LLString::null, + IM_SESSION_P2P_INVITE, + LLIMMgr::INVITATION_TYPE_VOICE, + eventSessionHandle); } else { @@ -2985,6 +3010,7 @@ void LLVoiceClient::participantPropertiesEvent( { participant->mPTT = !isLocallyMuted; participant->mIsSpeaking = isSpeaking; + participant->mIsModeratorMuted = isModeratorMuted; if (isSpeaking) { participant->mSpeakingTimeout.reset(); @@ -3022,7 +3048,7 @@ void LLVoiceClient::muteListChanged() ///////////////////////////// // Managing list of participants LLVoiceClient::participantState::participantState(const std::string &uri) : - mURI(uri), mPTT(false), mIsSpeaking(false), mPower(0.0), mServiceType(serviceTypeUnknown), + mURI(uri), mPTT(false), mIsSpeaking(false), mIsModeratorMuted(false), mPower(0.0), mServiceType(serviceTypeUnknown), mOnMuteList(false), mUserVolume(100), mVolumeDirty(false), mAvatarIDValid(false) { } @@ -3265,6 +3291,7 @@ void LLVoiceClient::switchChannel( { // Leave any channel we may be in llinfos << "leaving channel" << llendl; + notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED); } else { @@ -3786,6 +3813,19 @@ BOOL LLVoiceClient::getIsSpeaking(const LLUUID& id) return result; } +BOOL LLVoiceClient::getIsModeratorMuted(const LLUUID& id) +{ + BOOL result = FALSE; + + participantState *participant = findParticipantByID(id); + if(participant) + { + result = participant->mIsModeratorMuted; + } + + return result; +} + F32 LLVoiceClient::getCurrentPower(const LLUUID& id) { F32 result = 0; diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index ed256b6f8c..5179bc099c 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -63,6 +63,7 @@ public: STATUS_JOINING, STATUS_JOINED, STATUS_LEFT_CHANNEL, + STATUS_VOICE_DISABLED, BEGIN_ERROR_STATUS, ERROR_CHANNEL_FULL, ERROR_CHANNEL_LOCKED, @@ -139,6 +140,7 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient> void tuningStart(); void tuningStop(); bool inTuningMode(); + bool inTuningStates(); void tuningRenderStartSendMessage(const std::string& name, bool loop); void tuningRenderStopSendMessage(); @@ -218,6 +220,7 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient> // Accessors for data related to nearby speakers BOOL getVoiceEnabled(const LLUUID& id); // true if we've received data for this avatar BOOL getIsSpeaking(const LLUUID& id); + BOOL getIsModeratorMuted(const LLUUID& id); F32 getCurrentPower(const LLUUID& id); // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is... BOOL getPTTPressed(const LLUUID& id); // This is the inverse of the "locally muted" property. BOOL getOnMuteList(const LLUUID& id); @@ -242,6 +245,7 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient> std::string mDisplayName; bool mPTT; bool mIsSpeaking; + bool mIsModeratorMuted; LLFrameTimer mSpeakingTimeout; F32 mLastSpokeTimestamp; F32 mPower; @@ -316,7 +320,9 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient> stateLoggingIn, // waiting for account handle stateLoggedIn, // account handle received stateNoChannel, // - stateMicTuningLoggedIn, // mic tuning for a logged in user + stateMicTuningStart, + stateMicTuningRunning, + stateMicTuningStop, stateSessionCreate, // need to send Session.Create command stateSessionConnect, // need to send Session.Connect command stateJoiningSession, // waiting for session handle @@ -387,7 +393,7 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient> bool mTuningMicVolumeDirty; int mTuningSpeakerVolume; bool mTuningSpeakerVolumeDirty; - bool mTuningCaptureRunning; + state mTuningExitState; // state to return to when we leave tuning mode. std::string mSpatialSessionURI; diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index e6676639e2..39f2f63066 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -111,7 +111,7 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) { mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; - mSoundSymbol.mTexture [i] = gImageList.getUIImageByID(sound_level_img[i]); + mSoundSymbol.mTexture [i] = gImageList.getImageByID(sound_level_img[i]); mSoundSymbol.mWaveActive [i] = false; mSoundSymbol.mWaveOpacity [i] = 1.0f; mSoundSymbol.mWaveExpansion [i] = 1.0f; diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index dac693885f..ec277b1a1b 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -1117,11 +1117,6 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y ) BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen ) { - if( !getVisible() || !pointInView( x, y ) ) - { - return FALSE; - } - LLVector3d pos_global = viewPosToGlobal(x, y); LLSimInfo* info = gWorldMap->simInfoFromPosGlobal(pos_global); diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 7bb12f7853..5775af68a1 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -435,7 +435,7 @@ class DarwinManifest(ViewerManifest): self.copy_action(self.src_path_of(s), os.path.join(volpath, d)) # Unmount the image - self.run_command('hdiutil detach "' + devfile + '"') + self.run_command('hdiutil detach -force "' + devfile + '"') print "Converting temp disk image to final disk image" self.run_command('hdiutil convert "%(sparse)s" -format UDZO -imagekey zlib-level=9 -o "%(final)s"' % {'sparse':sparsename, 'final':finalname}) |