diff options
Diffstat (limited to 'indra/llui')
-rw-r--r-- | indra/llui/llfloater.cpp | 22 | ||||
-rw-r--r-- | indra/llui/llmenugl.cpp | 35 | ||||
-rw-r--r-- | indra/llui/llradiogroup.cpp | 68 | ||||
-rw-r--r-- | indra/llui/llradiogroup.h | 9 | ||||
-rw-r--r-- | indra/llui/lltabcontainer.cpp | 9 | ||||
-rw-r--r-- | indra/llui/lltextbase.cpp | 3 | ||||
-rw-r--r-- | indra/llui/lltextbox.cpp | 23 | ||||
-rw-r--r-- | indra/llui/lltexteditor.cpp | 17 | ||||
-rw-r--r-- | indra/llui/llui.cpp | 17 | ||||
-rw-r--r-- | indra/llui/llui.h | 4 | ||||
-rw-r--r-- | indra/llui/lluictrl.cpp | 50 | ||||
-rw-r--r-- | indra/llui/lluictrl.h | 3 | ||||
-rw-r--r-- | indra/llui/llurlregistry.cpp | 28 | ||||
-rw-r--r-- | indra/llui/llurlregistry.h | 6 | ||||
-rw-r--r-- | indra/llui/llview.cpp | 54 | ||||
-rw-r--r-- | indra/llui/llview.h | 1 |
16 files changed, 207 insertions, 142 deletions
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 4690c54c15..a57913683b 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -592,6 +592,8 @@ void LLFloater::openFloater(const LLSD& key) mOpenSignal(this, key); onOpen(key); + + dirtyRect(); } void LLFloater::closeFloater(bool app_quitting) @@ -657,7 +659,9 @@ void LLFloater::closeFloater(bool app_quitting) } } } - + + dirtyRect(); + // Close callback mCloseSignal(this, LLSD(app_quitting)); @@ -1923,8 +1927,8 @@ void LLFloaterView::restoreAll() LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor ) { LLRect base_rect = reference_floater->getRect(); - S32 width = neighbor->getRect().getWidth(); - S32 height = neighbor->getRect().getHeight(); + LLRect::tCoordType width = neighbor->getRect().getWidth(); + LLRect::tCoordType height = neighbor->getRect().getHeight(); LLRect new_rect = neighbor->getRect(); LLRect expanded_base_rect = base_rect; @@ -1943,10 +1947,10 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF } } - S32 left_margin = llmax(0, base_rect.mLeft); - S32 right_margin = llmax(0, getRect().getWidth() - base_rect.mRight); - S32 top_margin = llmax(0, getRect().getHeight() - base_rect.mTop); - S32 bottom_margin = llmax(0, base_rect.mBottom); + LLRect::tCoordType left_margin = llmax(0, base_rect.mLeft); + LLRect::tCoordType right_margin = llmax(0, getRect().getWidth() - base_rect.mRight); + LLRect::tCoordType top_margin = llmax(0, getRect().getHeight() - base_rect.mTop); + LLRect::tCoordType bottom_margin = llmax(0, base_rect.mBottom); // find position for floater in following order // right->left->bottom->top @@ -2252,8 +2256,8 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out // floater is hosted elsewhere, so ignore return; } - S32 screen_width = getSnapRect().getWidth(); - S32 screen_height = getSnapRect().getHeight(); + LLRect::tCoordType screen_width = getSnapRect().getWidth(); + LLRect::tCoordType screen_height = getSnapRect().getHeight(); // convert to local coordinate frame LLRect snap_rect_local = getLocalSnapRect(); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index e0bb6bd5d3..f2d147ac39 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -121,6 +121,8 @@ const F32 ACTIVATE_HIGHLIGHT_TIME = 0.3f; static MenuRegistry::Register<LLMenuItemSeparatorGL> register_separator("menu_item_separator"); static MenuRegistry::Register<LLMenuItemCallGL> register_menu_item_call("menu_item_call"); static MenuRegistry::Register<LLMenuItemCheckGL> register_menu_item_check("menu_item_check"); +// Created programmatically but we need to specify custom colors in xml +static MenuRegistry::Register<LLMenuItemTearOffGL> register_menu_item_tear_off("menu_item_tear_off"); static MenuRegistry::Register<LLMenuGL> register_menu("menu"); static LLDefaultChildRegistry::Register<LLMenuGL> register_menu_default("menu"); @@ -390,8 +392,10 @@ void LLMenuItemGL::buildDrawLabel( void ) void LLMenuItemGL::onCommit( void ) { - // close all open menus by default - // if parent menu is actually visible (and we are not triggering menu item via accelerator) + // Check torn-off status to allow left-arrow keyboard navigation back + // to parent menu. + // Also, don't hide if item triggered by keyboard shortcut (and hence + // parent not visible). if (!getMenu()->getTornOff() && getMenu()->getVisible()) { @@ -408,6 +412,12 @@ void LLMenuItemGL::onCommit( void ) { getMenu()->clearHoverItem(); } + + if (mHighlight != highlight) + { + dirtyRect(); + } + mHighlight = highlight; } @@ -1233,6 +1243,8 @@ void LLMenuItemBranchGL::openMenu() branch->translate( delta_x, delta_y ); branch->setVisible( TRUE ); branch->getParent()->sendChildToFront(branch); + + dirtyRect(); } } @@ -2334,8 +2346,8 @@ void LLMenuGL::createJumpKeys() { char jump_key = uppercase_word[i]; - if (LLStringOps::isDigit(jump_key) || LLStringOps::isUpper(jump_key) && - mJumpKeys.find(jump_key) == mJumpKeys.end()) + if (LLStringOps::isDigit(jump_key) || (LLStringOps::isUpper(jump_key) && + mJumpKeys.find(jump_key) == mJumpKeys.end())) { mJumpKeys.insert(std::pair<KEY, LLMenuItemGL*>(jump_key, (*item_it))); (*item_it)->setJumpKey(jump_key); @@ -3476,16 +3488,19 @@ LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) : LLRect rect; menup->localRectToOtherView(LLRect(-1, menup->getRect().getHeight(), menup->getRect().getWidth() + 3, 0), &rect, gFloaterView); // make sure this floater is big enough for menu - mTargetHeight = (F32)(rect.getHeight() + floater_header_size + 5); + mTargetHeight = (F32)(rect.getHeight() + floater_header_size); reshape(rect.getWidth(), rect.getHeight()); setRect(rect); // attach menu to floater - menup->setFollowsAll(); + menup->setFollows( FOLLOWS_LEFT | FOLLOWS_BOTTOM ); mOldParent = menup->getParent(); addChild(menup); menup->setVisible(TRUE); - menup->translate(-menup->getRect().mLeft + 1, -menup->getRect().mBottom + 1); + LLRect menu_rect = menup->getRect(); + menu_rect.setOriginAndSize( 1, 1, + menu_rect.getWidth(), menu_rect.getHeight()); + menup->setRect(menu_rect); menup->setDropShadowed(FALSE); mMenu = menup; @@ -3513,12 +3528,6 @@ void LLTearOffMenu::draw() // animate towards target height reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), mTargetHeight, LLCriticalDamp::getInterpolant(0.05f)))); } - else - { - // when in stasis, remain big enough to hold menu contents - mTargetHeight = (F32)(mMenu->getRect().getHeight() + floater_header_size + 4); - reshape(mMenu->getRect().getWidth() + 3, mMenu->getRect().getHeight() + floater_header_size + 5); - } LLFloater::draw(); } diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp index c66b9bde2b..d1ea5843eb 100644 --- a/indra/llui/llradiogroup.cpp +++ b/indra/llui/llradiogroup.cpp @@ -45,8 +45,6 @@ #include "lluictrlfactory.h" static LLDefaultChildRegistry::Register<LLRadioGroup> r1("radio_group"); - - static RadioGroupRegistry::Register<LLRadioCtrl> register_radio_ctrl("radio_item"); @@ -83,6 +81,10 @@ LLRadioGroup::~LLRadioGroup() // virtual BOOL LLRadioGroup::postBuild() { + if (!mRadioButtons.empty()) + { + mRadioButtons[0]->setTabStop(true); + } if (mControlVariable) { setSelectedIndex(mControlVariable->getValue().asInteger()); @@ -102,7 +104,7 @@ void LLRadioGroup::setIndexEnabled(S32 index, BOOL enabled) child->setEnabled(enabled); if (index == mSelectedIndex && enabled == FALSE) { - setSelectedIndex(-1); + mSelectedIndex = -1; } break; } @@ -142,8 +144,28 @@ BOOL LLRadioGroup::setSelectedIndex(S32 index, BOOL from_event) return FALSE; } + if (mSelectedIndex >= 0) + { + LLRadioCtrl* old_radio_item = mRadioButtons[mSelectedIndex]; + old_radio_item->setTabStop(false); + old_radio_item->setValue( FALSE ); + } + else + { + mRadioButtons[0]->setTabStop(false); + } + mSelectedIndex = index; + LLRadioCtrl* radio_item = mRadioButtons[mSelectedIndex]; + radio_item->setTabStop(true); + radio_item->setValue( TRUE ); + + if (hasFocus()) + { + mRadioButtons[mSelectedIndex]->focusFirstItem(FALSE, FALSE); + } + if (!from_event) { setControlValue(getSelectedIndex()); @@ -211,33 +233,6 @@ BOOL LLRadioGroup::handleKeyHere(KEY key, MASK mask) return handled; } -void LLRadioGroup::draw() -{ - S32 current_button = 0; - - BOOL take_focus = FALSE; - if (gFocusMgr.childHasKeyboardFocus(this)) - { - take_focus = TRUE; - } - - for (button_list_t::iterator iter = mRadioButtons.begin(); - iter != mRadioButtons.end(); ++iter) - { - LLRadioCtrl* radio = *iter; - BOOL selected = (current_button == mSelectedIndex); - radio->setValue( selected ); - if (take_focus && selected && !gFocusMgr.childHasKeyboardFocus(radio)) - { - // don't flash keyboard focus when navigating via keyboard - BOOL DONT_FLASH = FALSE; - radio->focusFirstItem(FALSE, DONT_FLASH); - } - current_button++; - } - - LLView::draw(); -} // When adding a child button, we need to ensure that the radio // group gets a message when the button is clicked. @@ -259,6 +254,19 @@ bool LLRadioGroup::addChild(LLView* view, S32 tab_group) return res; } +BOOL LLRadioGroup::handleMouseDown(S32 x, S32 y, MASK mask) +{ + // grab focus preemptively, before child button takes mousecapture + // + if (hasTabStop()) + { + focusFirstItem(FALSE, FALSE); + } + + return LLUICtrl::handleMouseDown(x, y, mask); +} + + // Handle one button being clicked. All child buttons must have this // function as their callback function. diff --git a/indra/llui/llradiogroup.h b/indra/llui/llradiogroup.h index b5516307fd..914548b6aa 100644 --- a/indra/llui/llradiogroup.h +++ b/indra/llui/llradiogroup.h @@ -54,7 +54,10 @@ public: Params() : length("length"), type("type") - {} + { + // radio items are not tabbable until they are selected + tab_stop = false; + } }; /*virtual*/ ~LLRadioCtrl(); @@ -103,6 +106,7 @@ public: virtual BOOL postBuild(); virtual bool addChild(LLView* view, S32 tab_group = 0); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleKeyHere(KEY key, MASK mask); @@ -117,9 +121,6 @@ public: virtual void setValue(const LLSD& value ); virtual LLSD getValue() const; - // Draw the group, but also fix the highlighting based on the control. - void draw(); - // Update the control as needed. Userdata must be a pointer to the button. void onClickButton(LLUICtrl* clicked_radio); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 720ca692f7..b6eed3ef18 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -329,10 +329,13 @@ void LLTabContainer::draw() } // Hide all the buttons - for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + if (getTabsHidden()) { - LLTabTuple* tuple = *iter; - tuple->mButton->setVisible( FALSE ); + for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + { + LLTabTuple* tuple = *iter; + tuple->mButton->setVisible( FALSE ); + } } LLPanel::draw(); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index cb60b4fe36..0fd6a14187 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -420,8 +420,9 @@ BOOL LLTextBase::handleToolTipForUrl(LLView *view, S32 x, S32 y, std::string& ms LLToolTipMgr::instance().show(LLToolTipParams() .message(tooltip_msg) .sticky_rect(sticky_rect_screen)); + return TRUE; } - return TRUE; + return FALSE; } LLContextMenu *LLTextBase::createUrlContextMenu(const std::string &in_url) diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 810626268f..132bef0296 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -161,7 +161,12 @@ BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask) BOOL LLTextBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { - return handleToolTipForUrl(this, x, y, msg, sticky_rect_screen); + if (handleToolTipForUrl(this, x, y, msg, sticky_rect_screen)) + { + return TRUE; + } + + return LLUICtrl::handleToolTip(x, y, msg, sticky_rect_screen); } void LLTextBox::setText(const LLStringExplicit& text) @@ -297,7 +302,7 @@ LLWString LLTextBox::getWrappedText(const LLStringExplicit& in_text, F32 max_wid // find the next Url in the text string LLUrlMatch match; - while ( LLUrlRegistry::instance().findUrl(wstring_to_utf8str(wtext), match)) + while ( LLUrlRegistry::instance().findUrl(wtext, match)) { S32 start = match.getStart(); S32 end = match.getEnd() + 1; @@ -573,17 +578,21 @@ void LLTextBox::updateDisplayTextAndSegments() LLWString text = mText.getWString(); // find the next Url in the text string - while ( LLUrlRegistry::instance().findUrl(wstring_to_utf8str(text), match, + while ( LLUrlRegistry::instance().findUrl(text, match, boost::bind(&LLTextBox::onUrlLabelUpdated, this, _1, _2)) ) { // work out the char offset for the start/end of the url + S32 url_start = match.getStart(); + S32 url_end = match.getEnd(); + + // and the char offset for the label in the display text S32 seg_start = mDisplayText.size(); - S32 start = seg_start + match.getStart(); - end = start + match.getLabel().size(); + S32 start = seg_start + url_start; + S32 end = start + match.getLabel().size(); // create a segment for the text before the Url mSegments.insert(new LLNormalTextSegment(new LLStyle(), seg_start, start, *this)); - mDisplayText += text.substr(0, match.getStart()); + mDisplayText += text.substr(0, url_start); // create a segment for the Url text LLStyleSP html(new LLStyle); @@ -599,7 +608,7 @@ void LLTextBox::updateDisplayTextAndSegments() mDisplayText += utf8str_to_wstring(match.getLabel()); // move on to the rest of the text after the Url - text = text.substr(match.getEnd()+1, text.size() - match.getEnd()); + text = text.substr(url_end+1, text.size() - url_end); } // output a segment for the remaining text diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 983777b747..8d5f277b59 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1120,21 +1120,12 @@ void LLTextEditor::updateCursorXPos() } // constraint cursor to editable segments of document +// NOTE: index must be within document range S32 LLTextEditor::getEditableIndex(S32 index, bool increasing_direction) { - //// always allow editable position at end of doc - //if (index == getLength()) - //{ - // return index; - //} - segment_set_t::iterator segment_iter; S32 offset; getSegmentAndOffset(index, &segment_iter, &offset); - if (segment_iter == mSegments.end()) - { - return 0; - } LLTextSegmentPtr segmentp = *segment_iter; @@ -3194,7 +3185,11 @@ void LLTextEditor::draw() drawLineNumbers(); { - LLLocalClipRect clip(mTextRect); + // pad clipping rectangle so that cursor can draw at full width + // when at left edge of mTextRect + LLRect clip_rect(mTextRect); + clip_rect.stretch(1); + LLLocalClipRect clip(clip_rect); drawSelectionBackground(); drawPreeditMarker(); drawText(); diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 950eaf2ea7..000e85f78c 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -81,7 +81,8 @@ std::list<std::string> gUntranslated; /*static*/ LLWindow* LLUI::sWindow = NULL; /*static*/ LLHtmlHelp* LLUI::sHtmlHelp = NULL; /*static*/ LLView* LLUI::sRootView = NULL; - +/*static*/ BOOL LLUI::sDirty = FALSE; +/*static*/ LLRect LLUI::sDirtyRect; /*static*/ std::vector<std::string> LLUI::sXUIPaths; /*static*/ LLFrameTimer LLUI::sMouseIdleTimer; @@ -1603,6 +1604,20 @@ void LLUI::cleanupClass() sImageProvider->cleanUp(); } +//static +void LLUI::dirtyRect(LLRect rect) +{ + if (!sDirty) + { + sDirtyRect = rect; + sDirty = TRUE; + } + else + { + sDirtyRect.unionWith(rect); + } +} + //static void LLUI::translate(F32 x, F32 y, F32 z) diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 33338f30f9..fddf8192ad 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -174,6 +174,10 @@ public: static void loadIdentity(); static void translate(F32 x, F32 y, F32 z = 0.0f); + static LLRect sDirtyRect; + static BOOL sDirty; + static void dirtyRect(LLRect rect); + // Return the ISO639 language name ("en", "ko", etc.) for the viewer UI. // http://www.loc.gov/standards/iso639-2/php/code_list.php static std::string getLanguage(); diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 28cdb1ac27..8807e26f6b 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -506,56 +506,6 @@ void LLUICtrl::setFocus(BOOL b) } } -void LLUICtrl::onFocusReceived() -{ - // trigger callbacks - LLFocusableElement::onFocusReceived(); - - // find first view in hierarchy above new focus that is a LLUICtrl - LLView* viewp = getParent(); - LLUICtrl* last_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getLastKeyboardFocus()); - - while (viewp && !viewp->isCtrl()) - { - viewp = viewp->getParent(); - } - - // and if it has newly gained focus, call onFocusReceived() - LLUICtrl* ctrlp = static_cast<LLUICtrl*>(viewp); - if (ctrlp && (!last_focus || !last_focus->hasAncestor(ctrlp))) - { - ctrlp->onFocusReceived(); - } -} - -void LLUICtrl::onFocusLost() -{ - // trigger callbacks - LLFocusableElement::onFocusLost(); - - // find first view in hierarchy above old focus that is a LLUICtrl - LLView* viewp = getParent(); - while (viewp && !viewp->isCtrl()) - { - viewp = viewp->getParent(); - } - - // and if it has just lost focus, call onFocusReceived() - LLUICtrl* ctrlp = static_cast<LLUICtrl*>(viewp); - // hasFocus() includes any descendants - if (ctrlp && !ctrlp->hasFocus()) - { - ctrlp->onFocusLost(); - } -} - -void LLUICtrl::onTopLost() -{ - // trigger callbacks - LLFocusableElement::onTopLost(); -} - - // virtual void LLUICtrl::setTabStop( BOOL b ) { diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 4030230684..3add9393ea 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -153,9 +153,6 @@ protected: public: // LLView interface /*virtual*/ BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); - /*virtual*/ void onFocusReceived(); - /*virtual*/ void onFocusLost(); - /*virtual*/ void onTopLost(); /*virtual*/ BOOL isCtrl() const; /*virtual*/ void setTentative(BOOL b); /*virtual*/ BOOL getTentative() const; diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index f2d340deb7..6f5c694b1b 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -162,3 +162,31 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL return false; } + +bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUrlLabelCallback &cb) +{ + // boost::regex_search() only works on char or wchar_t + // types, but wchar_t is only 2-bytes on Win32 (not 4). + // So we use UTF-8 to make this work the same everywhere. + std::string utf8_text = wstring_to_utf8str(text); + if (findUrl(utf8_text, match, cb)) + { + // we cannot blindly return the start/end offsets from + // the UTF-8 string because it is a variable-length + // character encoding, so we need to update the start + // and end values to be correct for the wide string. + LLWString wurl = utf8str_to_wstring(match.getUrl()); + S32 start = text.find(wurl); + if (start == std::string::npos) + { + return false; + } + S32 end = start + wurl.size() - 1; + + match.setValues(start, end, match.getUrl(), match.getLabel(), + match.getTooltip(), match.getIcon(), + match.getMenuName(), match.getLocation()); + return true; + } + return false; +} diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index 84b033036c..85e934e4b5 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -37,10 +37,10 @@ #include "llurlentry.h" #include "llurlmatch.h" #include "llsingleton.h" +#include "llstring.h" #include <string> #include <vector> -#include <map> /// This default callback for findUrl() simply ignores any label updates void LLUrlRegistryNullCallback(const std::string &url, const std::string &label); @@ -77,6 +77,10 @@ public: bool findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback); + /// a slightly less efficient version of findUrl for wide strings + bool findUrl(const LLWString &text, LLUrlMatch &match, + const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback); + private: LLUrlRegistry(); friend class LLSingleton<LLUrlRegistry>; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 46510804f8..256c776293 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -143,6 +143,7 @@ LLView::LLView(const LLView::Params& p) LLView::~LLView() { + dirtyRect(); //llinfos << "Deleting view " << mName << ":" << (void*) this << llendl; // llassert(LLView::sIsDrawing == FALSE); @@ -602,6 +603,7 @@ void LLView::setVisible(BOOL visible) if (!getParent() || getParent()->isInVisibleChain()) { // tell all children of this view that the visibility may have changed + dirtyRect(); handleVisibilityChange( visible ); } updateBoundingRect(); @@ -673,9 +675,13 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, std::string& msg, LLRect& st LLView* viewp = *child_it; S32 local_x = x - viewp->getRect().mLeft; S32 local_y = y - viewp->getRect().mBottom; - if(viewp->pointInView(local_x, local_y) && - viewp->getVisible() && - viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen) ) + if(!viewp->pointInView(local_x, local_y) || + !viewp->getVisible()) + { + continue; + } + + if(viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen) ) { if (sDebugMouseHandling) { @@ -685,17 +691,22 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, std::string& msg, LLRect& st handled_view = viewp; break; } + + if( viewp->blockMouseEvent(x, y) ) + { + handled_view = viewp; + } } return handled_view; } BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen) { - LLView* child_handler = childrenHandleToolTip(x, y, msg, sticky_rect_screen); - BOOL handled = child_handler != NULL; + BOOL handled = FALSE; - // child widgets get priority on tooltips - if (!handled && !mToolTipMsg.empty()) + // parents provide tooltips first, which are optionally + // overridden by children + if (!mToolTipMsg.empty()) { // allow "scrubbing" over ui by showing next tooltip immediately // if previous one was still visible @@ -710,7 +721,9 @@ BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_s handled = TRUE; } - if( blockMouseEvent(x, y) ) + // child tooltips will override our own + LLView* child_handler = childrenHandleToolTip(x, y, msg, sticky_rect_screen); + if (child_handler) { handled = TRUE; } @@ -1297,7 +1310,7 @@ void LLView::drawChildren() { // Only draw views that are within the root view localRectToScreen(viewp->getRect(),&screenRect); - if ( rootRect.overlaps(screenRect) ) + if ( rootRect.overlaps(screenRect) && LLUI::sDirtyRect.overlaps(screenRect)) { glMatrixMode(GL_MODELVIEW); LLUI::pushMatrix(); @@ -1316,6 +1329,21 @@ void LLView::drawChildren() gGL.getTexUnit(0)->disable(); } +void LLView::dirtyRect() +{ + LLView* child = getParent(); + LLView* parent = child ? child->getParent() : NULL; + LLView* cur = this; + while (child && parent && parent->getParent()) + { //find third to top-most view + cur = child; + child = parent; + parent = parent->getParent(); + } + + LLUI::dirtyRect(cur->calcScreenRect()); +} + //Draw a box for debugging. void LLView::drawDebugRect() { @@ -1529,6 +1557,8 @@ void LLView::updateBoundingRect() { if (isDead()) return; + LLRect cur_rect = mBoundingRect; + if (mUseBoundingRect) { mBoundingRect = calcBoundingRect(); @@ -1543,6 +1573,12 @@ void LLView::updateBoundingRect() { getParent()->updateBoundingRect(); } + + if (mBoundingRect != cur_rect) + { + dirtyRect(); + } + } LLRect LLView::calcScreenRect() const diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 1f7e5afaae..bf3b5d0614 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -519,6 +519,7 @@ public: virtual BOOL handleUnicodeCharHere(llwchar uni_char); virtual void handleReshape(const LLRect& rect, bool by_user); + virtual void dirtyRect(); virtual void notifyParent(const LLSD& info); virtual void notifyChildren(const LLSD& info); |