//-------------------------------------------------------------------------- void LLOfferHandler::onRejectToast(LLUUID& id) { LLNotificationPtr notification = LLNotifications::instance().find(id); // if (notification // && LLNotificationManager::getInstance()->getHandlerForNotification( // notification->getType()) == this // // don't delete notification since it may be used by IM floater // && !LLHandlerUtil::canAddNotifPanelToIM(notification)) // { // LLNotifications::instance().cancel(notification); // } // [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Modified: Catznip-2.5.0a // NOTE: this will be fired from LLScreenChannel::killToastByNotificationID() which treats visible and stored toasts differently if ( (notification) && (!notification->isCancelled()) && (LLNotificationManager::getInstance()->getHandlerForNotification(notification->getType()) == this) ) { LLScreenChannel* pChannel = dynamic_cast<LLScreenChannel*>(mChannel); LLToast* pToast = (pChannel) ? pChannel->getToastByNotificationID(notification->getID()) : NULL; if ( (!pToast) || (pToast->getCanBeStored()) ) { LLNotifications::instance().cancel(notification); } } // [/SL:KB] }
// virtual void LLInspectToast::onOpen(const LLSD& notification_id) { LLInspect::onOpen(notification_id); LLToast* toast = mScreenChannel->getToastByNotificationID(notification_id); if (toast == NULL) { llwarns << "Could not get requested toast from screen channel." << llendl; return; } mConnection = toast->setOnToastDestroyedCallback(boost::bind(&LLInspectToast::onToastDestroy, this, _1)); LLPanel * panel = toast->getPanel(); panel->setVisible(TRUE); panel->setMouseOpaque(FALSE); if(mPanel != NULL && mPanel->getParent() == this) { removeChild(mPanel); } addChild(panel); panel->setFocus(TRUE); mPanel = panel; LLRect panel_rect; panel_rect = panel->getRect(); reshape(panel_rect.getWidth(), panel_rect.getHeight()); LLUI::positionViewNearMouse(this); }
// 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) { LLToast* toast = (*it); toast->setVisible(FALSE); toast->stopTimer(); m_toast_pool.push_back(toast); } m_active_toasts.clear(); };
//-------------------------------------------------------------------------- void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id) { // *TODO: may be remove this function std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id); if( it == mStoredToastList.end() ) return; LLToast* toast = (*it).toast; mStoredToastList.erase(it); mRejectToastSignal(toast->getNotificationID()); }
//-------------------------------------------------------------------------- void LLScreenChannel::killToastByNotificationID(LLUUID id) { // searching among toasts on a screen std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); if( it != mToastList.end()) { LLToast* toast = it->getToast(); // if it is a notification toast and notification is UnResponded - then respond on it // else - simply destroy a toast // // NOTE: if a notification is unresponded this function will be called twice for the same toast. // At first, the notification will be discarded, at second (it will be caused by discarding), // the toast will be destroyed. if(toast && toast->isNotificationValid()) { mRejectToastSignal(toast->getNotificationID()); } else { deleteToast(toast); mToastList.erase(it); redrawToasts(); } return; } // searching among stored toasts it = find(mStoredToastList.begin(), mStoredToastList.end(), id); if (it != mStoredToastList.end()) { LLToast* toast = it->getToast(); if (toast) { // send signal to a listener to let him perform some action on toast rejecting mRejectToastSignal(toast->getNotificationID()); deleteToast(toast); } } // Call find() once more, because the mStoredToastList could have been changed // in mRejectToastSignal callback and the iterator could have become invalid. it = find(mStoredToastList.begin(), mStoredToastList.end(), id); if (it != mStoredToastList.end()) { mStoredToastList.erase(it); } }
//-------------------------------------------------------------------------- void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel) { std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); if( it != mToastList.end() && panel) { LLToast* toast = (*it).toast; LLPanel* old_panel = toast->getPanel(); toast->removeChild(old_panel); delete old_panel; toast->insertPanel(panel); toast->resetTimer(); redrawToasts(); } }
//-------------------------------------------------------------------------- void LLScreenChannel::hideToastsFromScreen() { for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++) { LLToast* toast = it->getToast(); if (toast) { toast->setVisible(FALSE); } else { llwarns << "Attempt to hide a deleted toast." << llendl; } } }
//-------------------------------------------------------------------------- void LLScreenChannel::hideToast(const LLUUID& notification_id) { std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), notification_id); if(mToastList.end() != it) { LLToast* toast = it->getToast(); if (toast) { toast->hide(); } else { llwarns << "Attempt to hide a deleted toast." << llendl; } } }
void LLScreenChannel::closeHiddenToasts(const Matcher& matcher) { // since we can't guarantee that close toast operation doesn't change mToastList // we collect matched toasts that should be closed into separate list std::list<LLToast*> toasts; for (std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++) { LLToast* toast = it->getToast(); // add to list valid toast that match to provided matcher criteria if (toast != NULL && !toast->isDead() && toast->getNotification() != NULL && !toast->getVisible() && matcher.matches(toast->getNotification())) { toasts.push_back(toast); } } // close collected toasts for (std::list<LLToast*>::iterator it = toasts.begin(); it != toasts.end(); it++) { LLToast* toast = *it; toast->closeFloater(); } }
void LLNearbyChatScreenChannel::updateSize(LLRect old_world_rect, LLRect new_world_rect) { for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) { LLToast* toast = it->get(); if (toast) { LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel()); if(panel) { reshapePanel(panel); toast->reshapeToPanel(); } } } arrangeToasts(); }
void LLNearbyChatScreenChannel::showToastsBottom() { if(mStopProcessing) return; LLRect toast_rect; updateBottom(); S32 channel_bottom = getRect().mBottom; S32 bottom = channel_bottom; S32 margin = gSavedSettings.getS32("ToastGap"); //sort active toasts std::sort(m_active_toasts.begin(),m_active_toasts.end(),sort_toasts_predicate); //calc max visible item and hide other toasts. for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) { LLToast* toast = it->get(); if (!toast) { llwarns << "NULL found in the active chat toasts list!" << llendl; continue; } S32 toast_top = bottom + toast->getRect().getHeight() + margin; if(toast_top > gFloaterView->getRect().getHeight()) { while(it!=m_active_toasts.end()) { addToToastPool(it->get()); it=m_active_toasts.erase(it); } break; } toast_rect = toast->getRect(); toast_rect.setLeftTopAndSize(getRect().mLeft , bottom + toast_rect.getHeight(), toast_rect.getWidth() ,toast_rect.getHeight()); toast->setRect(toast_rect); bottom += toast_rect.getHeight() - toast->getTopPad() + margin; } // use reverse order to provide correct z-order and avoid toast blinking for(toast_vec_t::reverse_iterator it = m_active_toasts.rbegin(); it != m_active_toasts.rend(); ++it) { LLToast* toast = it->get(); if (toast) { toast->setIsHidden(false); toast->setVisible(TRUE); } } }
bool LLNearbyChatScreenChannel::createPoolToast() { LLToastPanelBase* panel= m_create_toast_panel_callback_t(); if(!panel) return false; LLToast::Params p; p.panel = panel; p.lifetime_secs = gSavedSettings.getS32("NearbyToastLifeTime"); p.fading_time_secs = gSavedSettings.getS32("NearbyToastFadingTime"); LLToast* toast = new LLNearbyChatToast(p, this); toast->setOnFadeCallback(boost::bind(&LLNearbyChatScreenChannel::onToastFade, this, _1)); LL_DEBUGS("NearbyChat") << "Creating and pooling toast" << llendl; m_toast_pool.push_back(toast->getHandle()); return true; }
bool LLNearbyChatScreenChannel::createPoolToast() { LLToastPanelBase* panel= m_create_toast_panel_callback_t(); if(!panel) return false; LLToast::Params p; p.panel = panel; p.lifetime_secs = gSavedSettings.getS32("NearbyToastLifeTime"); p.fading_time_secs = gSavedSettings.getS32("NearbyToastFadingTime"); LLToast* toast = new LLToast(p); toast->setOnFadeCallback(boost::bind(&LLNearbyChatScreenChannel::onToastFade, this, _1)); toast->setOnToastDestroyedCallback(boost::bind(&LLNearbyChatScreenChannel::onToastDestroyed, this, _1)); m_toast_pool.push_back(toast); return true; }
//-------------------------------------------------------------------------- void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id) { std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id); if( it == mStoredToastList.end() ) return; LLToast* toast = (*it).toast; if(toast->getVisible()) { // toast is already in channel return; } toast->setIsHidden(false); toast->resetTimer(); mToastList.push_back((*it)); redrawToasts(); }
//-------------------------------------------------------------------------- void LLScreenChannel::removeAndStoreAllStorableToasts() { if(mToastList.size() == 0) return; hideToastsFromScreen(); for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();) { LLToast* toast = it->getToast(); if(toast && toast->getCanBeStored()) { storeToast(*it); it = mToastList.erase(it); } else { ++it; } } redrawToasts(); }
//-------------------------------------------------------------------------- void LLScreenChannel::loadStoredToastsToChannel() { std::vector<ToastElem>::iterator it; if(mStoredToastList.size() == 0) return; for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it) { LLToast* toast = it->getToast(); if (toast) { toast->setIsHidden(false); toast->startTimer(); mToastList.push_back(*it); } } mStoredToastList.clear(); redrawToasts(); }
//-------------------------------------------------------------------------- void LLScreenChannel::removeToastsBySessionID(LLUUID id) { if(mToastList.size() == 0) return; hideToastsFromScreen(); for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();) { LLToast* toast = it->getToast(); if(toast && toast->getSessionID() == id) { deleteToast(toast); it = mToastList.erase(it); } else { ++it; } } redrawToasts(); }
//-------------------------------------------------------------------------- void LLScreenChannel::showToastsCentre() { LLToast* toast = mToastList[0].getToast(); if (!toast) { llwarns << "Attempt to display a deleted toast." << llendl; return; } LLRect toast_rect; S32 bottom = (getRect().mTop - getRect().mBottom)/2 + toast->getRect().getHeight()/2; std::vector<ToastElem>::reverse_iterator it; for(it = mToastList.rbegin(); it != mToastList.rend(); ++it) { LLToast* toast = it->getToast(); if (!toast) { llwarns << "Attempt to display a deleted toast." << llendl; return; } toast_rect = toast->getRect(); toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + gSavedSettings.getS32("ToastGap"), toast_rect.getWidth() ,toast_rect.getHeight()); toast->setRect(toast_rect); toast->setVisible(TRUE); } }
bool LLNearbyChatScreenChannel::createPoolToast() { LLToastPanelBase* panel= m_create_toast_panel_callback_t(); if(!panel) return false; LLToast::Params p; p.panel = panel; p.lifetime_secs = gSavedSettings.getS32("NearbyToastLifeTime"); p.fading_time_secs = gSavedSettings.getS32("NearbyToastFadingTime"); LLToast* toast = new LLNearbyChatToast(p, this); reshapePanel(panel); toast->setOnFadeCallback(boost::bind(&LLNearbyChatScreenChannel::onToastFade, this, _1)); // If the toast gets somehow prematurely destroyed, deactivate it to prevent crash (STORM-1352). toast->setOnToastDestroyedCallback(boost::bind(&LLNearbyChatScreenChannel::onToastDestroyed, this, _1, false)); LL_DEBUGS("NearbyChat") << "Creating and pooling toast" << llendl; m_toast_pool.push_back(toast->getHandle()); return true; }
//-------------------------------------------------------------------------- void LLScreenChannel::addToast(const LLToast::Params& p) { bool store_toast = false, show_toast = false; mDisplayToastsAlways ? show_toast = true : show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show); store_toast = !show_toast && p.can_be_stored && mCanStoreToasts; if(!show_toast && !store_toast) { mRejectToastSignal(p.notif_id); return; } LLToast* toast = new LLToast(p); ToastElem new_toast_elem(toast->getHandle()); toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1)); toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1)); if(mControlHovering) { toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2)); toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopToastTimer, this, toast)); toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startToastTimer, this, toast)); } if(show_toast) { mToastList.push_back(new_toast_elem); if(p.can_be_stored) { // store toasts immediately - EXT-3762 storeToast(new_toast_elem); } updateShowToastsState(); redrawToasts(); } else // store_toast { mHiddenToastsNum++; storeToast(new_toast_elem); } }
void LLNearbyChatScreenChannel::showToastsBottom() { if(mStopProcessing) return; LLRect toast_rect; S32 bottom = getRect().mBottom; S32 margin = gSavedSettings.getS32("ToastGap"); for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) { LLToast* toast = (*it); S32 toast_top = bottom + toast->getRect().getHeight() + margin; if(toast_top > gFloaterView->getRect().getHeight()) { while(it!=m_active_toasts.end()) { toast->setVisible(FALSE); toast->stopTimer(); m_toast_pool.push_back(toast); it=m_active_toasts.erase(it); } break; } bottom = toast_top - toast->getTopPad(); } // 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) { LLToast* toast = (*it); S32 toast_top = bottom + toast->getTopPad(); toast_rect = toast->getRect(); toast_rect.setLeftTopAndSize(getRect().mLeft , toast_top, toast_rect.getWidth() ,toast_rect.getHeight()); toast->setRect(toast_rect); toast->setIsHidden(false); toast->setVisible(TRUE); bottom = toast->getRect().mBottom - margin; } }
void LLNearbyChatScreenChannel::addNotification(LLSD& notification) { //look in pool. if there is any message if(mStopProcessing) return; /* find last toast and check ID */ if(m_active_toasts.size()) { 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()) { panel->addMessage(notification); toast->reshapeToPanel(); toast->resetTimer(); arrangeToasts(); return; } } if(m_toast_pool.empty()) { //"pool" is empty - create one more panel if(!createPoolToast())//created toast will go to pool. so next call will find it return; addNotification(notification); return; } int chat_type = notification["chat_type"].asInteger(); if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG)) { if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) return; if(gSavedSettings.getS32("ShowScriptErrorsLocation")== 1) return; } //take 1st element from pool, (re)initialize it, put it in active toasts LLToast* toast = m_toast_pool.back(); m_toast_pool.pop_back(); LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel()); if(!panel) return; panel->init(notification); toast->reshapeToPanel(); toast->resetTimer(); m_active_toasts.insert(m_active_toasts.begin(),toast); arrangeToasts(); }
void LLNearbyChatScreenChannel::arrangeToasts() { if(mStopProcessing || isHovering()) return; if (mFloaterSnapRegion == NULL) { mFloaterSnapRegion = gViewerWindow->getRootView()->getChildView("floater_snap_region"); } if (!getParent()) { // connect to floater snap region just to get resize events, we don't care about being a proper widget mFloaterSnapRegion->addChild(this); setFollows(FOLLOWS_ALL); } LLRect toast_rect; updateRect(); LLRect channel_rect; mFloaterSnapRegion->localRectToOtherView(mFloaterSnapRegion->getLocalRect(), &channel_rect, gFloaterView); channel_rect.mLeft += 10; channel_rect.mRight = channel_rect.mLeft + 300; S32 channel_bottom = channel_rect.mBottom; // <FS:Ansariel> Configurable nearby chat toasts offset //S32 bottom = channel_bottom + 80; S32 bottom = channel_bottom + gSavedSettings.getS32("FSNearbyChatToastsOffset"); S32 margin = gSavedSettings.getS32("ToastGap"); //sort active toasts std::sort(m_active_toasts.begin(),m_active_toasts.end(),sort_toasts_predicate); //calc max visible item and hide other toasts. for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) { LLToast* toast = it->get(); if (!toast) { llwarns << "NULL found in the active chat toasts list!" << llendl; continue; } S32 toast_top = bottom + toast->getRect().getHeight() + margin; if(toast_top > channel_rect.getHeight()) { while(it!=m_active_toasts.end()) { addToToastPool(it->get()); it=m_active_toasts.erase(it); } break; } toast_rect = toast->getRect(); toast_rect.setLeftTopAndSize(channel_rect.mLeft , bottom + toast_rect.getHeight(), toast_rect.getWidth() ,toast_rect.getHeight()); toast->setRect(toast_rect); bottom += toast_rect.getHeight() - toast->getTopPad() + margin; } // use reverse order to provide correct z-order and avoid toast blinking for(toast_vec_t::reverse_iterator it = m_active_toasts.rbegin(); it != m_active_toasts.rend(); ++it) { LLToast* toast = it->get(); if (toast) { toast->setIsHidden(false); toast->setVisible(TRUE); } } }
//-------------------------------------------------------------------------- bool LLOfferHandler::processNotification(const LLSD& notify) { if(!mChannel) { return false; } LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) return false; // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { if( notification->getPayload().has("give_inventory_notification") && !notification->getPayload()["give_inventory_notification"] ) { // This is an original inventory offer, so add a script floater LLScriptFloaterManager::instance().onAddNotification(notification->getID()); } else { notification->setReusable(LLHandlerUtil::isNotificationReusable(notification)); LLUUID session_id; // if (LLHandlerUtil::canSpawnIMSession(notification)) // [RLVa:KB] - Checked: 2010-04-20 (RLVa-1.2.2a) | Added: RLVa-1.2.0f // Don't spawn a new IM session for inventory offers if this notification was subject to @shownames=n // RELEASE-RLVa: [SL-2.3.0] Test on every new release to make sure the notification gets routed the way we want it to be bool fSpawnIM = (LLHandlerUtil::canSpawnIMSession(notification)) && (!notification->getPayload().has("rlv_shownames")); if (fSpawnIM) // [/RLVa:KB] { const std::string name = LLHandlerUtil::getSubstitutionName(notification); LLUUID from_id = notification->getPayload()["from_id"]; session_id = LLHandlerUtil::spawnIMSession(name, from_id); } bool show_toast = LLHandlerUtil::canSpawnToast(notification); // bool add_notid_to_im = LLHandlerUtil::canAddNotifPanelToIM(notification); // [RLVa:KB] - Checked: 2010-04-20 (RLVa-1.2.2a) | Added: RLVa-1.2.0f // NOTE: add_notid_to_im needs to be FALSE if we suppressed spawning an IM because in that case the notification needs to // be routed to the "syswell" or the inventory offer floater will dissapear and the user won't be able to accept it bool add_notid_to_im = (fSpawnIM) && (LLHandlerUtil::canAddNotifPanelToIM(notification)); // [/RLVa:KB] if (add_notid_to_im) { LLHandlerUtil::addNotifPanelToIM(notification); } if (notification->getPayload().has("SUPPRESS_TOAST") && notification->getPayload()["SUPPRESS_TOAST"]) { LLNotificationsUtil::cancel(notification); } else if(show_toast) { LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); // don't close notification on panel destroy since it will be used by IM floater notify_box->setCloseNotificationOnDestroy(!add_notid_to_im); LLToast::Params p; p.notif_id = notification->getID(); p.notification = notification; p.panel = notify_box; p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); // we not save offer notifications to the syswell floater that should be added to the IM floater p.can_be_stored = !add_notid_to_im; LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) channel->addToast(p); // if we not add notification to IM - add it to notification well if (!add_notid_to_im) { // send a signal to the counter manager mNewNotificationSignal(); } } if (LLHandlerUtil::canLogToIM(notification)) { // log only to file if notif panel can be embedded to IM and IM is opened // [RLVa:KB] - Checked: 2010-04-20 (RLVa-1.2.2a) | Added: RLVa-1.2.0f if (notification->getPayload().has("rlv_shownames")) { // Log to chat history if this notification was subject to @shownames=n LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); } else if (add_notid_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) // [/RLVa:KB] // if (add_notid_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) { LLHandlerUtil::logToIMP2P(notification, true); } else { LLHandlerUtil::logToIMP2P(notification); } } } } else if (notify["sigtype"].asString() == "delete") { if( notification->getPayload().has("give_inventory_notification") && !notification->getPayload()["give_inventory_notification"] ) { // Remove original inventory offer script floater LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); } else { // if (LLHandlerUtil::canAddNotifPanelToIM(notification) // && !LLHandlerUtil::isIMFloaterOpened(notification)) // [SL:KB] - Checked: 2010-04-20 (RLVa-1.2.2a) | Added: RLVa-1.2.0f // Repro: // 1) have someone drop you 2 inventory items (new IM session will be spawned) // 2) accept/decline the inventory offers as they come in // -> unread IM counter shows 0 // 3) toggle "Enable plain text chat history" while the IM session with the inventory offers isn't the active session // -> unread IM counter shows -2 // -> LLHandlerUtil::decIMMesageCounter() really should be fixed to check for "0" before decreasing the count but // there are enough bugfixes in RLVa as it is already :( // Fix: // - the one and only time we need to decrease the unread IM count is when we've clicked any of the buttons on the *toast* // - since LLIMFloater::updateMessages() hides the toast when we open the IM (which resets the unread count to 0) we should // *only* decrease the unread IM count if there's a visible toast since the unread count will be at 0 otherwise anyway LLScreenChannel* pChannel = dynamic_cast<LLScreenChannel*>(mChannel); LLToast* pToast = (pChannel) ? pChannel->getToastByNotificationID(notification->getID()) : NULL; if ( (pToast) && (!pToast->getCanBeStored()) ) // [/SL:KB] { LLHandlerUtil::decIMMesageCounter(notification); } mChannel->killToastByNotificationID(notification->getID()); } } return false; }
//-------------------------------------------------------------------------- void LLScreenChannel::showToastsTop() { LLRect channel_rect = getChannelRect(); LLRect toast_rect; S32 top = channel_rect.mTop; std::vector<ToastElem>::reverse_iterator it; updateRect(); LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get()); // <FS:Ansariel> Show toasts in front of other floaters BOOL toasts_in_front = gSavedSettings.getBOOL("FSShowToastsInFront"); // Use a local variable instead of mToastList. // mToastList can be modified during recursive calls and then all iteratos will be invalidated. std::vector<ToastElem> vToastList( mToastList ); for(it = vToastList.rbegin(); it != vToastList.rend(); ++it) { if(it != vToastList.rbegin()) { LLToast* toast = (it-1)->getToast(); if (!toast) { llwarns << "Attempt to display a deleted toast." << llendl; return; } top = toast->getRect().mBottom - toast->getTopPad(); gSavedSettings.getS32("ToastGap"); } LLToast* toast = it->getToast(); if (!toast) { llwarns << "Attempt to display a deleted toast." << llendl; return; } toast_rect = toast->getRect(); toast_rect.setLeftTopAndSize(channel_rect.mRight - toast_rect.getWidth(), top, toast_rect.getWidth(), toast_rect.getHeight()); toast->setRect(toast_rect); if(floater && floater->overlapsScreenChannel()) { if(it == vToastList.rbegin()) { // move first toast above docked floater S32 shift = -floater->getRect().getHeight(); if(floater->getDockControl()) { shift -= floater->getDockControl()->getTongueHeight(); } toast->translate(0, shift); } LLRect channel_rect = getChannelRect(); // don't show toasts if there is not enough space if(toast_rect.mBottom < channel_rect.mBottom) { break; } } bool stop_showing_toasts = toast->getRect().mBottom < channel_rect.mBottom; if(!stop_showing_toasts) { if( it != vToastList.rend()-1) { S32 toast_bottom = toast->getRect().mBottom - gSavedSettings.getS32("ToastGap"); stop_showing_toasts = toast_bottom < channel_rect.mBottom; } } // at least one toast should be visible if(it == vToastList.rbegin()) { stop_showing_toasts = false; } if(stop_showing_toasts) break; if (!toast->getVisible()) { // HACK // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts toast->setVisible(TRUE); } // <FS:Ansariel> Show toasts in front of other floaters //if (!toast->hasFocus()) if (!toast->hasFocus() && !toasts_in_front) // </FS:Ansariel> Show toasts in front of other floaters { // Fixing Z-order of toasts (EXT-4862) // Next toast will be positioned under this one. gFloaterView->sendChildToBack(toast); } } // Dismiss toasts we don't have space for (STORM-391). std::vector<LLToast*> toasts_to_hide; if(it != vToastList.rend()) { mHiddenToastsNum = 0; for(; it != vToastList.rend(); it++) { LLToast* toast = it->getToast(); if (toast) { toasts_to_hide.push_back(toast); } } } for (std::vector<LLToast*>::iterator it = toasts_to_hide.begin(), end_it = toasts_to_hide.end(); it != end_it; ++it) { (*it)->hide(); } }
//-------------------------------------------------------------------------- void LLScreenChannel::showToastsBottom() { LLRect toast_rect; S32 bottom = getRect().mBottom - gFloaterView->getRect().mBottom; S32 toast_margin = 0; std::vector<ToastElem>::reverse_iterator it; LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get()); for(it = mToastList.rbegin(); it != mToastList.rend(); ++it) { if(it != mToastList.rbegin()) { LLToast* toast = (*(it-1)).toast; bottom = toast->getRect().mTop - toast->getTopPad(); toast_margin = gSavedSettings.getS32("ToastGap"); } toast_rect = (*it).toast->getRect(); toast_rect.setOriginAndSize(getRect().mRight - toast_rect.getWidth(), bottom + toast_margin, toast_rect.getWidth(), toast_rect.getHeight()); (*it).toast->setRect(toast_rect); if(floater && floater->overlapsScreenChannel()) { if(it == mToastList.rbegin()) { // move first toast above docked floater S32 shift = floater->getRect().getHeight(); if(floater->getDockControl()) { shift += floater->getDockControl()->getTongueHeight(); } (*it).toast->translate(0, shift); } LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); // don't show toasts if there is not enough space if(toast_rect.mTop > world_rect.mTop) { break; } } bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop; if(!stop_showing_toasts) { if( it != mToastList.rend()-1) { S32 toast_top = (*it).toast->getRect().mTop + gSavedSettings.getS32("ToastGap"); stop_showing_toasts = toast_top > getRect().mTop; } } // at least one toast should be visible if(it == mToastList.rbegin()) { stop_showing_toasts = false; } if(stop_showing_toasts) break; if( !(*it).toast->getVisible() ) { // HACK // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts (*it).toast->setVisible(TRUE); } if(!(*it).toast->hasFocus()) { // Fixing Z-order of toasts (EXT-4862) // Next toast will be positioned under this one. gFloaterView->sendChildToBack((*it).toast); } } if(it != mToastList.rend()) { mHiddenToastsNum = 0; for(; it != mToastList.rend(); it++) { (*it).toast->stopTimer(); (*it).toast->setVisible(FALSE); mHiddenToastsNum++; } } else { closeOverflowToastPanel(); } }