diff options
-rw-r--r-- | indra/llrender/llfontfreetype.cpp | 23 | ||||
-rw-r--r-- | indra/llrender/llfontfreetype.h | 2 | ||||
-rw-r--r-- | indra/llrender/llfontgl.cpp | 57 | ||||
-rw-r--r-- | indra/llui/llfloater.cpp | 13 | ||||
-rw-r--r-- | indra/llui/llkeywords.cpp | 82 | ||||
-rw-r--r-- | indra/llui/llkeywords.h | 29 | ||||
-rw-r--r-- | indra/llui/llmenugl.cpp | 40 | ||||
-rw-r--r-- | indra/llui/llmenugl.h | 10 | ||||
-rw-r--r-- | indra/llui/llresizehandle.cpp | 86 | ||||
-rw-r--r-- | indra/llui/lltextbase.cpp | 40 | ||||
-rw-r--r-- | indra/llui/lltextbase.h | 8 | ||||
-rw-r--r-- | indra/newview/app_settings/settings.xml | 13 | ||||
-rw-r--r-- | indra/newview/llagentwearables.cpp | 1 | ||||
-rw-r--r-- | indra/newview/llbottomtray.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llfloaterpreference.cpp | 26 | ||||
-rw-r--r-- | indra/newview/llpanelnearbymedia.cpp | 31 | ||||
-rw-r--r-- | indra/newview/llpanelnearbymedia.h | 10 | ||||
-rw-r--r-- | indra/newview/lltexlayer.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llvieweraudio.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llviewermedia.cpp | 3 | ||||
-rw-r--r-- | indra/newview/llvoiceclient.cpp | 15 |
21 files changed, 350 insertions, 147 deletions
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 22fad792da..a86bbbffff 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -270,6 +270,14 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const return (F32)mFontBitmapCachep->getMaxCharWidth(); } +F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const +{ + if (mFTFace == NULL) + return 0.0; + + return glyph->mXAdvance; +} + F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const { if (mFTFace == NULL) @@ -289,6 +297,21 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const return delta.x*(1.f/64.f); } +F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const +{ + if (mFTFace == NULL) + return 0.0; + + U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0; + U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0; + + FT_Vector delta; + + llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta)); + + return delta.x*(1.f/64.f); +} + BOOL LLFontFreetype::hasGlyph(llwchar wch) const { llassert(!mIsFallback); diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index 7a5d029038..f60d09316d 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -128,7 +128,9 @@ public: }; F32 getXAdvance(llwchar wc) const; + F32 getXAdvance(const LLFontGlyphInfo* glyph) const; F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters + F32 getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const; // Get the kerning between the two characters LLFontGlyphInfo* getGlyphInfo(llwchar wch) const; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index b6a6b448ee..f1f86fd638 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -249,11 +249,18 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons // Remember last-used texture to avoid unnecesssary bind calls. LLImageGL *last_bound_texture = NULL; + const LLFontGlyphInfo* next_glyph = NULL; + for (i = begin_offset; i < begin_offset + length; i++) { llwchar wch = wstr[i]; - const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch); + const LLFontGlyphInfo* fgi = next_glyph; + next_glyph = NULL; + if(!fgi) + { + fgi = mFontFreetype->getGlyphInfo(wch); + } if (!fgi) { llerrs << "Missing Glyph Info" << llendl; @@ -295,7 +302,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if (next_char && (next_char < LAST_CHARACTER)) { // Kern this puppy. - cur_x += mFontFreetype->getXKerning(wch, next_char); + next_glyph = mFontFreetype->getGlyphInfo(next_char); + cur_x += mFontFreetype->getXKerning(fgi, next_glyph); } // Round after kerning. @@ -435,14 +443,21 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars F32 cur_x = 0; const S32 max_index = begin_offset + max_chars; + const LLFontGlyphInfo* next_glyph = NULL; + F32 width_padding = 0.f; for (S32 i = begin_offset; i < max_index && wchars[i] != 0; i++) { llwchar wch = wchars[i]; - const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch); + const LLFontGlyphInfo* fgi = next_glyph; + next_glyph = NULL; + if(!fgi) + { + fgi = mFontFreetype->getGlyphInfo(wch); + } - F32 advance = mFontFreetype->getXAdvance(wch); + F32 advance = mFontFreetype->getXAdvance(fgi); // for the last character we want to measure the greater of its width and xadvance values // so keep track of the difference between these values for the each character we measure @@ -459,7 +474,8 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars && (next_char < LAST_CHARACTER)) { // Kern this puppy. - cur_x += mFontFreetype->getXKerning(wch, next_char); + next_glyph = mFontFreetype->getGlyphInfo(next_char); + cur_x += mFontFreetype->getXKerning(fgi, next_glyph); } // Round after kerning. cur_x = (F32)llround(cur_x); @@ -492,6 +508,8 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch // avoid S32 overflow when max_pixels == S32_MAX by staying in floating point F32 scaled_max_pixels = ceil(max_pixels * sScaleX); F32 width_padding = 0.f; + + LLFontGlyphInfo* next_glyph = NULL; S32 i; for (i=0; (i < max_chars); i++) @@ -534,8 +552,13 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch in_word = TRUE; } } - - LLFontGlyphInfo* fgi = mFontFreetype->getGlyphInfo(wch); + + LLFontGlyphInfo* fgi = next_glyph; + next_glyph = NULL; + if(!fgi) + { + fgi = mFontFreetype->getGlyphInfo(wch); + } // account for glyphs that run beyond the starting point for the next glyphs width_padding = llmax( 0.f, // always use positive padding amount @@ -554,7 +577,8 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch if (((i+1) < max_chars) && wchars[i+1]) { // Kern this puppy. - cur_x += mFontFreetype->getXKerning(wch, wchars[i+1]); + next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1]); + cur_x += mFontFreetype->getXKerning(fgi, next_glyph); } // Round after kerning. @@ -660,6 +684,8 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t const S32 max_index = begin_offset + llmin(S32_MAX - begin_offset, max_chars); F32 scaled_max_pixels = max_pixels * sScaleX; + + const LLFontGlyphInfo* next_glyph = NULL; S32 pos; for (pos = begin_offset; pos < max_index; pos++) @@ -669,7 +695,15 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t { break; // done } - F32 char_width = mFontFreetype->getXAdvance(wch); + + const LLFontGlyphInfo* glyph = next_glyph; + next_glyph = NULL; + if(!glyph) + { + glyph = mFontFreetype->getGlyphInfo(wch); + } + + F32 char_width = mFontFreetype->getXAdvance(glyph); if (round) { @@ -695,11 +729,12 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t if (((pos + 1) < max_index) && (wchars[(pos + 1)])) { - llwchar next_char = wchars[pos + 1]; // Kern this puppy. - cur_x += mFontFreetype->getXKerning(wch, next_char); + next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1]); + cur_x += mFontFreetype->getXKerning(glyph, next_glyph); } + // Round after kerning. cur_x = llround(cur_x); } diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index a55915af35..f3cd112b9a 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2376,10 +2376,17 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out LLRect new_rect; new_rect.setLeftTopAndSize(view_rect.mLeft,view_rect.mTop,new_width, new_height); - floater->reshape( new_width, new_height, TRUE ); - floater->setRect(new_rect); + floater->setShape(new_rect); - floater->translateIntoRect( getLocalRect(), false ); + if (floater->followsRight()) + { + floater->translate(old_width - new_width, 0); + } + + if (floater->followsTop()) + { + floater->translate(0, old_height - new_height); + } } } diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index ede32084d0..75342afbe2 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -218,6 +218,86 @@ void LLKeywords::addToken(LLKeywordToken::TOKEN_TYPE type, llassert(0); } } +LLKeywords::WStringMapIndex::WStringMapIndex(const WStringMapIndex& other) +{ + if(other.mOwner) + { + copyData(other.mData, other.mLength); + } + else + { + mOwner = false; + mLength = other.mLength; + mData = other.mData; + } +} + +LLKeywords::WStringMapIndex::WStringMapIndex(const LLWString& str) +{ + copyData(str.data(), str.size()); +} + +LLKeywords::WStringMapIndex::WStringMapIndex(const llwchar *start, size_t length): +mData(start), mLength(length), mOwner(false) +{ +} + +LLKeywords::WStringMapIndex::~WStringMapIndex() +{ + if(mOwner) + delete[] mData; +} + +void LLKeywords::WStringMapIndex::copyData(const llwchar *start, size_t length) +{ + llwchar *data = new llwchar[length]; + memcpy((void*)data, (const void*)start, length * sizeof(llwchar)); + + mOwner = true; + mLength = length; + mData = data; +} + +bool LLKeywords::WStringMapIndex::operator<(const LLKeywords::WStringMapIndex &other) const +{ + // NOTE: Since this is only used to organize a std::map, it doesn't matter if it uses correct collate order or not. + // The comparison only needs to strictly order all possible strings, and be stable. + + bool result = false; + const llwchar* self_iter = mData; + const llwchar* self_end = mData + mLength; + const llwchar* other_iter = other.mData; + const llwchar* other_end = other.mData + other.mLength; + + while(true) + { + if(other_iter >= other_end) + { + // We've hit the end of other. + // This covers two cases: other being shorter than self, or the strings being equal. + // In either case, we want to return false. + result = false; + break; + } + else if(self_iter >= self_end) + { + // self is shorter than other. + result = true; + break; + } + else if(*self_iter != *other_iter) + { + // The current character differs. The strings are not equal. + result = *self_iter < *other_iter; + break; + } + + self_iter++; + other_iter++; + } + + return result; +} LLColor3 LLKeywords::readColor( const std::string& s ) { @@ -429,7 +509,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW S32 seg_len = p - cur; if( seg_len > 0 ) { - LLWString word( cur, 0, seg_len ); + WStringMapIndex word( cur, seg_len ); word_token_map_t::iterator map_iter = mWordTokenMap.find(word); if( map_iter != mWordTokenMap.end() ) { diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h index 53377869ca..e5b66dfa56 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -92,8 +92,33 @@ public: const std::string& key, const LLColor3& color, const std::string& tool_tip = LLStringUtil::null); - - typedef std::map<LLWString, LLKeywordToken*> word_token_map_t; + + // This class is here as a performance optimization. + // The word token map used to be defined as std::map<LLWString, LLKeywordToken*>. + // This worked, but caused a performance bottleneck due to memory allocation and string copies + // because it's not possible to search such a map without creating an LLWString. + // Using this class as the map index instead allows us to search using segments of an existing + // text run without copying them first, which greatly reduces overhead in LLKeywords::findSegments(). + class WStringMapIndex + { + public: + // copy constructor + WStringMapIndex(const WStringMapIndex& other); + // constructor from a string (copies the string's data into the new object) + WStringMapIndex(const LLWString& str); + // constructor from pointer and length + // NOTE: does NOT copy data, caller must ensure that the lifetime of the pointer exceeds that of the new object! + WStringMapIndex(const llwchar *start, size_t length); + ~WStringMapIndex(); + bool operator<(const WStringMapIndex &other) const; + private: + void copyData(const llwchar *start, size_t length); + const llwchar *mData; + size_t mLength; + bool mOwner; + }; + + typedef std::map<WStringMapIndex, LLKeywordToken*> word_token_map_t; typedef word_token_map_t::const_iterator keyword_iterator_t; keyword_iterator_t begin() const { return mWordTokenMap.begin(); } keyword_iterator_t end() const { return mWordTokenMap.end(); } diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index d18abbfb2f..0d56c5ed31 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -657,11 +657,38 @@ LLMenuItemVerticalSeparatorGL::LLMenuItemVerticalSeparatorGL( void ) // Class LLMenuItemTearOffGL //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LLMenuItemTearOffGL::LLMenuItemTearOffGL(const LLMenuItemTearOffGL::Params& p) -: LLMenuItemGL(p), - mParentHandle(p.parent_floater_handle) +: LLMenuItemGL(p) { } +// Returns the first floater ancestor if there is one +LLFloater* LLMenuItemTearOffGL::getParentFloater() +{ + LLView* parent_view = getMenu(); + + while (parent_view) + { + if (dynamic_cast<LLFloater*>(parent_view)) + { + return dynamic_cast<LLFloater*>(parent_view); + } + + bool parent_is_menu = dynamic_cast<LLMenuGL*>(parent_view) && !dynamic_cast<LLMenuBarGL*>(parent_view); + + if (parent_is_menu) + { + // use menu parent + parent_view = dynamic_cast<LLMenuGL*>(parent_view)->getParentMenuItem(); + } + else + { + // just use regular view parent + parent_view = parent_view->getParent(); + } + } + + return NULL; +} void LLMenuItemTearOffGL::onCommit() { @@ -680,7 +707,7 @@ void LLMenuItemTearOffGL::onCommit() getMenu()->needsArrange(); - LLFloater* parent_floater = mParentHandle.get(); + LLFloater* parent_floater = getParentFloater(); LLFloater* tear_off_menu = LLTearOffMenu::create(getMenu()); if (tear_off_menu) @@ -1671,7 +1698,6 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p) mSpilloverMenu(NULL), mJumpKey(p.jump_key), mCreateJumpKeys(p.create_jump_keys), - mParentFloaterHandle(p.parent_floater), mNeedsArrange(FALSE), mShortcutPad(p.shortcut_pad) { @@ -1699,7 +1725,7 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p) void LLMenuGL::initFromParams(const LLMenuGL::Params& p) { LLUICtrl::initFromParams(p); - setCanTearOff(p.can_tear_off, p.parent_floater); + setCanTearOff(p.can_tear_off); } // Destroys the object @@ -1711,12 +1737,11 @@ LLMenuGL::~LLMenuGL( void ) mJumpKeys.clear(); } -void LLMenuGL::setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_handle ) +void LLMenuGL::setCanTearOff(BOOL tear_off) { if (tear_off && mTearOffItem == NULL) { LLMenuItemTearOffGL::Params p; - p.parent_floater_handle = parent_floater_handle; mTearOffItem = LLUICtrlFactory::create<LLMenuItemTearOffGL>(p); addChildInBack(mTearOffItem); } @@ -2233,7 +2258,6 @@ void LLMenuGL::createSpilloverBranch() LLMenuGL::Params p; p.name("More"); p.label("More"); // *TODO: Translate - p.parent_floater(mParentFloaterHandle); p.bg_color(mBackgroundColor); p.bg_visible(true); p.can_tear_off(false); diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 8441aaadd4..39d1986461 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -355,7 +355,6 @@ class LLMenuGL public: struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> { - Optional<LLHandle<LLFloater> > parent_floater; Optional<KEY> jump_key; Optional<bool> horizontal_layout, can_tear_off, @@ -430,7 +429,7 @@ public: void setBackgroundColor( const LLUIColor& color ) { mBackgroundColor = color; } const LLUIColor& getBackgroundColor() const { return mBackgroundColor; } void setBackgroundVisible( BOOL b ) { mBgVisible = b; } - void setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_handle = LLHandle<LLFloater>()); + void setCanTearOff(BOOL tear_off); // add a separator to this menu virtual BOOL addSeparator(); @@ -553,7 +552,6 @@ private: class LLMenuItemTearOffGL* mTearOffItem; class LLMenuItemBranchGL* mSpilloverBranch; LLMenuGL* mSpilloverMenu; - LLHandle<LLFloater> mParentFloaterHandle; KEY mJumpKey; BOOL mCreateJumpKeys; S32 mShortcutPad; @@ -814,7 +812,6 @@ class LLMenuItemTearOffGL : public LLMenuItemGL public: struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params> { - Optional<LLHandle<LLFloater> > parent_floater_handle; Params() { name = "tear off"; @@ -823,13 +820,12 @@ public: }; LLMenuItemTearOffGL( const Params& ); - + virtual void onCommit(void); virtual void draw(void); virtual U32 getNominalHeight() const; -private: - LLHandle<LLFloater> mParentHandle; + LLFloater* getParentFloater(); }; diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp index 3df09d124a..00214d451c 100644 --- a/indra/llui/llresizehandle.cpp +++ b/indra/llui/llresizehandle.cpp @@ -124,7 +124,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask) { // Make sure the mouse in still over the application. We don't want to make the parent // so big that we can't see the resize handle any more. - + S32 screen_x; S32 screen_y; localPointToScreen(x, y, &screen_x, &screen_y); @@ -136,9 +136,10 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask) if( resizing_view ) { // undock floater when user resize it - if (((LLFloater*)getParent())->isDocked()) + LLFloater* floater_parent = dynamic_cast<LLFloater*>(getParent()); + if (floater_parent && floater_parent->isDocked()) { - ((LLFloater*)getParent())->setDocked(false, false); + floater_parent->setDocked(false, false); } // Resize the parent @@ -146,61 +147,68 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask) LLRect scaled_rect = orig_rect; S32 delta_x = screen_x - mDragLastScreenX; S32 delta_y = screen_y - mDragLastScreenY; - - if(delta_x == 0 && delta_y == 0) - return FALSE; - LLCoordGL mouse_dir; // use hysteresis on mouse motion to preserve user intent when mouse stops moving mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX; mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY; - mLastMouseScreenX = screen_x; mLastMouseScreenY = screen_y; mLastMouseDir = mouse_dir; - S32 new_width = orig_rect.getWidth(); - S32 new_height = orig_rect.getHeight(); + S32 x_multiple = 1; + S32 y_multiple = 1; + switch( mCorner ) + { + case LEFT_TOP: + x_multiple = -1; + y_multiple = 1; + break; + case LEFT_BOTTOM: + x_multiple = -1; + y_multiple = -1; + break; + case RIGHT_TOP: + x_multiple = 1; + y_multiple = 1; + break; + case RIGHT_BOTTOM: + x_multiple = 1; + y_multiple = -1; + break; + } - S32 new_pos_x = orig_rect.mLeft; - S32 new_pos_y = orig_rect.mTop; + S32 new_width = orig_rect.getWidth() + x_multiple * delta_x; + if( new_width < mMinWidth ) + { + new_width = mMinWidth; + delta_x = x_multiple * (mMinWidth - orig_rect.getWidth()); + } + + S32 new_height = orig_rect.getHeight() + y_multiple * delta_y; + if( new_height < mMinHeight ) + { + new_height = mMinHeight; + delta_y = y_multiple * (mMinHeight - orig_rect.getHeight()); + } switch( mCorner ) { - case LEFT_TOP: - new_width-=delta_x; - new_height+=delta_y; - new_pos_x+=delta_x; - new_pos_y+=delta_y; + case LEFT_TOP: + scaled_rect.translate(delta_x, 0); break; case LEFT_BOTTOM: - new_width-=delta_x; - new_height-=delta_y; - new_pos_x+=delta_x; + scaled_rect.translate(delta_x, delta_y); break; case RIGHT_TOP: - new_width+=delta_x; - new_height+=delta_y; - new_pos_y+=delta_y; break; case RIGHT_BOTTOM: - new_width+=delta_x; - new_height-=delta_y; + scaled_rect.translate(0, delta_y); break; } - new_width = llmax(new_width,mMinWidth); - new_height = llmax(new_height,mMinHeight); - - LLRect::tCoordType screen_width = resizing_view->getParent()->getSnapRect().getWidth(); - LLRect::tCoordType screen_height = resizing_view->getParent()->getSnapRect().getHeight(); - - new_width = llmin(new_width, screen_width); - new_height = llmin(new_height, screen_height); - // temporarily set new parent rect - scaled_rect.setLeftTopAndSize(new_pos_x,new_pos_y,new_width,new_height); - + scaled_rect.mRight = scaled_rect.mLeft + new_width; + scaled_rect.mTop = scaled_rect.mBottom + new_height; resizing_view->setRect(scaled_rect); LLView* snap_view = NULL; @@ -251,11 +259,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask) resizing_view->setRect(orig_rect); // translate and scale to new shape - resizing_view->reshape(scaled_rect.getWidth(),scaled_rect.getHeight()); - resizing_view->setRect(scaled_rect); - //set shape to handle dependent floaters... - resizing_view->handleReshape(scaled_rect, false); - + resizing_view->setShape(scaled_rect, true); // update last valid mouse cursor position based on resized view's actual size LLRect new_rect = resizing_view->getRect(); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index b84e6f45fb..851fb966ec 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1445,10 +1445,10 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i } // Finds the text segment (if any) at the give local screen position -LLTextSegmentPtr LLTextBase::getSegmentAtLocalPos( S32 x, S32 y ) +LLTextSegmentPtr LLTextBase::getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line) { // Find the cursor position at the requested local screen position - S32 offset = getDocIndexFromLocalCoord( x, y, FALSE ); + S32 offset = getDocIndexFromLocalCoord( x, y, FALSE, hit_past_end_of_line); segment_set_t::iterator seg_iter = getSegIterContaining(offset); if (seg_iter != mSegments.end()) { @@ -1788,7 +1788,7 @@ const LLWString& LLTextBase::getWText() const // will be put to its right. If round is false, the cursor will always be put to the // character's left. -S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const +S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line) const { // Figure out which line we're nearest to. LLRect visible_region = getVisibleDocumentRect(); @@ -1817,7 +1817,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round S32 text_width, text_height; segmentp->getDimensions(line_seg_offset, segment_line_length, text_width, text_height); if (local_x < start_x + text_width // cursor to left of right edge of text - || segmentp->getEnd() >= line_iter->mDocIndexEnd - 1) // or this segment wraps to next line + || (hit_past_end_of_line && (segmentp->getEnd() >= line_iter->mDocIndexEnd - 1))) // or this segment wraps to next line { // Figure out which character we're nearest to. S32 offset; @@ -2402,8 +2402,12 @@ BOOL LLNormalTextSegment::handleHover(S32 x, S32 y, MASK mask) { if (getStyle() && getStyle()->isLink()) { - LLUI::getWindow()->setCursor(UI_CURSOR_HAND); - return TRUE; + // Only process the click if it's actually in this segment, not to the right of the end-of-line. + if(mEditor.getSegmentAtLocalPos(x, y, false) == this) + { + LLUI::getWindow()->setCursor(UI_CURSOR_HAND); + return TRUE; + } } return FALSE; } @@ -2412,8 +2416,12 @@ BOOL LLNormalTextSegment::handleRightMouseDown(S32 x, S32 y, MASK mask) { if (getStyle() && getStyle()->isLink()) { - mEditor.createUrlContextMenu(x, y, getStyle()->getLinkHREF()); - return TRUE; + // Only process the click if it's actually in this segment, not to the right of the end-of-line. + if(mEditor.getSegmentAtLocalPos(x, y, false) == this) + { + mEditor.createUrlContextMenu(x, y, getStyle()->getLinkHREF()); + return TRUE; + } } return FALSE; } @@ -2422,8 +2430,12 @@ BOOL LLNormalTextSegment::handleMouseDown(S32 x, S32 y, MASK mask) { if (getStyle() && getStyle()->isLink()) { - // eat mouse down event on hyperlinks, so we get the mouse up - return TRUE; + // Only process the click if it's actually in this segment, not to the right of the end-of-line. + if(mEditor.getSegmentAtLocalPos(x, y, false) == this) + { + // eat mouse down event on hyperlinks, so we get the mouse up + return TRUE; + } } return FALSE; @@ -2433,8 +2445,12 @@ BOOL LLNormalTextSegment::handleMouseUp(S32 x, S32 y, MASK mask) { if (getStyle() && getStyle()->isLink()) { - LLUrlAction::clickAction(getStyle()->getLinkHREF()); - return TRUE; + // Only process the click if it's actually in this segment, not to the right of the end-of-line. + if(mEditor.getSegmentAtLocalPos(x, y, false) == this) + { + LLUrlAction::clickAction(getStyle()->getLinkHREF()); + return TRUE; + } } return FALSE; diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 3dda6f4cc8..5b24c63557 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -48,6 +48,7 @@ class LLContextMenu; class LLTextSegment; +class LLNormalTextSegment; typedef LLPointer<LLTextSegment> LLTextSegmentPtr; @@ -61,6 +62,9 @@ class LLTextBase protected LLEditMenuHandler { public: + friend class LLTextSegment; + friend class LLNormalTextSegment; + struct LineSpacingParams : public LLInitParam::Choice<LineSpacingParams> { Alternative<F32> multiple; @@ -165,7 +169,7 @@ public: S32 getVPad() { return mVPad; } S32 getHPad() { return mHPad; } - S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const; + S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line = true) const; LLRect getLocalRectFromDocIndex(S32 pos) const; LLRect getDocRectFromDocIndex(S32 pos) const; @@ -275,7 +279,7 @@ protected: // manage segments void getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const; void getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp ); - LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y ); + LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line = true); segment_set_t::iterator getSegIterContaining(S32 index); segment_set_t::const_iterator getSegIterContaining(S32 index) const; void clearSegments(); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 8beff26654..f58f4ac594 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4598,7 +4598,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>MediaShowWithinParcel</key> <map> @@ -10393,17 +10393,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>VoiceDefaultInternalLevel</key> - <map> - <key>Comment</key> - <string>Internal level of voice set by default. Is equivalent to 0.5 (from 0.0-1.0 range) external voice level (internal = 400 * external^2).</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>100</integer> - </map> <key>VoiceEarLocation</key> <map> <key>Comment</key> diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 68ee9cd612..f4bc35002b 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1673,6 +1673,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it if (mAvatarObject) { mAvatarObject->updateVisualParams(); + mAvatarObject->invalidateAll(); } // Start rendering & update the server diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 95a946cee8..459a61dec3 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -350,7 +350,7 @@ void LLBottomTray::setVisible(BOOL visible) { mBottomTrayLite->setVisible(visible); } - else + else { LLPanel::setVisible(visible); } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index f20ef76bed..c6719a3092 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -321,9 +321,6 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.VertexShaderEnable", boost::bind(&LLFloaterPreference::onVertexShaderEnable, this)); mCommitCallbackRegistrar.add("Pref.WindowedMod", boost::bind(&LLFloaterPreference::onCommitWindowedMode, this)); mCommitCallbackRegistrar.add("Pref.UpdateSliderText", boost::bind(&LLFloaterPreference::onUpdateSliderText,this, _1,_2)); - mCommitCallbackRegistrar.add("Pref.ParcelMediaAutoPlayEnable", boost::bind(&LLFloaterPreference::onCommitParcelMediaAutoPlayEnable, this)); - mCommitCallbackRegistrar.add("Pref.MediaEnabled", boost::bind(&LLFloaterPreference::onCommitMediaEnabled, this)); - mCommitCallbackRegistrar.add("Pref.MusicEnabled", boost::bind(&LLFloaterPreference::onCommitMusicEnabled, this)); mCommitCallbackRegistrar.add("Pref.QualityPerformance", boost::bind(&LLFloaterPreference::onChangeQuality, this, _2)); mCommitCallbackRegistrar.add("Pref.applyUIColor", boost::bind(&LLFloaterPreference::applyUIColor, this ,_1, _2)); mCommitCallbackRegistrar.add("Pref.getUIColor", boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2)); @@ -957,29 +954,6 @@ void LLFloaterPreference::disableUnavailableSettings() } } -void LLFloaterPreference::onCommitParcelMediaAutoPlayEnable() -{ - BOOL autoplay = getChild<LLCheckBoxCtrl>("autoplay_enabled")->get(); - - gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, autoplay); - - lldebugs << "autoplay now = " << int(autoplay) << llendl; -} - -void LLFloaterPreference::onCommitMediaEnabled() -{ - LLCheckBoxCtrl *media_enabled_ctrl = getChild<LLCheckBoxCtrl>("media_enabled"); - bool enabled = media_enabled_ctrl->get(); - gSavedSettings.setBOOL("AudioStreamingMedia", enabled); -} - -void LLFloaterPreference::onCommitMusicEnabled() -{ - LLCheckBoxCtrl *music_enabled_ctrl = getChild<LLCheckBoxCtrl>("music_enabled"); - bool enabled = music_enabled_ctrl->get(); - gSavedSettings.setBOOL("AudioStreamingMusic", enabled); -} - void LLFloaterPreference::refresh() { LLPanel::refresh(); diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index 6a88c916d7..8ad5389566 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -38,6 +38,7 @@ #include "llcheckboxctrl.h" #include "llcombobox.h" #include "llresizebar.h" +#include "llresizehandle.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" #include "llscrolllistcell.h" @@ -116,6 +117,20 @@ BOOL LLPanelNearByMedia::postBuild() p.resizing_view = this; addChild( LLUICtrlFactory::create<LLResizeBar>(p) ); + p.rect = LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0); + p.name = "resizebar_left"; + p.min_size = getRect().getWidth(); + p.side = LLResizeBar::LEFT; + addChild( LLUICtrlFactory::create<LLResizeBar>(p) ); + + LLResizeHandle::Params resize_handle_p; + resize_handle_p.rect = LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ); + resize_handle_p.mouse_opaque(false); + resize_handle_p.min_width(getRect().getWidth()); + resize_handle_p.min_height(getRect().getHeight()); + resize_handle_p.corner(LLResizeHandle::LEFT_BOTTOM); + addChild(LLUICtrlFactory::create<LLResizeHandle>(resize_handle_p)); + mNearbyMediaPanel = getChild<LLUICtrl>("nearby_media_panel"); mMediaList = getChild<LLScrollListCtrl>("media_list"); mEnableAllCtrl = getChild<LLUICtrl>("all_nearby_media_enable_btn"); @@ -148,8 +163,10 @@ BOOL LLPanelNearByMedia::postBuild() updateColumns(); LLView* minimized_controls = getChildView("minimized_controls"); - mMoreHeight = getRect().getHeight(); - mLessHeight = getRect().getHeight() - minimized_controls->getRect().mBottom; + mMoreRect = getRect(); + mLessRect = getRect(); + mLessRect.mBottom = minimized_controls->getRect().mBottom; + getChild<LLUICtrl>("more_less_btn")->setValue(false); onMoreLess(); @@ -207,7 +224,7 @@ void LLPanelNearByMedia::reshape(S32 width, S32 height, BOOL called_from_parent) LLButton* more_less_btn = getChild<LLButton>("more_less_btn"); if (more_less_btn->getValue().asBoolean()) { - mMoreHeight = getRect().getHeight(); + mMoreRect = getRect(); } } @@ -614,6 +631,8 @@ void LLPanelNearByMedia::refreshList() // Clear all items so the list gets regenerated. mMediaList->deleteAllItems(); + mParcelAudioItem = NULL; + mParcelMediaItem = NULL; all_items_deleted = true; updateColumns(); @@ -926,10 +945,8 @@ void LLPanelNearByMedia::onMoreLess() // enable resizing when expanded getChildView("resizebar_bottom")->setEnabled(is_more); - S32 new_height = is_more ? mMoreHeight : mLessHeight; - - LLRect new_rect = getRect(); - new_rect.mBottom = new_rect.mTop - new_height; + LLRect new_rect = is_more ? mMoreRect : mLessRect; + new_rect.translate(getRect().mRight - new_rect.mRight, getRect().mTop - new_rect.mTop); setShape(new_rect); } diff --git a/indra/newview/llpanelnearbymedia.h b/indra/newview/llpanelnearbymedia.h index eedfd447de..6fe724266b 100644 --- a/indra/newview/llpanelnearbymedia.h +++ b/indra/newview/llpanelnearbymedia.h @@ -174,11 +174,11 @@ private: std::string mParcelMediaName; std::string mParcelAudioName; - S32 mMoreHeight; - S32 mLessHeight; - LLFrameTimer mHoverTimer; - LLScrollListItem* mParcelMediaItem; - LLScrollListItem* mParcelAudioItem; + LLRect mMoreRect; + LLRect mLessRect; + LLFrameTimer mHoverTimer; + LLScrollListItem* mParcelMediaItem; + LLScrollListItem* mParcelAudioItem; }; diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index ddb6405c41..662e6dcabe 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -167,8 +167,8 @@ void LLTexLayerSetBuffer::popProjection() const BOOL LLTexLayerSetBuffer::needsRender() { const LLVOAvatarSelf* avatar = mTexLayerSet->getAvatar(); - BOOL upload_now = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal(); - BOOL needs_update = gAgentQueryManager.hasNoPendingQueries() && (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating; + BOOL upload_now = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal() && gAgentQueryManager.hasNoPendingQueries(); + BOOL needs_update = (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating; if (needs_update) { BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT); diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index 934981b0ad..1d935f5ab8 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -251,7 +251,7 @@ void audio_update_wind(bool force_update) { // initialize wind volume (force_update) by using large volume_delta // which is sufficient to completely turn off or turn on wind noise - volume_delta = max_wind_volume; + volume_delta = 1.f; } // mute wind when not flying diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 642f672faf..395467dffb 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1318,6 +1318,9 @@ void LLViewerMediaImpl::loadURI() { if(mMediaSource) { + // trim whitespace from front and back of URL - fixes EXT-5363 + LLStringUtil::trim( mMediaURL ); + // *HACK: we don't know if the URI coming in is properly escaped // (the contract doesn't specify whether it is escaped or not. // but LLQtWebKit expects it to be, so we do our best to encode diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 3d153db733..59606f17b2 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -1115,10 +1115,9 @@ public: * Gets stored external (vivox) volume level for specified speaker and * transforms it into internal (viewer) level. * - * If specified user is not found default level will be returned. It is equivalent of - * external level 0.5 from the 0.0..1.0 range. + * If specified user is not found -1 will be returned. * Internal level is calculated as: internal = 400 * external^2 - * Maps 0.0 to 1.0 to internal values 0-400 with default 0.5 == 100 + * Maps 0.0 to 1.0 to internal values 0-400 * * @param[in] speaker_id - LLUUID of user to get his volume level */ @@ -1157,9 +1156,8 @@ void LLSpeakerVolumeStorage::storeSpeakerVolume(const LLUUID& speaker_id, F32 vo S32 LLSpeakerVolumeStorage::getSpeakerVolume(const LLUUID& speaker_id) { - // default internal level of user voice. - const static LLUICachedControl<S32> DEFAULT_INTERNAL_VOLUME_LEVEL("VoiceDefaultInternalLevel", 100); - S32 ret_val = DEFAULT_INTERNAL_VOLUME_LEVEL; + // Return value of -1 indicates no level is stored for this speaker + S32 ret_val = -1; speaker_data_map_t::const_iterator it = mSpeakersData.find(speaker_id); if (it != mSpeakersData.end()) @@ -5045,6 +5043,11 @@ LLVoiceClient::participantState *LLVoiceClient::sessionState::addParticipant(con mParticipantsByUUID.insert(participantUUIDMap::value_type(&(result->mAvatarID), result)); result->mUserVolume = LLSpeakerVolumeStorage::getInstance()->getSpeakerVolume(result->mAvatarID); + if (result->mUserVolume != -1) + { + result->mVolumeDirty = true; + mVolumeDirty = true; + } LL_DEBUGS("Voice") << "participant \"" << result->mURI << "\" added." << LL_ENDL; } |