summaryrefslogtreecommitdiff
path: root/indra/newview/llnearbychathandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llnearbychathandler.cpp')
-rw-r--r--indra/newview/llnearbychathandler.cpp193
1 files changed, 146 insertions, 47 deletions
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index 1fadb126e4..ff5655dec4 100644
--- a/indra/newview/llnearbychathandler.cpp
+++ b/indra/newview/llnearbychathandler.cpp
@@ -37,7 +37,9 @@
#include "llbottomtray.h"
#include "llchatitemscontainerctrl.h"
+#include "llfirstuse.h"
#include "llfloaterscriptdebug.h"
+#include "llhints.h"
#include "llnearbychat.h"
#include "llrecentpeople.h"
@@ -60,8 +62,15 @@ LLToastPanelBase* createToastPanel()
class LLNearbyChatScreenChannel: public LLScreenChannelBase
{
+ LOG_CLASS(LLNearbyChatScreenChannel);
public:
- LLNearbyChatScreenChannel(const LLUUID& id):LLScreenChannelBase(id) { mStopProcessing = false;};
+ typedef std::vector<LLHandle<LLToast> > toast_vec_t;
+ typedef std::list<LLHandle<LLToast> > toast_list_t;
+
+ LLNearbyChatScreenChannel(const LLUUID& id):LLScreenChannelBase(id)
+ {
+ mStopProcessing = false;
+ }
void addNotification (LLSD& notification);
void arrangeToasts ();
@@ -70,7 +79,7 @@ public:
typedef boost::function<LLToastPanelBase* (void )> create_toast_panel_callback_t;
void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;}
- void onToastDestroyed (LLToast* toast);
+ void onToastDestroyed (LLToast* toast, bool app_quitting);
void onToastFade (LLToast* toast);
void reshape (S32 width, S32 height, BOOL called_from_parent);
@@ -81,33 +90,34 @@ public:
}
// hide all toasts from screen, but not remove them from a channel
- virtual void hideToastsFromScreen()
- {
- };
// removes all toasts from a channel
virtual void removeToastsFromChannel()
{
- for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
+ for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
{
- addToToastPool((*it));
+ addToToastPool(it->get());
}
m_active_toasts.clear();
};
virtual void deleteAllChildren()
{
+ LL_DEBUGS("NearbyChat") << "Clearing toast pool" << llendl;
m_toast_pool.clear();
m_active_toasts.clear();
LLScreenChannelBase::deleteAllChildren();
}
protected:
+ void deactivateToast(LLToast* toast);
void addToToastPool(LLToast* toast)
{
+ if (!toast) return;
+ LL_DEBUGS("NearbyChat") << "Pooling toast" << llendl;
toast->setVisible(FALSE);
toast->stopTimer();
toast->setIsHidden(true);
- m_toast_pool.push_back(toast);
+ m_toast_pool.push_back(toast->getHandle());
}
void createOverflowToast(S32 bottom, F32 timer);
@@ -116,31 +126,85 @@ protected:
bool createPoolToast();
- std::vector<LLToast*> m_active_toasts;
- std::list<LLToast*> m_toast_pool;
+ toast_vec_t m_active_toasts;
+ toast_list_t m_toast_pool;
bool mStopProcessing;
};
+//-----------------------------------------------------------------------------------------------
+// LLNearbyChatToast
+//-----------------------------------------------------------------------------------------------
+
+// We're deriving from LLToast to be able to override onClose()
+// in order to handle closing nearby chat toasts properly.
+class LLNearbyChatToast : public LLToast
+{
+ LOG_CLASS(LLNearbyChatToast);
+public:
+ LLNearbyChatToast(const LLToast::Params& p, LLNearbyChatScreenChannel* nc_channelp)
+ : LLToast(p),
+ mNearbyChatScreenChannelp(nc_channelp)
+ {
+ }
+
+ /*virtual*/ void onClose(bool app_quitting);
+
+private:
+ LLNearbyChatScreenChannel* mNearbyChatScreenChannelp;
+};
+
+//-----------------------------------------------------------------------------------------------
+// LLNearbyChatScreenChannel
+//-----------------------------------------------------------------------------------------------
+
+void LLNearbyChatScreenChannel::deactivateToast(LLToast* toast)
+{
+ toast_vec_t::iterator pos = std::find(m_active_toasts.begin(), m_active_toasts.end(), toast->getHandle());
+
+ if (pos == m_active_toasts.end())
+ {
+ llassert(pos == m_active_toasts.end());
+ return;
+ }
+
+ LL_DEBUGS("NearbyChat") << "Deactivating toast" << llendl;
+ m_active_toasts.erase(pos);
+}
+
void LLNearbyChatScreenChannel::createOverflowToast(S32 bottom, F32 timer)
{
//we don't need overflow toast in nearby chat
}
-void LLNearbyChatScreenChannel::onToastDestroyed(LLToast* toast)
+void LLNearbyChatScreenChannel::onToastDestroyed(LLToast* toast, bool app_quitting)
{
+ LL_DEBUGS("NearbyChat") << "Toast destroyed (app_quitting=" << app_quitting << ")" << llendl;
+
+ if (app_quitting)
+ {
+ // Viewer is quitting.
+ // Immediately stop processing chat messages (EXT-1419).
mStopProcessing = true;
}
+ else
+ {
+ // The toast is being closed by user (STORM-192).
+ // Remove it from the list of active toasts to prevent
+ // further references to the invalid pointer.
+ deactivateToast(toast);
+ }
+}
void LLNearbyChatScreenChannel::onToastFade(LLToast* toast)
{
+ LL_DEBUGS("NearbyChat") << "Toast fading" << llendl;
+
//fade mean we put toast to toast pool
if(!toast)
return;
- std::vector<LLToast*>::iterator pos = std::find(m_active_toasts.begin(),m_active_toasts.end(),toast);
- if(pos!=m_active_toasts.end())
- m_active_toasts.erase(pos);
+ deactivateToast(toast);
addToToastPool(toast);
@@ -159,13 +223,13 @@ bool LLNearbyChatScreenChannel::createPoolToast()
p.lifetime_secs = gSavedSettings.getS32("NearbyToastLifeTime");
p.fading_time_secs = gSavedSettings.getS32("NearbyToastFadingTime");
- LLToast* toast = new LLToast(p);
+ LLToast* toast = new LLNearbyChatToast(p, this);
toast->setOnFadeCallback(boost::bind(&LLNearbyChatScreenChannel::onToastFade, this, _1));
- toast->setOnToastDestroyedCallback(boost::bind(&LLNearbyChatScreenChannel::onToastDestroyed, this, _1));
-
- m_toast_pool.push_back(toast);
+
+ LL_DEBUGS("NearbyChat") << "Creating and pooling toast" << llendl;
+ m_toast_pool.push_back(toast->getHandle());
return true;
}
@@ -183,17 +247,20 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
{
LLUUID fromID = notification["from_id"].asUUID(); // agent id or object id
std::string from = notification["from"].asString();
- LLToast* toast = m_active_toasts[0];
- LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel());
-
- if(panel && panel->messageID() == fromID && panel->getFromName() == from && panel->canAddText())
+ LLToast* toast = m_active_toasts[0].get();
+ if (toast)
{
- panel->addMessage(notification);
- toast->reshapeToPanel();
- toast->resetTimer();
-
- arrangeToasts();
- return;
+ LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel());
+
+ if(panel && panel->messageID() == fromID && panel->getFromName() == from && panel->canAddText())
+ {
+ panel->addMessage(notification);
+ toast->reshapeToPanel();
+ toast->resetTimer();
+
+ arrangeToasts();
+ return;
+ }
}
}
@@ -202,6 +269,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
if(m_toast_pool.empty())
{
//"pool" is empty - create one more panel
+ LL_DEBUGS("NearbyChat") << "Empty pool" << llendl;
if(!createPoolToast())//created toast will go to pool. so next call will find it
return;
addNotification(notification);
@@ -221,7 +289,8 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
//take 1st element from pool, (re)initialize it, put it in active toasts
- LLToast* toast = m_toast_pool.back();
+ LL_DEBUGS("NearbyChat") << "Getting toast from pool" << llendl;
+ LLToast* toast = m_toast_pool.back().get();
m_toast_pool.pop_back();
@@ -234,25 +303,36 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
toast->reshapeToPanel();
toast->resetTimer();
- m_active_toasts.push_back(toast);
+ m_active_toasts.push_back(toast->getHandle());
arrangeToasts();
}
void LLNearbyChatScreenChannel::arrangeToasts()
{
- if(m_active_toasts.size() == 0 || isHovering())
- return;
-
- hideToastsFromScreen();
+ if(!isHovering())
+ {
+ showToastsBottom();
+ }
- showToastsBottom();
+ if (m_active_toasts.empty())
+ {
+ LLHints::registerHintTarget("incoming_chat", LLHandle<LLView>());
+ }
+ else
+ {
+ LLToast* toast = m_active_toasts.front().get();
+ if (toast)
+ {
+ LLHints::registerHintTarget("incoming_chat", m_active_toasts.front().get()->LLView::getHandle());
+ }
+ }
}
-int sort_toasts_predicate(LLToast* first,LLToast* second)
+int sort_toasts_predicate(LLHandle<LLToast> first, LLHandle<LLToast> second)
{
- F32 v1 = first->getTimer()->getEventTimer().getElapsedTimeF32();
- F32 v2 = second->getTimer()->getEventTimer().getElapsedTimeF32();
+ F32 v1 = first.get()->getTimer()->getEventTimer().getElapsedTimeF32();
+ F32 v2 = second.get()->getTimer()->getEventTimer().getElapsedTimeF32();
return v1 < v2;
}
@@ -270,20 +350,22 @@ void LLNearbyChatScreenChannel::showToastsBottom()
//calc max visible item and hide other toasts.
- for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
+ for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
{
- S32 toast_top = bottom + (*it)->getRect().getHeight() + margin;
+ LLToast* toast = it->get();
+ if (!toast) continue;
+
+ S32 toast_top = bottom + toast->getRect().getHeight() + margin;
if(toast_top > gFloaterView->getRect().getHeight())
{
while(it!=m_active_toasts.end())
{
- addToToastPool((*it));
+ addToToastPool(it->get());
it=m_active_toasts.erase(it);
}
break;
}
- LLToast* toast = (*it);
toast_rect = toast->getRect();
toast_rect.setLeftTopAndSize(getRect().mLeft , bottom + toast_rect.getHeight(), toast_rect.getWidth() ,toast_rect.getHeight());
@@ -294,14 +376,17 @@ void LLNearbyChatScreenChannel::showToastsBottom()
// use reverse order to provide correct z-order and avoid toast blinking
- for(std::vector<LLToast*>::reverse_iterator it = m_active_toasts.rbegin(); it != m_active_toasts.rend(); ++it)
+ for(toast_vec_t::reverse_iterator it = m_active_toasts.rbegin(); it != m_active_toasts.rend(); ++it)
+ {
+ LLToast* toast = it->get();
+ if (toast)
{
- LLToast* toast = (*it);
toast->setIsHidden(false);
toast->setVisible(TRUE);
+ }
+ }
}
-}
void LLNearbyChatScreenChannel::reshape (S32 width, S32 height, BOOL called_from_parent)
{
@@ -346,8 +431,6 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
{
if(chat_msg.mMuted == TRUE)
return;
- if(chat_msg.mSourceType == CHAT_SOURCE_AGENT && chat_msg.mFromID.notNull())
- LLRecentPeople::instance().add(chat_msg.mFromID);
if(chat_msg.mText.empty())
return;//don't process empty messages
@@ -451,6 +534,12 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
channel->addNotification(notification);
}
+ if(chat_msg.mSourceType == CHAT_SOURCE_AGENT
+ && chat_msg.mFromID.notNull()
+ && chat_msg.mFromID != gAgentID)
+ {
+ LLFirstUse::otherAvatarChatFirst();
+ }
}
void LLNearbyChatHandler::onDeleteToast(LLToast* toast)
@@ -458,4 +547,14 @@ void LLNearbyChatHandler::onDeleteToast(LLToast* toast)
}
+//-----------------------------------------------------------------------------------------------
+// LLNearbyChatToast
+//-----------------------------------------------------------------------------------------------
+
+// virtual
+void LLNearbyChatToast::onClose(bool app_quitting)
+{
+ mNearbyChatScreenChannelp->onToastDestroyed(this, app_quitting);
+}
+// EOF