diff options
author | Leslie Linden <leslie@lindenlab.com> | 2011-12-16 15:07:04 -0800 |
---|---|---|
committer | Leslie Linden <leslie@lindenlab.com> | 2011-12-16 15:07:04 -0800 |
commit | 16b6a472477bd389771fe4022e425f77ca85c2bd (patch) | |
tree | 5fd889a61378bc60f7063a8f0f3afd750368aac4 | |
parent | 22ef5853ffb768960003f1e0af3ff6d0027daeb3 (diff) |
EXP-1742 FIX -- Clicking IM notification or receiving multiple IM notifications in quick succession crashes to desktop
* Moved toast logic for mouse hover out of the draw call to avoid chain of callbacks that lead to reordering of the draw list while we are iterating over it.
-rw-r--r-- | indra/newview/llappviewer.cpp | 2 | ||||
-rw-r--r-- | indra/newview/lltoast.cpp | 146 | ||||
-rw-r--r-- | indra/newview/lltoast.h | 8 |
3 files changed, 89 insertions, 67 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b45f9c55fb..0861fe85a8 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -75,6 +75,7 @@ //#include "llfirstuse.h" #include "llrender.h" #include "llteleporthistory.h" +#include "lltoast.h" #include "lllocationhistory.h" #include "llfasttimerview.h" #include "llvector4a.h" @@ -4051,6 +4052,7 @@ void LLAppViewer::idle() LLFrameTimer::updateFrameTime(); LLFrameTimer::updateFrameCount(); LLEventTimer::updateClass(); + LLNotificationsUI::LLToast::updateClass(); LLCriticalDamp::updateInterpolants(); LLMortician::updateClass(); LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify() diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index c4b226b70b..da691a2d0c 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -140,7 +140,9 @@ LLToast::LLToast(const LLToast::Params& p) // init callbacks if present if(!p.on_delete_toast().empty()) + { mOnDeleteToastSignal.connect(p.on_delete_toast()); + } } void LLToast::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -236,7 +238,9 @@ void LLToast::setCanFade(bool can_fade) { mCanFade = can_fade; if(!mCanFade) + { mTimer->stop(); + } } //-------------------------------------------------------------------------- @@ -328,55 +332,6 @@ void LLToast::draw() drawChild(mHideBtn); } } - - updateHoveredState(); - - LLToastLifeTimer* timer = getTimer(); - if (!timer) - { - return; - } - - // Started timer means the mouse had left the toast previously. - // If toast is hovered in the current frame we should handle - // a mouse enter event. - if(timer->getStarted() && mIsHovered) - { - mOnToastHoverSignal(this, MOUSE_ENTER); - - updateTransparency(); - - //toasts fading is management by Screen Channel - - sendChildToFront(mHideBtn); - if(mHideBtn && mHideBtn->getEnabled()) - { - mHideBtn->setVisible(TRUE); - } - mToastMouseEnterSignal(this, getValue()); - } - // Stopped timer means the mouse had entered the toast previously. - // If the toast is not hovered in the current frame we should handle - // a mouse leave event. - else if(!timer->getStarted() && !mIsHovered) - { - mOnToastHoverSignal(this, MOUSE_LEAVE); - - updateTransparency(); - - //toasts fading is management by Screen Channel - - if(mHideBtn && mHideBtn->getEnabled()) - { - if( mHideBtnPressed ) - { - mHideBtnPressed = false; - return; - } - mHideBtn->setVisible(FALSE); - } - mToastMouseLeaveSignal(this, getValue()); - } } //-------------------------------------------------------------------------- @@ -440,28 +395,80 @@ void LLToast::updateHoveredState() { // mouse is not over this toast mIsHovered = false; - return; } + else + { + bool is_overlapped_by_other_floater = false; - bool is_overlapped_by_other_floater = false; - - const child_list_t* child_list = gFloaterView->getChildList(); + const child_list_t* child_list = gFloaterView->getChildList(); - // find this toast in gFloaterView child list to check whether any floater - // with higher Z-order is visible under the mouse pointer overlapping this toast - child_list_const_reverse_iter_t r_iter = std::find(child_list->rbegin(), child_list->rend(), this); - if (r_iter != child_list->rend()) - { - // skip this toast and proceed to views above in Z-order - for (++r_iter; r_iter != child_list->rend(); ++r_iter) + // find this toast in gFloaterView child list to check whether any floater + // with higher Z-order is visible under the mouse pointer overlapping this toast + child_list_const_reverse_iter_t r_iter = std::find(child_list->rbegin(), child_list->rend(), this); + if (r_iter != child_list->rend()) { - LLView* view = *r_iter; - is_overlapped_by_other_floater = view->isInVisibleChain() && view->calcScreenRect().pointInRect(x, y); - if (is_overlapped_by_other_floater) break; + // skip this toast and proceed to views above in Z-order + for (++r_iter; r_iter != child_list->rend(); ++r_iter) + { + LLView* view = *r_iter; + is_overlapped_by_other_floater = view->isInVisibleChain() && view->calcScreenRect().pointInRect(x, y); + if (is_overlapped_by_other_floater) + { + break; + } + } } + + mIsHovered = !is_overlapped_by_other_floater; } - mIsHovered = !is_overlapped_by_other_floater; + LLToastLifeTimer* timer = getTimer(); + + if (timer) + { + // Started timer means the mouse had left the toast previously. + // If toast is hovered in the current frame we should handle + // a mouse enter event. + if(timer->getStarted() && mIsHovered) + { + mOnToastHoverSignal(this, MOUSE_ENTER); + + updateTransparency(); + + //toasts fading is management by Screen Channel + + sendChildToFront(mHideBtn); + if(mHideBtn && mHideBtn->getEnabled()) + { + mHideBtn->setVisible(TRUE); + } + + mToastMouseEnterSignal(this, getValue()); + } + // Stopped timer means the mouse had entered the toast previously. + // If the toast is not hovered in the current frame we should handle + // a mouse leave event. + else if(!timer->getStarted() && !mIsHovered) + { + mOnToastHoverSignal(this, MOUSE_LEAVE); + + updateTransparency(); + + //toasts fading is management by Screen Channel + + if(mHideBtn && mHideBtn->getEnabled()) + { + if( mHideBtnPressed ) + { + mHideBtnPressed = false; + return; + } + mHideBtn->setVisible(FALSE); + } + + mToastMouseLeaveSignal(this, getValue()); + } + } } void LLToast::setBackgroundOpaque(BOOL b) @@ -553,3 +560,14 @@ S32 LLToast::notifyParent(const LLSD& info) return LLModalDialog::notifyParent(info); } + +//static +void LLToast::updateClass() +{ + for (LLInstanceTracker<LLToast>::instance_iter iter = LLInstanceTracker<LLToast>::beginInstances(); iter != LLInstanceTracker<LLToast>::endInstances(); ) + { + LLToast& toast = *iter++; + + toast.updateHoveredState(); + } +} diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 77229e7beb..0b06728935 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -27,7 +27,7 @@ #ifndef LL_LLTOAST_H #define LL_LLTOAST_H - +#include "llinstancetracker.h" #include "llpanel.h" #include "llmodaldialog.h" #include "lleventtimer.h" @@ -69,7 +69,7 @@ private : * Represents toast pop-up. * This is a parent view for all toast panels. */ -class LLToast : public LLModalDialog +class LLToast : public LLModalDialog, public LLInstanceTracker<LLToast> { friend class LLToastLifeTimer; public: @@ -102,6 +102,8 @@ public: Params(); }; + + static void updateClass(); LLToast(const LLToast::Params& p); virtual ~LLToast(); @@ -221,7 +223,7 @@ private: F32 mToastLifetime; // in seconds F32 mToastFadingTime; // in seconds - + LLPanel* mPanel; LLButton* mHideBtn; |