From 418308bc7ce4e9924d6280f784222ba45172eea4 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 6 Nov 2019 12:34:26 +0100 Subject: Characters can have more than one representation in LLFontFreetype * By default all viewer text will use B/W glyphs * Added temporary use_color attribute to LLTextBase for testing --- indra/llui/llfolderviewitem.cpp | 6 +++--- indra/llui/lltextbase.cpp | 11 ++++++++--- indra/llui/lltextbase.h | 3 +++ indra/llui/llview.cpp | 2 +- 4 files changed, 15 insertions(+), 7 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 0510e472c5..0c1c3c40ec 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -826,7 +826,7 @@ void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y // font->renderUTF8(mLabel, 0, x, y, color, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, getRect().getWidth() - (S32) x - mLabelPaddingRight, &right_x, TRUE); + S32_MAX, getRect().getWidth() - (S32) x - mLabelPaddingRight, &right_x, /*use_ellipses*/TRUE, /*use_color*/FALSE); } void LLFolderViewItem::draw() @@ -905,7 +905,7 @@ void LLFolderViewItem::draw() { font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE ); + S32_MAX, S32_MAX, &right_x, /*use_ellipses*/FALSE, /*use_color*/FALSE ); } //--------------------------------------------------------------------------------// @@ -917,7 +917,7 @@ void LLFolderViewItem::draw() F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; font->renderUTF8( combined_string, mViewModelItem->getFilterStringOffset(), match_string_left, yy, sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - filter_string_length, S32_MAX, &right_x, FALSE ); + filter_string_length, S32_MAX, &right_x, /*use_ellipses*/FALSE, /*use_color*/FALSE ); } //Gilbert Linden 9-20-2012: Although this should be legal, removing it because it causes the mLabelSuffix rendering to diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index a23741b6dd..64b3a0ddcc 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -163,6 +163,7 @@ LLTextBase::Params::Params() wrap("wrap"), trusted_content("trusted_content", true), use_ellipses("use_ellipses", false), + use_color("use_color", false), parse_urls("parse_urls", false), force_urls_external("force_urls_external", false), parse_highlights("parse_highlights", false) @@ -217,6 +218,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mPlainText ( p.plain_text ), mWordWrap(p.wrap), mUseEllipses( p.use_ellipses ), + mUseColor(p.use_color), mParseHTML(p.parse_urls), mForceUrlsExternal(p.force_urls_external), mParseHighlights(p.parse_highlights), @@ -3198,7 +3200,8 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele mStyle->getShadowType(), length, &right_x, - mEditor.getUseEllipses()); + mEditor.getUseEllipses(), + mEditor.getUseColor()); } rect.mLeft = right_x; @@ -3217,7 +3220,8 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele LLFontGL::NO_SHADOW, length, &right_x, - mEditor.getUseEllipses()); + mEditor.getUseEllipses(), + mEditor.getUseColor()); } rect.mLeft = right_x; if( selection_end < seg_end ) @@ -3234,7 +3238,8 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele mStyle->getShadowType(), length, &right_x, - mEditor.getUseEllipses()); + mEditor.getUseEllipses(), + mEditor.getUseColor()); } return right_x; } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 9831c35858..6f1e178e36 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -314,6 +314,7 @@ public: plain_text, wrap, use_ellipses, + use_color, parse_urls, force_urls_external, parse_highlights, @@ -389,6 +390,7 @@ public: // used by LLTextSegment layout code bool getWordWrap() { return mWordWrap; } bool getUseEllipses() { return mUseEllipses; } + bool getUseColor() { return mUseColor; } bool truncate(); // returns true of truncation occurred bool isContentTrusted() {return mTrustedContent;} @@ -681,6 +683,7 @@ protected: bool mParseHighlights; // highlight user-defined keywords bool mWordWrap; bool mUseEllipses; + bool mUseColor; bool mTrackEnd; // if true, keeps scroll position at end of document during resize bool mReadOnly; bool mBGVisible; // render background? diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 89ad8138d8..40537e6c4a 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1282,7 +1282,7 @@ void LLView::drawDebugRect() debug_rect.getWidth(), debug_rect.getHeight()); LLFontGL::getFontSansSerifSmall()->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color, LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, NULL, FALSE); + S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE); } } LLUI::popMatrix(); -- cgit v1.3 From b44ade68e6eea656dc0e31738f9603caffe4d659 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 7 Nov 2019 20:33:53 +0100 Subject: FIXED Calling LLTextBase::insertStringNoUndo() with more than one segment results in overlapping segment ranges Text is only inserted into the view model *after* the segments are added so if seg1_pos_start is the current EOF: -> 1st segment: getSegIterContaining(seg1_pos_start) returns the last segment and insertSegment() ends up properly adjusting its start/end position -> 2nd segment: getSegIterContaining(seg2_pos_start) returns mSegments.end() since its position is beyond the available and insertSegment() leaves the last 2 segments with overlapping ranges After the fix: -> if index runs past the end of all segments then mSegments.end() is returned (no change) -> if index is a position past the length of text but claimed by a segment then that segment is returned (change) -> if index specifies a position in the middle of the document unclaimed by any segment then the first segment after that position is returned (no change) (this does break the assertion that segment->mStart <= index <= segment->mEnd?) --- indra/llui/lltextbase.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 64b3a0ddcc..ecceb289f0 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1889,8 +1889,6 @@ LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index) text_len = mLabel.getWString().length(); } - if (index > text_len) { return mSegments.end(); } - // when there are no segments, we return the end iterator, which must be checked by caller if (mSegments.size() <= 1) { return mSegments.begin(); } @@ -1914,8 +1912,6 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i text_len = mLabel.getWString().length(); } - if (index > text_len) { return mSegments.end(); } - // when there are no segments, we return the end iterator, which must be checked by caller if (mSegments.size() <= 1) { return mSegments.begin(); } -- cgit v1.3 From d58b530e805e2b3c943b1ff446ac84a10c500b32 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 7 Nov 2019 20:48:20 +0100 Subject: Add text_valign to LLTextBase to specify the vertical alignment within a single document line The existing font_valign property is used as to position the entire document so it's impossible to top align a text editor with each line's text centered within that line's extents --- indra/llui/lltextbase.cpp | 10 ++++++---- indra/llui/lltextbase.h | 7 +++++-- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index ecceb289f0..cc44f46706 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -160,6 +160,7 @@ LLTextBase::Params::Params() line_spacing("line_spacing"), max_text_length("max_length", 255), font_shadow("font_shadow"), + text_valign("text_valign"), wrap("wrap"), trusted_content("trusted_content", true), use_ellipses("use_ellipses", false), @@ -205,6 +206,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mVPad(p.v_pad), mHAlign(p.font_halign), mVAlign(p.font_valign), + mTextVAlign(p.text_valign.isProvided() ? p.text_valign : p.font_valign), mLineSpacingMult(p.line_spacing.multiple), mLineSpacingPixels(p.line_spacing.pixels), mClip(p.clip), @@ -515,7 +517,7 @@ void LLTextBase::drawCursor() fontp = segmentp->getStyle()->getFont(); fontp->render(text, mCursorPos, cursor_rect, LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], alpha), - LLFontGL::LEFT, mVAlign, + LLFontGL::LEFT, mTextVAlign, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 1); @@ -3191,7 +3193,7 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele font->render(text, start, rect, color, - LLFontGL::LEFT, mEditor.mVAlign, + LLFontGL::LEFT, mEditor.mTextVAlign, LLFontGL::NORMAL, mStyle->getShadowType(), length, @@ -3211,7 +3213,7 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele font->render(text, start, rect, mStyle->getSelectedColor().get(), - LLFontGL::LEFT, mEditor.mVAlign, + LLFontGL::LEFT, mEditor.mTextVAlign, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, length, @@ -3229,7 +3231,7 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele font->render(text, start, rect, color, - LLFontGL::LEFT, mEditor.mVAlign, + LLFontGL::LEFT, mEditor.mTextVAlign, LLFontGL::NORMAL, mStyle->getShadowType(), length, diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 6f1e178e36..99c243a346 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -333,6 +333,8 @@ public: Optional font_shadow; + Optional text_valign; + Params(); }; @@ -673,8 +675,9 @@ protected: // configuration S32 mHPad; // padding on left of text S32 mVPad; // padding above text - LLFontGL::HAlign mHAlign; - LLFontGL::VAlign mVAlign; + LLFontGL::HAlign mHAlign; // horizontal alignment of the document in its entirety + LLFontGL::VAlign mVAlign; // vertical alignment of the document in its entirety + LLFontGL::VAlign mTextVAlign; // vertical alignment of a text segment within a single line of text F32 mLineSpacingMult; // multiple of line height used as space for a single line of text (e.g. 1.5 to get 50% padding) S32 mLineSpacingPixels; // padding between lines bool mBorderVisible; -- cgit v1.3 From bab70f6f152952ce755188d29bea1cfd8821a4be Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Mon, 29 Aug 2022 00:00:31 +0200 Subject: Review + resolve minor issues --- autobuild.xml | 8 ++++---- indra/llrender/llfontbitmapcache.cpp | 29 +++++++++++------------------ indra/llrender/llfontbitmapcache.h | 12 ++++++------ indra/llrender/llfontregistry.cpp | 4 ++-- indra/llui/lltextbase.cpp | 2 +- indra/newview/viewer_manifest.py | 2 +- 6 files changed, 25 insertions(+), 32 deletions(-) (limited to 'indra/llui') diff --git a/autobuild.xml b/autobuild.xml index ac7459ddca..babc7d73bc 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -958,9 +958,9 @@ archive hash - aa8be83cdfcd5cda0343ea72e7d662ca + f3e63d80bd80da03aa7f87f7bd7c5f8b url - freetype-2.10.1.0-windows64-72.tar.bz2 + freetype-2.10.1.0-windows64-222392239.tar.bz2 name windows64 @@ -1510,9 +1510,9 @@ archive hash - e8b20cea748b90ea18bb63dfba06e059 + 340980c10153446b678625ec7af047c2 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/491/1075/icu4c-4.8.1-windows64-500388.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55243/513658/icu4c-4.8.1-windows64-539138.tar.bz2 name windows64 diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp index 754adb14cb..2d65ec47c6 100644 --- a/indra/llrender/llfontbitmapcache.cpp +++ b/indra/llrender/llfontbitmapcache.cpp @@ -31,17 +31,7 @@ LLFontBitmapCache::LLFontBitmapCache() : LLTrace::MemTrackable("LLFontBitmapCache") - , mBitmapWidth(0) - , mBitmapHeight(0) - , mMaxCharWidth(0) - , mMaxCharHeight(0) { - // *TODO: simplify with initializer after VS2017 - for (U32 idx = 0, cnt = static_cast(EFontGlyphType::Count); idx < cnt; idx++) - { - mCurrentOffsetX[idx] = 1; - mCurrentOffsetY[idx] = 1; - } } LLFontBitmapCache::~LLFontBitmapCache() @@ -123,6 +113,9 @@ BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp // Attach corresponding GL texture. (*TODO: is this needed?) gGL.getTexUnit(0)->bind(image_gl); image_gl->setFilteringOption(LLTexUnit::TFO_POINT); // was setMipFilterNearest(TRUE, TRUE); + + claimMem(image_raw); + claimMem(image_gl); } else { @@ -145,29 +138,29 @@ void LLFontBitmapCache::destroyGL() { for (U32 idx = 0, cnt = static_cast(EFontGlyphType::Count); idx < cnt; idx++) { - for (std::vector >::iterator it = mImageGLVec[idx].begin(); it != mImageGLVec[idx].end(); ++it) + for (LLImageGL* image_gl : mImageGLVec[idx]) { - (*it)->destroyGLTexture(); + image_gl->destroyGLTexture(); } } } void LLFontBitmapCache::reset() { - for (U32 idx = 0, cnt = static_cast(EFontGlyphType::Count); idx < cnt; idx++) + for (U32 kitty = 0, cnt = static_cast(EFontGlyphType::Count); kitty < cnt; kitty++) { - for (std::vector >::iterator it = mImageRawVec[idx].begin(), end_it = mImageRawVec[idx].end(); it != end_it; ++it) + for (LLImageRaw* image_raw : mImageRawVec[kitty]) { - disclaimMem(**it); + disclaimMem(image_raw); } - mImageRawVec[idx].clear(); + mImageRawVec[kitty].clear(); } for (U32 idx = 0, cnt = static_cast(EFontGlyphType::Count); idx < cnt; idx++) { - for (std::vector >::iterator it = mImageGLVec[idx].begin(), end_it = mImageGLVec[idx].end(); it != end_it; ++it) + for (LLImageGL* image_gl : mImageGLVec[idx]) { - disclaimMem(**it); + disclaimMem(image_gl); } mImageGLVec[idx].clear(); mCurrentOffsetX[idx] = 1; diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h index 5d0094fd69..6b339e9afd 100644 --- a/indra/llrender/llfontbitmapcache.h +++ b/indra/llrender/llfontbitmapcache.h @@ -68,12 +68,12 @@ protected: static U32 getNumComponents(EFontGlyphType bitmap_type); private: - S32 mBitmapWidth; - S32 mBitmapHeight; - S32 mCurrentOffsetX[static_cast(EFontGlyphType::Count)]; - S32 mCurrentOffsetY[static_cast(EFontGlyphType::Count)]; - S32 mMaxCharWidth; - S32 mMaxCharHeight; + S32 mBitmapWidth = 0; + S32 mBitmapHeight = 0; + S32 mCurrentOffsetX[static_cast(EFontGlyphType::Count)] = { 1 }; + S32 mCurrentOffsetY[static_cast(EFontGlyphType::Count)] = { 1 }; + S32 mMaxCharWidth = 0; + S32 mMaxCharHeight = 0; std::vector> mImageRawVec[static_cast(EFontGlyphType::Count)]; std::vector> mImageGLVec[static_cast(EFontGlyphType::Count)]; }; diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index f2dc5771e9..1d7d930e6f 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -482,6 +482,8 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) font_search_paths.push_back(LLFontGL::getFontPathSystem()); #if LL_DARWIN font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY); + font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY + MACOSX_FONT_SUPPLEMENTAL); + font_search_paths.push_back(sys_path + MACOSX_FONT_SUPPLEMENTAL); #endif // The fontname string may contain multiple font file names separated by semicolons. @@ -491,8 +493,6 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) ++font_file_it) { LLFontGL *fontp = NULL; - font_paths.push_back(MACOSX_FONT_PATH_LIBRARY + MACOSX_FONT_SUPPLEMENTAL + *file_name_it); - font_paths.push_back(sys_path + MACOSX_FONT_SUPPLEMENTAL + *file_name_it); bool is_ft_collection = (std::find_if(font_collection_files.begin(), font_collection_files.end(), [&font_file_it](const LLFontFileInfo& ffi) { return font_file_it->FileName == ffi.FileName; }) != font_collection_files.end()); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 9005d70b2e..0447e7070c 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -208,7 +208,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mVPad(p.v_pad), mHAlign(p.font_halign), mVAlign(p.font_valign), - mTextVAlign(p.text_valign.isProvided() ? p.text_valign : p.font_valign), + mTextVAlign(p.text_valign.isProvided() ? p.text_valign.getValue() : p.font_valign.getValue()), mLineSpacingMult(p.line_spacing.multiple), mLineSpacingPixels(p.line_spacing.pixels), mClip(p.clip), diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 281777e492..85c9318b8a 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -140,7 +140,7 @@ class ViewerManifest(LLManifest): self.path("*.tga") # Include our fonts - with self.prefix(src="../packages/fonts"): + with self.prefix(src="../packages/fonts",src_dst="fonts"): self.path("*.ttf") self.path("*.txt") -- cgit v1.3 From 063fe5953ada75177c1668f8b805cd9b79724581 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 2 Nov 2022 14:25:27 +0100 Subject: Create a separate segment for emoji characters so that we can display them in a slightly larger font size than the surrounding text --- indra/llui/lltextbase.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++--- indra/llui/lltextbase.h | 12 ++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 0447e7070c..2a6e6901e4 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2302,6 +2302,36 @@ void LLTextBase::appendWidget(const LLInlineViewSegment::Params& params, const s insertStringNoUndo(getLength(), widget_wide_text, &segments); } +void LLTextBase::createTextWithEmojiSegment(const LLWString& text, S32 segment_start, LLStyleConstSP style, segment_vec_t& segments) +{ + LLStyleSP emoji_style; + + S32 text_start = 0, text_kitty = 0, text_len = text.size(); + for (; text_kitty < text_len; text_kitty++) + { + if (LLStringOps::isEmoji(text[text_kitty])) + { + if (text_kitty > text_start) + { + segments.push_back(new LLNormalTextSegment(style, segment_start + text_start, segment_start + text_kitty, *this)); + } + + if (!emoji_style) + { + emoji_style = new LLStyle(*style); + emoji_style->setFont(LLFontGL::getFontEmoji()); + } + segments.push_back(new LLEmojiTextSegment(emoji_style, segment_start + text_kitty, segment_start + text_kitty + 1, *this)); + text_start = text_kitty + 1; + } + } + + if (text_start < text_len) + { + segments.push_back(new LLNormalTextSegment(style, segment_start + text_start, segment_start + text_len, *this)); + } +} + void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only) { // Save old state @@ -2334,6 +2364,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig S32 cur_length = getLength(); LLStyleConstSP sp(new LLStyle(highlight_params)); LLTextSegmentPtr segmentp; + segment_vec_t segments; if (underline_on_hover_only || mSkipLinkUnderline) { highlight_params.font.style("NORMAL"); @@ -2342,9 +2373,8 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig } else { - segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this); + createTextWithEmojiSegment(wide_text, cur_length, sp, segments); } - segment_vec_t segments; segments.push_back(segmentp); insertStringNoUndo(cur_length, wide_text, &segments); } @@ -2367,7 +2397,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig } else { - segments.push_back(new LLNormalTextSegment(sp, segment_start, segment_end, *this )); + createTextWithEmojiSegment(wide_text, segment_start, sp, segments); } insertStringNoUndo(getLength(), wide_text, &segments); @@ -3514,6 +3544,19 @@ const S32 LLLabelTextSegment::getLength() const return mEditor.getWlabel().length(); } +// +// LLEmojiTextSegment +// +LLEmojiTextSegment::LLEmojiTextSegment(LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor) + : LLNormalTextSegment(style, start, end, editor) +{ +} + +LLEmojiTextSegment::LLEmojiTextSegment(const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible) + : LLNormalTextSegment(color, start, end, editor, is_visible) +{ +} + // // LLOnHoverChangeableTextSegment // diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 590e7c9dbb..fc999c4cca 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -178,6 +178,17 @@ protected: /*virtual*/ const S32 getLength() const; }; +// Text segment that represents a single emoji character that has a different style (=font size) than the rest of +// the document it belongs to +class LLEmojiTextSegment : public LLNormalTextSegment +{ +public: + LLEmojiTextSegment(LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor); + LLEmojiTextSegment(const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE); + + bool canEdit() const override { return false; } +}; + // Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment) class LLOnHoverChangeableTextSegment : public LLNormalTextSegment { @@ -629,6 +640,7 @@ protected: void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params()); void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false); + void createTextWithEmojiSegment(const LLWString& wide_text, S32 segment_start, LLStyleConstSP style, segment_vec_t& segments); S32 normalizeUri(std::string& uri); protected: -- cgit v1.3 From 8694f055b64eb7ce13897e49afe73c4d3295a29a Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:09:30 +0200 Subject: Add emoji helper support to LLTextEditor --- indra/llui/lltexteditor.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ indra/llui/lltexteditor.h | 5 +++++ 2 files changed, 45 insertions(+) (limited to 'indra/llui') diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index b1f8b00cab..889940cf9a 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -43,6 +43,7 @@ #include "llmath.h" #include "llclipboard.h" +#include "llemojihelper.h" #include "llscrollbar.h" #include "llstl.h" #include "llstring.h" @@ -238,6 +239,7 @@ LLTextEditor::Params::Params() default_color("default_color"), commit_on_focus_lost("commit_on_focus_lost", false), show_context_menu("show_context_menu"), + show_emoji_helper("show_emoji_helper"), enable_tooltip_paste("enable_tooltip_paste") { addSynonym(prevalidate_callback, "text_type"); @@ -259,6 +261,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : mPrevalidateFunc(p.prevalidate_callback()), mContextMenu(NULL), mShowContextMenu(p.show_context_menu), + mShowEmojiHelper(p.show_emoji_helper), mEnableTooltipPaste(p.enable_tooltip_paste), mPassDelete(FALSE), mKeepSelectionOnReturn(false) @@ -501,6 +504,15 @@ void LLTextEditor::getSegmentsInRange(LLTextEditor::segment_vec_t& segments_out, } } +void LLTextEditor::setShowEmojiHelper(bool show) { + if (!mShowEmojiHelper) + { + LLEmojiHelper::instance().hideHelper(this); + } + + mShowEmojiHelper = show; +} + BOOL LLTextEditor::selectionContainsLineBreaks() { if (hasSelection()) @@ -930,6 +942,12 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask) S32 LLTextEditor::execute( TextCmd* cmd ) { + if (!mReadOnly && mShowEmojiHelper) + { + // Any change to our contents should always hide the helper + LLEmojiHelper::instance().hideHelper(this); + } + S32 delta = 0; if( cmd->execute(this, &delta) ) { @@ -1124,6 +1142,17 @@ void LLTextEditor::addChar(llwchar wc) setCursorPos(mCursorPos + addChar( mCursorPos, wc )); + if (!mReadOnly && mShowEmojiHelper) + { + LLWString wtext(getWText()); S32 shortCodePos; + if (LLEmojiHelper::isCursorInEmojiCode(wtext, mCursorPos, &shortCodePos)) + { + const LLRect cursorRect = getLocalRectFromDocIndex(mCursorPos); + const LLWString shortCode = wtext.substr(shortCodePos, mCursorPos); + LLEmojiHelper::instance().showHelper(this, cursorRect.mLeft, cursorRect.mTop, wstring_to_utf8str(shortCode)); + } + } + if (!mReadOnly && mAutoreplaceCallback != NULL) { // autoreplace the text, if necessary @@ -1774,6 +1803,11 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask ) } else { + if (!mReadOnly && mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask)) + { + return TRUE; + } + if (mEnableTooltipPaste && LLToolTipMgr::instance().toolTipVisible() && KEY_TAB == key) @@ -1815,6 +1849,12 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask ) { resetCursorBlink(); needsScroll(); + + if (mShowEmojiHelper) + { + // Dismiss the helper whenever we handled a key that it didn't + LLEmojiHelper::instance().hideHelper(this); + } } return handled; diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 26702b2412..04910b6f68 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -60,6 +60,7 @@ public: ignore_tab, commit_on_focus_lost, show_context_menu, + show_emoji_helper, enable_tooltip_paste, auto_indent; @@ -201,6 +202,9 @@ public: void setShowContextMenu(bool show) { mShowContextMenu = show; } bool getShowContextMenu() const { return mShowContextMenu; } + void setShowEmojiHelper(bool show); + bool getShowEmojiHelper() const { return mShowEmojiHelper; } + void setPassDelete(BOOL b) { mPassDelete = b; } protected: @@ -317,6 +321,7 @@ private: BOOL mAllowEmbeddedItems; bool mShowContextMenu; + bool mShowEmojiHelper; bool mEnableTooltipPaste; bool mPassDelete; bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter -- cgit v1.3 From ec23b4bc633b853223d8442f60e769d44a25fe2d Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:06:41 +0200 Subject: Add the basic emoji dictionary class (responsible for loading them from disk and providing helpful lookup functions) --- indra/llui/CMakeLists.txt | 2 + indra/llui/llemojidictionary.cpp | 177 +++++++++++++++++++++++++++++++++++++++ indra/llui/llemojidictionary.h | 71 ++++++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 indra/llui/llemojidictionary.cpp create mode 100644 indra/llui/llemojidictionary.h (limited to 'indra/llui') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index f781ff4110..4e007e429a 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -53,6 +53,7 @@ set(llui_SOURCE_FILES lldockcontrol.cpp lldraghandle.cpp lleditmenuhandler.cpp + llemojidictionary.cpp llf32uictrl.cpp llfiltereditor.cpp llflashtimer.cpp @@ -163,6 +164,7 @@ set(llui_HEADER_FILES lldockablefloater.h lldockcontrol.h lleditmenuhandler.h + llemojidictionary.h llf32uictrl.h llfiltereditor.h llflashtimer.h diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp new file mode 100644 index 0000000000..e149832a8b --- /dev/null +++ b/indra/llui/llemojidictionary.cpp @@ -0,0 +1,177 @@ +/** +* @file llemojidictionary.cpp +* @brief Implementation of LLEmojiDictionary +* +* $LicenseInfo:firstyear=2014&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2014, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" + +#include "lldir.h" +#include "llemojidictionary.h" +#include "llsdserialize.h" + +#include + +// ============================================================================ +// Constants +// + +constexpr char SKINNED_EMOJI_FILENAME[] = "emoji_characters.xml"; + +// ============================================================================ +// Helper functions +// + +template +std::list llsd_array_to_list(const LLSD& sd, std::function mutator = {}); + +template<> +std::list llsd_array_to_list(const LLSD& sd, std::function mutator) +{ + std::list result; + for (LLSD::array_const_iterator it = sd.beginArray(), end = sd.endArray(); it != end; ++it) + { + const LLSD& entry = *it; + if (!entry.isString()) + continue; + + result.push_back(entry.asStringRef()); + if (mutator) + { + mutator(result.back()); + } + } + return result; +} + +LLEmojiDescriptor::LLEmojiDescriptor(const LLSD& descriptor_sd) +{ + Name = descriptor_sd["Name"].asStringRef(); + + const LLWString emoji_string = utf8str_to_wstring(descriptor_sd["Character"].asString()); + Character = (1 == emoji_string.size()) ? emoji_string[0] : L'\0'; // We don't currently support character composition + + auto toLower = [](std::string& str) { LLStringUtil::toLower(str); }; + ShortCodes = llsd_array_to_list(descriptor_sd["ShortCodes"], toLower); + Categories = llsd_array_to_list(descriptor_sd["Categories"], toLower); + + if (Name.empty()) + { + Name = ShortCodes.front(); + } +} + +bool LLEmojiDescriptor::isValid() const +{ + return + Character && + !ShortCodes.empty() && + !Categories.empty(); +} + +// ============================================================================ +// LLEmojiDictionary class +// + +LLEmojiDictionary::LLEmojiDictionary() +{ +} + +// static +void LLEmojiDictionary::initClass() +{ + LLEmojiDictionary* pThis = &LLEmojiDictionary::initParamSingleton(); + + LLSD data; + + const std::string filename = gDirUtilp->findSkinnedFilenames(LLDir::XUI, SKINNED_EMOJI_FILENAME, LLDir::CURRENT_SKIN).front(); + llifstream file(filename.c_str()); + if (file.is_open()) + { + LL_DEBUGS() << "Loading emoji characters file at " << filename << LL_ENDL; + LLSDSerialize::fromXML(data, file); + } + + if (data.isUndefined()) + { + LL_WARNS() << "Emoji file characters missing or ill-formed" << LL_ENDL; + return; + } + + for (LLSD::array_const_iterator descriptor_it = data.beginArray(), descriptor_end = data.endArray(); descriptor_it != descriptor_end; ++descriptor_it) + { + LLEmojiDescriptor descriptor(*descriptor_it); + if (!descriptor.isValid()) + { + LL_WARNS() << "Skipping invalid emoji descriptor " << descriptor.Character << LL_ENDL; + continue; + } + pThis->addEmoji(std::move(descriptor)); + } +} + +LLWString LLEmojiDictionary::findMatchingEmojis(std::string needle) +{ + // Search without the colon (if present) so the user can type ':food' and see all emojis in the 'Food' category + LLStringUtil::toLower(needle); + const auto kitty_needle = boost::make_iterator_range((boost::starts_with(needle, ":")) ? needle.begin() + 1 : needle.begin(), needle.end()); + + LLWString wstr; + for (const auto& descr : mEmojis) + { + for (const auto& short_code : descr.ShortCodes) + { + if (boost::icontains(short_code, kitty_needle)) + { + wstr.push_back(descr.Character); + continue; + } + } + + for (const auto& category : descr.Categories) + { + if (boost::icontains(category, kitty_needle)) + { + wstr.push_back(descr.Character); + continue; + } + } + } + + return wstr; +} + +std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch) +{ + const auto it = mEmoji2Descr.find(ch); + return (mEmoji2Descr.end() != it) ? it->second->Name : LLStringUtil::null; +} + +void LLEmojiDictionary::addEmoji(LLEmojiDescriptor&& descr) +{ + mEmojis.push_back(descr); + const LLEmojiDescriptor& back = mEmojis.back(); + mEmoji2Descr.insert(std::make_pair(descr.Character, &back)); +} + +// ============================================================================ diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h new file mode 100644 index 0000000000..87ea4a5aef --- /dev/null +++ b/indra/llui/llemojidictionary.h @@ -0,0 +1,71 @@ +/** +* @file llemojidictionary.h +* @brief Header file for LLEmojiDictionary +* +* $LicenseInfo:firstyear=2014&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2014, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#pragma once + +#include "lldictionary.h" +#include "llinitdestroyclass.h" +#include "llsingleton.h" + +// ============================================================================ +// LLEmojiDescriptor class +// + +struct LLEmojiDescriptor +{ + LLEmojiDescriptor(const LLSD& descriptor_sd); + + bool isValid() const; + + std::string Name; + llwchar Character; + std::list ShortCodes; + std::list Categories; +}; + +// ============================================================================ +// LLEmojiDictionary class +// + +class LLEmojiDictionary : public LLParamSingleton, public LLInitClass +{ + LLSINGLETON(LLEmojiDictionary); + ~LLEmojiDictionary() override {}; + +public: + static void initClass(); + LLWString findMatchingEmojis(std::string needle); + std::string getNameFromEmoji(llwchar ch); + +private: + void addEmoji(LLEmojiDescriptor&& descr); + +private: + std::list mEmojis; + std::map mEmoji2Descr; +}; + +// ============================================================================ -- cgit v1.3 From dad25bcb1e17e3dc384a9fb35d21b669bc3bbacd Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:17:02 +0200 Subject: Add the emoji helper class which can be used by text-input controls to provide emoji picker support --- indra/llui/CMakeLists.txt | 2 + indra/llui/llemojihelper.cpp | 142 +++++++++++++++++++++++++++++++++++++++++++ indra/llui/llemojihelper.h | 64 +++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 indra/llui/llemojihelper.cpp create mode 100644 indra/llui/llemojihelper.h (limited to 'indra/llui') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 4e007e429a..68019734ab 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -54,6 +54,7 @@ set(llui_SOURCE_FILES lldraghandle.cpp lleditmenuhandler.cpp llemojidictionary.cpp + llemojihelper.cpp llf32uictrl.cpp llfiltereditor.cpp llflashtimer.cpp @@ -165,6 +166,7 @@ set(llui_HEADER_FILES lldockcontrol.h lleditmenuhandler.h llemojidictionary.h + llemojihelper.h llf32uictrl.h llfiltereditor.h llflashtimer.h diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp new file mode 100644 index 0000000000..d4c31ee986 --- /dev/null +++ b/indra/llui/llemojihelper.cpp @@ -0,0 +1,142 @@ +/** +* @file llemojihelper.h +* @brief Header file for LLEmojiHelper +* +* $LicenseInfo:firstyear=2014&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2014, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" + +#include "llemojidictionary.h" +#include "llemojihelper.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "lluictrl.h" + +// ============================================================================ +// Constants +// + +constexpr char DEFAULT_EMOJI_HELPER_FLOATER[] = "emoji_complete"; +constexpr S32 HELPER_FLOATER_OFFSET_X = 20; +constexpr S32 HELPER_FLOATER_OFFSET_Y = 0; + +// ============================================================================ +// LLEmojiHelper +// + +std::string LLEmojiHelper::getToolTip(llwchar ch) const +{ + return LLEmojiDictionary::instance().getNameFromEmoji(ch); +} + +bool LLEmojiHelper::isActive(const LLUICtrl* ctrl_p) const +{ + return mHostHandle.get() == ctrl_p; +} + +// static +bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S32* pShortCodePos) +{ + S32 shortCodePos = cursorPos; + + while (shortCodePos > 1 && + (LLStringOps::isAlnum(wtext[shortCodePos - 1]) || wtext[shortCodePos - 1] == L'-' || wtext[shortCodePos - 1] == L'_') ) + { + shortCodePos--; + } + + bool isShortCode = (L':' == wtext[shortCodePos - 1]) && (cursorPos - shortCodePos >= 2); + if (pShortCodePos) + *pShortCodePos = (isShortCode) ? shortCodePos - 1 : -1; + return isShortCode; +} + +void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function cb) +{ + if (mHelperHandle.isDead()) + { + LLFloater* pHelperFloater = LLFloaterReg::getInstance(DEFAULT_EMOJI_HELPER_FLOATER); + mHelperHandle = pHelperFloater->getHandle(); + mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())); }, std::placeholders::_2)); + } + setHostCtrl(hostctrl_p); + mEmojiCommitCb = cb; + + S32 floater_x, floater_y; + if (!hostctrl_p->localPointToOtherView(local_x, local_y, &floater_x, &floater_y, gFloaterView)) + { + LL_ERRS() << "Cannot show emoji helper for non-floater controls." << LL_ENDL; + return; + } + + LLFloater* pHelperFloater = mHelperHandle.get(); + LLRect rct = pHelperFloater->getRect(); + rct.setLeftTopAndSize(floater_x - HELPER_FLOATER_OFFSET_X, floater_y - HELPER_FLOATER_OFFSET_Y + rct.getHeight(), rct.getWidth(), rct.getHeight()); + pHelperFloater->setRect(rct); + pHelperFloater->openFloater(LLSD().with("hint", short_code)); +} + +void LLEmojiHelper::hideHelper(const LLUICtrl* ctrl_p) +{ + setHostCtrl(nullptr); +} + +bool LLEmojiHelper::handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask) +{ + if (mHelperHandle.isDead() || !isActive(ctrl_p)) + { + return false; + } + + return mHelperHandle.get()->handleKey(key, mask, true); +} + +void LLEmojiHelper::onCommitEmoji(const LLWString& wstr) +{ + if (!mHostHandle.isDead() && mEmojiCommitCb) + { + mEmojiCommitCb(wstr); + } +} + +void LLEmojiHelper::setHostCtrl(LLUICtrl* hostctrl_p) +{ + const LLUICtrl* pCurHostCtrl = mHostHandle.get(); + if (pCurHostCtrl != hostctrl_p) + { + mHostCtrlFocusLostConn.disconnect(); + mHostHandle.markDead(); + mEmojiCommitCb = {}; + + if (!mHelperHandle.isDead()) + { + mHelperHandle.get()->closeFloater(); + } + + if (hostctrl_p) + { + mHostHandle = hostctrl_p->getHandle(); + mHostCtrlFocusLostConn = hostctrl_p->setFocusLostCallback(std::bind([&]() { hideHelper(getHostCtrl()); })); + } + } +} diff --git a/indra/llui/llemojihelper.h b/indra/llui/llemojihelper.h new file mode 100644 index 0000000000..7ed042fc5f --- /dev/null +++ b/indra/llui/llemojihelper.h @@ -0,0 +1,64 @@ +/** +* @file llemojihelper.h +* @brief Header file for LLEmojiHelper +* +* $LicenseInfo:firstyear=2014&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2014, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#pragma once + +#include "llhandle.h" +#include "llsingleton.h" + +#include + +class LLFloater; +class LLUICtrl; + +class LLEmojiHelper : public LLSingleton +{ + LLSINGLETON(LLEmojiHelper) {} + ~LLEmojiHelper() override {} + +public: + // General + std::string getToolTip(llwchar ch) const; + bool isActive(const LLUICtrl* ctrl_p) const; + static bool isCursorInEmojiCode(const LLWString& wtext, S32 cursor_pos, S32* short_code_pos_p = nullptr); + void showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function commit_cb); + void hideHelper(const LLUICtrl* ctrl_p); + + // Eventing + bool handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask); + void onCommitEmoji(const LLWString& wstr); + +protected: + LLUICtrl* getHostCtrl() const { return mHostHandle.get(); } + void setHostCtrl(LLUICtrl* hostctrl_p); + +private: + LLHandle mHostHandle; + LLHandle mHelperHandle; + boost::signals2::connection mHostCtrlFocusLostConn; + boost::signals2::connection mHelperCommitConn; + std::function mEmojiCommitCb; +}; -- cgit v1.3 From 3acb4caa0fb9d381be6cfbe1693ace389d90a16c Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:18:22 +0200 Subject: Add emoji helper support to LLTextEditor --- indra/llui/lltexteditor.cpp | 21 ++++++++++++++++++--- indra/llui/lltexteditor.h | 2 ++ 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 889940cf9a..168c260c7d 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -676,6 +676,21 @@ void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_p endSelection(); } +void LLTextEditor::handleEmojiCommit(const LLWString& wstr) +{ + LLWString wtext(getWText()); S32 shortCodePos; + if (LLEmojiHelper::isCursorInEmojiCode(wtext, mCursorPos, &shortCodePos)) + { + remove(shortCodePos, mCursorPos - shortCodePos, true); + + auto styleParams = LLStyle::Params(); + styleParams.font = LLFontGL::getFontEmoji(); + insert(shortCodePos, wstr, false, new LLEmojiTextSegment(new LLStyle(styleParams), shortCodePos, shortCodePos + wstr.size(), *this)); + + setCursorPos(shortCodePos + 1); + } +} + BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; @@ -1147,9 +1162,9 @@ void LLTextEditor::addChar(llwchar wc) LLWString wtext(getWText()); S32 shortCodePos; if (LLEmojiHelper::isCursorInEmojiCode(wtext, mCursorPos, &shortCodePos)) { - const LLRect cursorRect = getLocalRectFromDocIndex(mCursorPos); - const LLWString shortCode = wtext.substr(shortCodePos, mCursorPos); - LLEmojiHelper::instance().showHelper(this, cursorRect.mLeft, cursorRect.mTop, wstring_to_utf8str(shortCode)); + const LLRect cursorRect = getLocalRectFromDocIndex(mCursorPos - 1); + const LLWString shortCode = wtext.substr(shortCodePos, mCursorPos - shortCodePos); + LLEmojiHelper::instance().showHelper(this, cursorRect.mLeft, cursorRect.mTop, wstring_to_utf8str(shortCode), std::bind(&LLTextEditor::handleEmojiCommit, this, std::placeholders::_1)); } } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 04910b6f68..4c8175a286 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -92,6 +92,8 @@ public: static S32 spacesPerTab(); + void handleEmojiCommit(const LLWString& wstr); + // mousehandler overrides virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); -- cgit v1.3 From f6f52d327be5f03265d66a95df6fc0716f91ca07 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:35:44 +0200 Subject: Provide a way for a floater to remain the topmost floater, even when focus is given to a different floater --- indra/llui/llfloater.cpp | 24 +++++++++++++++++++++++- indra/llui/llfloater.h | 4 ++++ 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 0e42922543..04f6b11b7c 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -3039,7 +3039,29 @@ void LLFloaterView::syncFloaterTabOrder() LLFloater* floaterp = dynamic_cast(*child_it); if (gFocusMgr.childHasKeyboardFocus(floaterp)) { - bringToFront(floaterp, FALSE); + if (mFrontChild != floaterp) + { + // Grab a list of the top floaters that want to stay on top of the focused floater + std::list listTop; + if (mFrontChild && !mFrontChild->canFocusStealFrontmost()) + { + for (LLView* childfloaterp : *getChildList()) + { + if (static_cast(childfloaterp)->canFocusStealFrontmost()) + break; + listTop.push_back(childfloaterp); + } + } + + bringToFront(floaterp, FALSE); + + // Restore top floaters + for (LLView* childp :listTop) + { + sendChildToFront(childp); + } + } + break; } } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 2672d600c6..1d4aff31eb 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -313,6 +313,9 @@ public: /*virtual*/ void setVisible(BOOL visible); // do not override /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); // do not override + bool canFocusStealFrontmost() const { return mFocusStealsFrontmost; } + void setFocusStealsFrontmost(bool wants_frontmost) { mFocusStealsFrontmost = wants_frontmost; } + void setFrontmost(BOOL take_focus = TRUE, BOOL restore = TRUE); virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD()); @@ -478,6 +481,7 @@ private: BOOL mCanTearOff; BOOL mCanMinimize; BOOL mCanClose; + bool mFocusStealsFrontmost = true; // FALSE if we don't want the currently focused floater to cover this floater without user interaction BOOL mDragOnLeft; BOOL mResizable; -- cgit v1.3 From 8d08f417dc1f5b2681774f000951993e0f0cf79f Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:37:10 +0200 Subject: Show tooltip when hovering over an emoji text segment (currently will show its shortcode) --- indra/llui/lltextbase.cpp | 14 ++++++++++++++ indra/llui/lltextbase.h | 1 + 2 files changed, 15 insertions(+) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 2a6e6901e4..693dcb7b8d 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -3557,6 +3557,20 @@ LLEmojiTextSegment::LLEmojiTextSegment(const LLColor4& color, S32 start, S32 end { } +BOOL LLEmojiTextSegment::handleToolTip(S32 x, S32 y, MASK mask) +{ + if (mTooltip.empty()) + { + LLWString emoji = getWText().substr(getStart(), getEnd() - getStart()); + if (!emoji.empty()) + { + mTooltip = LLEmojiHelper::instance().getToolTip(emoji[0]); + } + } + + return LLNormalTextSegment::handleToolTip(x, y, mask); +} + // // LLOnHoverChangeableTextSegment // diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index fc999c4cca..31e9f16110 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -187,6 +187,7 @@ public: LLEmojiTextSegment(const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE); bool canEdit() const override { return false; } + BOOL handleToolTip(S32 x, S32 y, MASK mask); }; // Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment) -- cgit v1.3 From 58cdcd5dd23778c6fad9fa0da31b670ceff8eeeb Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 17:47:51 +0200 Subject: Handle return and escape in the mini emoji helper --- indra/llui/llemojihelper.cpp | 5 ++++ indra/llui/llemojihelper.h | 2 +- indra/newview/llpanelemojicomplete.cpp | 48 +++++++++++++++++++++++++++++++--- indra/newview/llpanelemojicomplete.h | 1 + 4 files changed, 51 insertions(+), 5 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index d4c31ee986..54c801ab7b 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -98,6 +98,11 @@ void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, c void LLEmojiHelper::hideHelper(const LLUICtrl* ctrl_p) { + if (ctrl_p && !isActive(ctrl_p)) + { + return; + } + setHostCtrl(nullptr); } diff --git a/indra/llui/llemojihelper.h b/indra/llui/llemojihelper.h index 7ed042fc5f..63f5c640c9 100644 --- a/indra/llui/llemojihelper.h +++ b/indra/llui/llemojihelper.h @@ -45,7 +45,7 @@ public: bool isActive(const LLUICtrl* ctrl_p) const; static bool isCursorInEmojiCode(const LLWString& wtext, S32 cursor_pos, S32* short_code_pos_p = nullptr); void showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function commit_cb); - void hideHelper(const LLUICtrl* ctrl_p); + void hideHelper(const LLUICtrl* ctrl_p = nullptr); // Eventing bool handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask); diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index f6823befac..61b08ad48d 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llemojidictionary.h" +#include "llemojihelper.h" #include "llpanelemojicomplete.h" #include "lluictrlfactory.h" @@ -101,9 +102,9 @@ BOOL LLPanelEmojiComplete::handleHover(S32 x, S32 y, MASK mask) BOOL LLPanelEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent) { + bool handled = false; if (MASK_NONE == mask) { - bool handled = false; switch (key) { case KEY_LEFT: @@ -116,11 +117,24 @@ BOOL LLPanelEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent selectNext(); handled = true; break; + case KEY_RETURN: + if (!mEmojis.empty()) + { + LLWString wstr; + wstr.push_back(mEmojis.at(mCurSelected)); + setValue(wstring_to_utf8str(wstr)); + onCommit(); + handled = true; + } + break; } - return handled; } - return false; + if (handled) + { + return TRUE; + } + return LLUICtrl::handleKey(key, mask, called_from_parent); } void LLPanelEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -223,6 +237,26 @@ LLFloaterEmojiComplete::LLFloaterEmojiComplete(const LLSD& sdKey) setIsChrome(true); } +BOOL LLFloaterEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ + bool handled = false; + if (MASK_NONE == mask) + { + switch (key) + { + case KEY_ESCAPE: + LLEmojiHelper::instance().hideHelper(); + handled = true; + break; + } + + } + + if (handled) + return TRUE; + return LLFloater::handleKey(key, mask, called_from_parent); +} + void LLFloaterEmojiComplete::onOpen(const LLSD& key) { mEmojiCtrl->setEmojiHint(key["hint"].asString()); @@ -231,9 +265,15 @@ void LLFloaterEmojiComplete::onOpen(const LLSD& key) BOOL LLFloaterEmojiComplete::postBuild() { mEmojiCtrl = findChild("emoji_complete_ctrl"); + mEmojiCtrl->setCommitCallback( + std::bind([&](const LLSD& sdValue) + { + setValue(sdValue); + onCommit(); + }, std::placeholders::_2)); mEmojiCtrlHorz = getRect().getWidth() - mEmojiCtrl->getRect().getWidth(); - return TRUE; + return LLFloater::postBuild(); } void LLFloaterEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_parent) diff --git a/indra/newview/llpanelemojicomplete.h b/indra/newview/llpanelemojicomplete.h index b389ac9d53..361a2dc9b7 100644 --- a/indra/newview/llpanelemojicomplete.h +++ b/indra/newview/llpanelemojicomplete.h @@ -98,6 +98,7 @@ public: LLFloaterEmojiComplete(const LLSD& sdKey); public: + BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override; void onOpen(const LLSD& key) override; BOOL postBuild() override; void reshape(S32 width, S32 height, BOOL called_from_parent) override; -- cgit v1.3 From fb1553d8cf704eeb222de7ebd520a81fa242b317 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 17:55:13 +0200 Subject: Cannot use the :+1 emoji shortcode --- indra/llui/llemojihelper.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index 54c801ab7b..551f0331e7 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -59,8 +59,18 @@ bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S { S32 shortCodePos = cursorPos; - while (shortCodePos > 1 && - (LLStringOps::isAlnum(wtext[shortCodePos - 1]) || wtext[shortCodePos - 1] == L'-' || wtext[shortCodePos - 1] == L'_') ) + auto isPartOfShortcode = [](llwchar ch) { + switch (ch) + { + case L'-': + case L'_': + case L'+': + return true; + default: + return LLStringOps::isAlnum(ch); + } + }; + while (shortCodePos > 1 && isPartOfShortcode(wtext[shortCodePos - 1])) { shortCodePos--; } -- cgit v1.3 From d1dbefc09b77990563d22aaf08d0c5708cc6cbbe Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 19:05:19 +0200 Subject: Refactor emoji matching --- indra/llui/llemojidictionary.cpp | 70 ++++++++++++++++++++++++---------------- indra/llui/llemojidictionary.h | 2 +- 2 files changed, 43 insertions(+), 29 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp index e149832a8b..eefa4047a2 100644 --- a/indra/llui/llemojidictionary.cpp +++ b/indra/llui/llemojidictionary.cpp @@ -31,6 +31,8 @@ #include "llsdserialize.h" #include +#include +#include // ============================================================================ // Constants @@ -89,6 +91,41 @@ bool LLEmojiDescriptor::isValid() const !Categories.empty(); } +struct emoji_filter_base +{ + emoji_filter_base(const std::string& needle) + { + // Search without the colon (if present) so the user can type ':food' and see all emojis in the 'Food' category + mNeedle = (boost::starts_with(needle, ":")) ? needle.substr(1) : needle; + LLStringUtil::toLower(mNeedle); + } + +protected: + std::string mNeedle; +}; + +struct emoji_filter_shortcode_or_category_contains : public emoji_filter_base +{ + emoji_filter_shortcode_or_category_contains(const std::string& needle) : emoji_filter_base(needle) {} + + bool operator()(const LLEmojiDescriptor& descr) const + { + for (const auto& short_code : descr.ShortCodes) + { + if (boost::icontains(short_code, mNeedle)) + return true; + } + + for (const auto& category : descr.Categories) + { + if (boost::icontains(category, mNeedle)) + return true; + } + + return false; + } +}; + // ============================================================================ // LLEmojiDictionary class // @@ -130,35 +167,12 @@ void LLEmojiDictionary::initClass() } } -LLWString LLEmojiDictionary::findMatchingEmojis(std::string needle) +LLWString LLEmojiDictionary::findMatchingEmojis(const std::string& needle) const { - // Search without the colon (if present) so the user can type ':food' and see all emojis in the 'Food' category - LLStringUtil::toLower(needle); - const auto kitty_needle = boost::make_iterator_range((boost::starts_with(needle, ":")) ? needle.begin() + 1 : needle.begin(), needle.end()); - - LLWString wstr; - for (const auto& descr : mEmojis) - { - for (const auto& short_code : descr.ShortCodes) - { - if (boost::icontains(short_code, kitty_needle)) - { - wstr.push_back(descr.Character); - continue; - } - } - - for (const auto& category : descr.Categories) - { - if (boost::icontains(category, kitty_needle)) - { - wstr.push_back(descr.Character); - continue; - } - } - } - - return wstr; + LLWString result; + boost::transform(mEmojis | boost::adaptors::filtered(emoji_filter_shortcode_or_category_contains(needle)), + std::back_inserter(result), [](const auto& descr) { return descr.Character; }); + return result; } std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch) diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h index 87ea4a5aef..3fa55cd417 100644 --- a/indra/llui/llemojidictionary.h +++ b/indra/llui/llemojidictionary.h @@ -57,7 +57,7 @@ class LLEmojiDictionary : public LLParamSingleton, public LLI public: static void initClass(); - LLWString findMatchingEmojis(std::string needle); + LLWString findMatchingEmojis(const std::string& needle) const; std::string getNameFromEmoji(llwchar ch); private: -- cgit v1.3 From c40d3351d511b19f4468f7467be38499bf16588f Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 2 Nov 2022 19:05:24 +0100 Subject: Commit immediately if the user already typed a full shortcode --- indra/llui/llemojidictionary.cpp | 17 +++++++++++++---- indra/llui/llemojidictionary.h | 6 ++++-- indra/llui/llemojihelper.cpp | 8 ++++++++ indra/llui/lltextbase.cpp | 1 + 4 files changed, 26 insertions(+), 6 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp index eefa4047a2..c31638b0bf 100644 --- a/indra/llui/llemojidictionary.cpp +++ b/indra/llui/llemojidictionary.cpp @@ -175,17 +175,26 @@ LLWString LLEmojiDictionary::findMatchingEmojis(const std::string& needle) const return result; } -std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch) +const LLEmojiDescriptor* LLEmojiDictionary::getDescriptorFromShortCode(const std::string& short_code) const +{ + const auto it = mShortCode2Descr.find(short_code); + return (mShortCode2Descr.end() != it) ? &it->second : nullptr; +} + +std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch) const { const auto it = mEmoji2Descr.find(ch); - return (mEmoji2Descr.end() != it) ? it->second->Name : LLStringUtil::null; + return (mEmoji2Descr.end() != it) ? it->second.Name : LLStringUtil::null; } void LLEmojiDictionary::addEmoji(LLEmojiDescriptor&& descr) { mEmojis.push_back(descr); - const LLEmojiDescriptor& back = mEmojis.back(); - mEmoji2Descr.insert(std::make_pair(descr.Character, &back)); + mEmoji2Descr.insert(std::make_pair(descr.Character, mEmojis.back())); + for (const std::string& shortCode : descr.ShortCodes) + { + mShortCode2Descr.insert(std::make_pair(shortCode, mEmojis.back())); + } } // ============================================================================ diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h index 3fa55cd417..0cde663719 100644 --- a/indra/llui/llemojidictionary.h +++ b/indra/llui/llemojidictionary.h @@ -58,14 +58,16 @@ class LLEmojiDictionary : public LLParamSingleton, public LLI public: static void initClass(); LLWString findMatchingEmojis(const std::string& needle) const; - std::string getNameFromEmoji(llwchar ch); + const LLEmojiDescriptor* getDescriptorFromShortCode(const std::string& short_code) const; + std::string getNameFromEmoji(llwchar ch) const; private: void addEmoji(LLEmojiDescriptor&& descr); private: std::list mEmojis; - std::map mEmoji2Descr; + std::map mEmoji2Descr; + std::map mShortCode2Descr; }; // ============================================================================ diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index 551f0331e7..32471e59a8 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -83,6 +83,14 @@ bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function cb) { + // Commit immediately if the user already typed a full shortcode + if (const auto* emojiDescrp = LLEmojiDictionary::instance().getDescriptorFromShortCode(short_code)) + { + cb(LLWString(1, emojiDescrp->Character)); + hideHelper(); + return; + } + if (mHelperHandle.isDead()) { LLFloater* pHelperFloater = LLFloaterReg::getInstance(DEFAULT_EMOJI_HELPER_FLOATER); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 693dcb7b8d..b88c7ced40 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -29,6 +29,7 @@ #include "lltextbase.h" +#include "llemojihelper.h" #include "lllocalcliprect.h" #include "llmenugl.h" #include "llscrollcontainer.h" -- cgit v1.3 From 81dd143d0d901e8e5234cff01fbda246e4621628 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Tue, 8 Nov 2022 00:16:58 +0100 Subject: [FIXED] Various minor issues - Typing :+1: doesn't replace the short code with the thumbs-up emoji - Moving the mouse over the emoji complete panel highlights the wrong emoji when mScrollPos > 0 - Emoji complete panel is missing attributes - Crash when attempting to show the tooltip for an emoji text segment - Emoji autocomplete panel can sometimes show empty (type ':cat', select the heart eyed one, Ctrl-Z and then type 2 which should show the emoji for :cat2 but shows an empty square instead) --- indra/llui/llemojidictionary.cpp | 8 ++++---- indra/llui/llemojidictionary.h | 4 ++-- indra/llui/llemojihelper.cpp | 3 ++- indra/newview/llpanelemojicomplete.cpp | 4 ++-- indra/newview/skins/default/xui/en/widgets/emoji_complete.xml | 3 +++ 5 files changed, 13 insertions(+), 9 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp index c31638b0bf..b70a9b2e7a 100644 --- a/indra/llui/llemojidictionary.cpp +++ b/indra/llui/llemojidictionary.cpp @@ -178,22 +178,22 @@ LLWString LLEmojiDictionary::findMatchingEmojis(const std::string& needle) const const LLEmojiDescriptor* LLEmojiDictionary::getDescriptorFromShortCode(const std::string& short_code) const { const auto it = mShortCode2Descr.find(short_code); - return (mShortCode2Descr.end() != it) ? &it->second : nullptr; + return (mShortCode2Descr.end() != it) ? it->second : nullptr; } std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch) const { const auto it = mEmoji2Descr.find(ch); - return (mEmoji2Descr.end() != it) ? it->second.Name : LLStringUtil::null; + return (mEmoji2Descr.end() != it) ? it->second->Name : LLStringUtil::null; } void LLEmojiDictionary::addEmoji(LLEmojiDescriptor&& descr) { mEmojis.push_back(descr); - mEmoji2Descr.insert(std::make_pair(descr.Character, mEmojis.back())); + mEmoji2Descr.insert(std::make_pair(descr.Character, &mEmojis.back())); for (const std::string& shortCode : descr.ShortCodes) { - mShortCode2Descr.insert(std::make_pair(shortCode, mEmojis.back())); + mShortCode2Descr.insert(std::make_pair(shortCode, &mEmojis.back())); } } diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h index 0cde663719..46a61f1cd7 100644 --- a/indra/llui/llemojidictionary.h +++ b/indra/llui/llemojidictionary.h @@ -66,8 +66,8 @@ private: private: std::list mEmojis; - std::map mEmoji2Descr; - std::map mShortCode2Descr; + std::map mEmoji2Descr; + std::map mShortCode2Descr; }; // ============================================================================ diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index 32471e59a8..1e4c19a183 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -57,7 +57,8 @@ bool LLEmojiHelper::isActive(const LLUICtrl* ctrl_p) const // static bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S32* pShortCodePos) { - S32 shortCodePos = cursorPos; + // If the cursor is currently on a colon start the check one character further back + S32 shortCodePos = (cursorPos == 0 || L':' != wtext[cursorPos - 1]) ? cursorPos : cursorPos - 1; auto isPartOfShortcode = [](llwchar ch) { switch (ch) diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index a7058a6724..f890a14e8e 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -146,9 +146,9 @@ void LLPanelEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_paren void LLPanelEmojiComplete::setEmojiHint(const std::string& hint) { llwchar curEmoji = (mCurSelected < mEmojis.size()) ? mEmojis.at(mCurSelected) : 0; - size_t curEmojiIdx = (curEmoji) ? mEmojis.find(curEmoji) : std::string::npos; mEmojis = LLEmojiDictionary::instance().findMatchingEmojis(hint); + size_t curEmojiIdx = (curEmoji) ? mEmojis.find(curEmoji) : std::string::npos; mCurSelected = (std::string::npos != curEmojiIdx) ? curEmojiIdx : 0; if (mAutoSize) @@ -168,7 +168,7 @@ size_t LLPanelEmojiComplete::posToIndex(S32 x, S32 y) const { if (mRenderRect.pointInRect(x, y)) { - return llmin((size_t)x / mEmojiWidth, mEmojis.size() - 1); + return mScrollPos + llmin((size_t)x / mEmojiWidth, mEmojis.size() - 1); } return npos; } diff --git a/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml b/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml index f35105ff7e..370f1d174e 100644 --- a/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml +++ b/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml @@ -1,7 +1,10 @@ -- cgit v1.3 From 17a3924a28770e6910022ad8f627bb8e2b667730 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Tue, 8 Nov 2022 01:10:09 +0100 Subject: Add proper mouse down handler to the emoji complete panel -> the previous commit didn't properly set mFrontChild after restoring the topmost floaters -> additionally we don't want mouse clicks in "can't steal focus from frontmost" floaters to set focus to them --- indra/llui/llfloater.cpp | 23 ++++++++++++++--------- indra/newview/llpanelemojicomplete.cpp | 30 +++++++++++++++++++++++++++--- indra/newview/llpanelemojicomplete.h | 3 +++ 3 files changed, 44 insertions(+), 12 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 04f6b11b7c..6f341bc0cd 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2486,7 +2486,7 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus, BOOL restore if (mFrontChild == child) { - if (give_focus && !gFocusMgr.childHasKeyboardFocus(child)) + if (give_focus && child->canFocusStealFrontmost() && !gFocusMgr.childHasKeyboardFocus(child)) { child->setFocus(TRUE); } @@ -3042,24 +3042,29 @@ void LLFloaterView::syncFloaterTabOrder() if (mFrontChild != floaterp) { // Grab a list of the top floaters that want to stay on top of the focused floater - std::list listTop; + std::list listTop; if (mFrontChild && !mFrontChild->canFocusStealFrontmost()) { - for (LLView* childfloaterp : *getChildList()) + for (LLView* childp : *getChildList()) { - if (static_cast(childfloaterp)->canFocusStealFrontmost()) + LLFloater* child_floaterp = static_cast(childp); + if (child_floaterp->canFocusStealFrontmost()) break; - listTop.push_back(childfloaterp); + listTop.push_back(child_floaterp); } } bringToFront(floaterp, FALSE); // Restore top floaters - for (LLView* childp :listTop) - { - sendChildToFront(childp); - } + if (!listTop.empty()) + { + for (LLView* childp : listTop) + { + sendChildToFront(childp); + } + mFrontChild = listTop.back(); + } } break; diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index f890a14e8e..8b89e3aa14 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -120,9 +120,6 @@ BOOL LLPanelEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent case KEY_RETURN: if (!mEmojis.empty()) { - LLWString wstr; - wstr.push_back(mEmojis.at(mCurSelected)); - setValue(wstring_to_utf8str(wstr)); onCommit(); handled = true; } @@ -137,6 +134,33 @@ BOOL LLPanelEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent return LLUICtrl::handleKey(key, mask, called_from_parent); } +BOOL LLPanelEmojiComplete::handleMouseDown(S32 x, S32 y, MASK mask) +{ + mCurSelected = posToIndex(x, y); + mLastHover = LLVector2(x, y); + + return TRUE; +} + +BOOL LLPanelEmojiComplete::handleMouseUp(S32 x, S32 y, MASK mask) +{ + mCurSelected = posToIndex(x, y); + onCommit(); + + return TRUE; +} + +void LLPanelEmojiComplete::onCommit() +{ + if (npos != mCurSelected) + { + LLWString wstr; + wstr.push_back(mEmojis.at(mCurSelected)); + setValue(wstring_to_utf8str(wstr)); + LLUICtrl::onCommit(); + } +} + void LLPanelEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_parent) { LLUICtrl::reshape(width, height, called_from_parent); diff --git a/indra/newview/llpanelemojicomplete.h b/indra/newview/llpanelemojicomplete.h index 138cc465ba..2116b350be 100644 --- a/indra/newview/llpanelemojicomplete.h +++ b/indra/newview/llpanelemojicomplete.h @@ -56,6 +56,9 @@ public: void draw() override; BOOL handleHover(S32 x, S32 y, MASK mask) override; BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override; + BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + void onCommit() override; void reshape(S32 width, S32 height, BOOL called_from_parent) override; public: -- cgit v1.3 From 62d62abe9c35066bb7bb29155046311245854563 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 9 Nov 2022 00:08:43 +0100 Subject: [FIXED] Using the Windows emoji picker or pasting text containing emojis doesn't create emoji segments (=emoji size is same size as the text size) -> Partial revert of 063fe59 --- indra/llui/lltextbase.cpp | 55 +++++++++++++++++++---------------------------- indra/llui/lltextbase.h | 1 - 2 files changed, 22 insertions(+), 34 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index b88c7ced40..28165aa1ef 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -834,6 +834,25 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s } } + // Insert special segments where necessary (insertSegment takes care of splitting normal text segments around them for us) + { + LLStyleSP emoji_style; + for (S32 text_kitty = 0, text_len = wstr.size(); text_kitty < text_len; text_kitty++) + { + if (LLStringOps::isEmoji(wstr[text_kitty])) + { + if (!emoji_style) + { + emoji_style = new LLStyle(getStyleParams()); + emoji_style->setFont(LLFontGL::getFontEmoji()); + } + + S32 new_seg_start = pos + text_kitty; + insertSegment(new LLEmojiTextSegment(emoji_style, new_seg_start, new_seg_start + 1, *this)); + } + } + } + getViewModel()->getEditableDisplay().insert(pos, wstr); if ( truncate() ) @@ -2303,36 +2322,6 @@ void LLTextBase::appendWidget(const LLInlineViewSegment::Params& params, const s insertStringNoUndo(getLength(), widget_wide_text, &segments); } -void LLTextBase::createTextWithEmojiSegment(const LLWString& text, S32 segment_start, LLStyleConstSP style, segment_vec_t& segments) -{ - LLStyleSP emoji_style; - - S32 text_start = 0, text_kitty = 0, text_len = text.size(); - for (; text_kitty < text_len; text_kitty++) - { - if (LLStringOps::isEmoji(text[text_kitty])) - { - if (text_kitty > text_start) - { - segments.push_back(new LLNormalTextSegment(style, segment_start + text_start, segment_start + text_kitty, *this)); - } - - if (!emoji_style) - { - emoji_style = new LLStyle(*style); - emoji_style->setFont(LLFontGL::getFontEmoji()); - } - segments.push_back(new LLEmojiTextSegment(emoji_style, segment_start + text_kitty, segment_start + text_kitty + 1, *this)); - text_start = text_kitty + 1; - } - } - - if (text_start < text_len) - { - segments.push_back(new LLNormalTextSegment(style, segment_start + text_start, segment_start + text_len, *this)); - } -} - void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only) { // Save old state @@ -2365,7 +2354,6 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig S32 cur_length = getLength(); LLStyleConstSP sp(new LLStyle(highlight_params)); LLTextSegmentPtr segmentp; - segment_vec_t segments; if (underline_on_hover_only || mSkipLinkUnderline) { highlight_params.font.style("NORMAL"); @@ -2374,8 +2362,9 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig } else { - createTextWithEmojiSegment(wide_text, cur_length, sp, segments); + segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this); } + segment_vec_t segments; segments.push_back(segmentp); insertStringNoUndo(cur_length, wide_text, &segments); } @@ -2398,7 +2387,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig } else { - createTextWithEmojiSegment(wide_text, segment_start, sp, segments); + segments.push_back(new LLNormalTextSegment(sp, segment_start, segment_end, *this )); } insertStringNoUndo(getLength(), wide_text, &segments); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 31e9f16110..a047db25b2 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -641,7 +641,6 @@ protected: void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params()); void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false); - void createTextWithEmojiSegment(const LLWString& wide_text, S32 segment_start, LLStyleConstSP style, segment_vec_t& segments); S32 normalizeUri(std::string& uri); protected: -- cgit v1.3 From 3185bdea27b19e155c2ccc03c80624e113d312a6 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 26 Jan 2023 14:45:45 -0800 Subject: DRTVWR-489-emoji: As part of the work to get macOS version of the Viewer working, the flag was introduced to warn (and therefore error out) when a virtual override was not marked with the 'override' keyword. Fixing this up involved a large number of changes and this commit represents just those changes - nothing specially from the DRTVWR-489 viewer --- indra/llappearance/llwearabletype.h | 2 +- indra/llcommon/llcoros.h | 2 +- indra/llcommon/llsingleton.h | 2 +- indra/llinventory/llfoldertype.cpp | 2 +- indra/llinventory/llinventorysettings.cpp | 2 +- indra/llmessage/llexperiencecache.h | 2 +- indra/llmessage/llproxy.h | 2 +- indra/llui/llnotifications.h | 6 +- indra/llui/llspellcheck.h | 2 +- indra/llui/lltextbase.cpp | 21 ---- indra/llui/lltextbase.h | 2 +- indra/llui/lluictrl.h | 2 +- indra/llui/llview.cpp | 4 +- indra/llui/llviewquery.h | 12 +-- indra/newview/llautoreplace.h | 2 +- indra/newview/llchannelmanager.h | 2 +- indra/newview/llchicletbar.h | 4 +- indra/newview/llconversationlog.h | 10 +- indra/newview/llfeaturemanager.h | 2 +- indra/newview/llfriendcard.h | 2 +- indra/newview/llgesturemgr.h | 4 +- indra/newview/llimagefiltersmanager.h | 2 +- indra/newview/llimview.h | 2 +- indra/newview/llmutelist.h | 2 +- indra/newview/llnavigationbar.h | 8 +- indra/newview/lloutfitobserver.h | 2 +- indra/newview/llpaneltopinfobar.h | 6 +- indra/newview/llpathfindingpathtool.h | 18 ++-- indra/newview/llproductinforequest.h | 2 +- indra/newview/llrecentpeople.h | 2 +- indra/newview/llspeakers.h | 4 +- indra/newview/llspeakingindicatormanager.cpp | 2 +- indra/newview/lltoolbrush.h | 20 ++-- indra/newview/lltoolcomp.h | 72 ++++++------- indra/newview/lltooldraganddrop.h | 12 +-- indra/newview/lltoolface.h | 10 +- indra/newview/lltoolfocus.h | 14 +-- indra/newview/lltoolindividual.h | 8 +- indra/newview/lltoolobjpicker.h | 14 +-- indra/newview/lltoolpie.h | 32 +++--- indra/newview/lltoolpipette.h | 8 +- indra/newview/lltoolselectland.h | 16 +-- indra/newview/llversioninfo.h | 2 +- indra/newview/llviewerhelp.h | 10 +- indra/newview/llviewermedia.h | 2 +- indra/newview/llviewermediafocus.h | 16 +-- indra/newview/llviewerparcelaskplay.h | 4 +- indra/newview/llviewerparcelmedia.h | 2 +- indra/newview/llviewerparcelmediaautoplay.h | 2 +- indra/newview/llviewertexturelist.h | 6 +- indra/newview/llvoicechannel.h | 22 ++-- indra/newview/llvoicevivox.h | 146 +++++++++++++-------------- indra/newview/llwearableitemslist.h | 6 +- indra/newview/llwindebug.h | 4 +- 54 files changed, 272 insertions(+), 295 deletions(-) (limited to 'indra/llui') diff --git a/indra/llappearance/llwearabletype.h b/indra/llappearance/llwearabletype.h index 793a33cc87..1fbe19ddd1 100644 --- a/indra/llappearance/llwearabletype.h +++ b/indra/llappearance/llwearabletype.h @@ -37,7 +37,7 @@ class LLWearableType : public LLParamSingleton { LLSINGLETON(LLWearableType, LLTranslationBridge::ptr_t &trans); ~LLWearableType(); - void initSingleton(); + void initSingleton() override; public: enum EType { diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index dbff921f16..a6da94005b 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -92,7 +92,7 @@ class LL_COMMON_API LLCoros: public LLSingleton LLSINGLETON(LLCoros); ~LLCoros(); - void cleanupSingleton(); + void cleanupSingleton() override; public: /// The viewer's use of the term "coroutine" became deeply embedded before /// the industry term "fiber" emerged to distinguish userland threads from diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 51ef514cf7..cbe5ab6406 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -802,7 +802,7 @@ public: private: \ /* implement LLSingleton pure virtual method whose sole purpose */ \ /* is to remind people to use this macro */ \ - virtual void you_must_use_LLSINGLETON_macro() {} \ + virtual void you_must_use_LLSINGLETON_macro() override {} \ friend class LLSingleton; \ DERIVED_CLASS(__VA_ARGS__) diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp index 675da65af2..818a8b5cc3 100644 --- a/indra/llinventory/llfoldertype.cpp +++ b/indra/llinventory/llfoldertype.cpp @@ -60,7 +60,7 @@ class LLFolderDictionary : public LLSingleton, { LLSINGLETON(LLFolderDictionary); protected: - virtual LLFolderType::EType notFound() const + virtual LLFolderType::EType notFound() const override { return LLFolderType::FT_NONE; } diff --git a/indra/llinventory/llinventorysettings.cpp b/indra/llinventory/llinventorysettings.cpp index 81485b3a97..bc604097da 100644 --- a/indra/llinventory/llinventorysettings.cpp +++ b/indra/llinventory/llinventorysettings.cpp @@ -62,7 +62,7 @@ class LLSettingsDictionary : public LLSingleton, { LLSINGLETON(LLSettingsDictionary); - void initSingleton(); + void initSingleton() override; }; LLSettingsDictionary::LLSettingsDictionary() diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h index 1c97133723..8be4c64dfc 100644 --- a/indra/llmessage/llexperiencecache.h +++ b/indra/llmessage/llexperiencecache.h @@ -106,7 +106,7 @@ public: private: virtual ~LLExperienceCache(); - virtual void initSingleton(); + virtual void initSingleton() override; typedef boost::function permissionInvoker_fn; diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h index 25f6977e14..8a64cdbfaa 100644 --- a/indra/llmessage/llproxy.h +++ b/indra/llmessage/llproxy.h @@ -226,7 +226,7 @@ class LLProxy: public LLSingleton LLSINGLETON(LLProxy); LOG_CLASS(LLProxy); - /*virtual*/ void initSingleton(); + /*virtual*/ void initSingleton() override; public: // Static check for enabled status for UDP packets. Call from main thread only. diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 921398a693..4d9a33f1d7 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -913,7 +913,7 @@ public: /* virtual */ LLNotificationPtr add(const std::string& name, const LLSD& substitutions, const LLSD& payload, - LLNotificationFunctorRegistry::ResponseFunctor functor); + LLNotificationFunctorRegistry::ResponseFunctor functor) override; LLNotificationPtr add(const LLNotification::Params& p); void add(const LLNotificationPtr pNotif); @@ -964,8 +964,8 @@ public: bool isVisibleByRules(LLNotificationPtr pNotification); private: - /*virtual*/ void initSingleton(); - /*virtual*/ void cleanupSingleton(); + /*virtual*/ void initSingleton() override; + /*virtual*/ void cleanupSingleton() override; void loadPersistentNotifications(); diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h index 3da5e30955..14f9b44fe4 100644 --- a/indra/llui/llspellcheck.h +++ b/indra/llui/llspellcheck.h @@ -47,7 +47,7 @@ public: protected: void addToDictFile(const std::string& dict_path, const std::string& word); void initHunspell(const std::string& dict_language); - void initSingleton(); + void initSingleton() override; public: typedef std::list dict_list_t; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index b2c0577604..dff4bf9617 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1997,19 +1997,8 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getEditableSegIterContaini LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index) { - static LLPointer index_segment = new LLIndexSegment(); - S32 text_len = 0; - if (!useLabel()) - { - text_len = getLength(); - } - else - { - text_len = mLabel.getWString().length(); - } - // when there are no segments, we return the end iterator, which must be checked by caller if (mSegments.size() <= 1) { return mSegments.begin(); } @@ -2023,16 +2012,6 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i { static LLPointer index_segment = new LLIndexSegment(); - S32 text_len = 0; - if (!useLabel()) - { - text_len = getLength(); - } - else - { - text_len = mLabel.getWString().length(); - } - // when there are no segments, we return the end iterator, which must be checked by caller if (mSegments.size() <= 1) { return mSegments.begin(); } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 7e1f727607..9b3691e404 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -187,7 +187,7 @@ public: LLEmojiTextSegment(const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE); bool canEdit() const override { return false; } - BOOL handleToolTip(S32 x, S32 y, MASK mask); + BOOL handleToolTip(S32 x, S32 y, MASK mask) override; }; // Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment) diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 67dd24341c..d71dc8d859 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -263,7 +263,7 @@ public: class LLTextInputFilter : public LLQueryFilter, public LLSingleton { LLSINGLETON_EMPTY_CTOR(LLTextInputFilter); - /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const + /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override { return filterResult_t(view->isCtrl() && static_cast(view)->acceptsTextInput(), TRUE); } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 74abe54690..2b7f05dcda 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1953,7 +1953,7 @@ private: class SortByTabOrder : public LLQuerySorter, public LLSingleton { LLSINGLETON_EMPTY_CTOR(SortByTabOrder); - /*virtual*/ void sort(LLView * parent, LLView::child_list_t &children) const + /*virtual*/ void sort(LLView * parent, LLView::child_list_t &children) const override { children.sort(CompareByTabOrder(parent->getTabOrder(), parent->getDefaultTabGroup())); } @@ -1977,7 +1977,7 @@ const LLViewQuery & LLView::getTabOrderQuery() class LLFocusRootsFilter : public LLQueryFilter, public LLSingleton { LLSINGLETON_EMPTY_CTOR(LLFocusRootsFilter); - /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const + /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override { return filterResult_t(view->isCtrl() && view->isFocusRoot(), !view->isFocusRoot()); } diff --git a/indra/llui/llviewquery.h b/indra/llui/llviewquery.h index 21bb1be26f..4bc9c4a08e 100644 --- a/indra/llui/llviewquery.h +++ b/indra/llui/llviewquery.h @@ -55,37 +55,37 @@ public: class LLLeavesFilter : public LLQueryFilter, public LLSingleton { LLSINGLETON_EMPTY_CTOR(LLLeavesFilter); - /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; + /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override; }; class LLRootsFilter : public LLQueryFilter, public LLSingleton { LLSINGLETON_EMPTY_CTOR(LLRootsFilter); - /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; + /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override; }; class LLVisibleFilter : public LLQueryFilter, public LLSingleton { LLSINGLETON_EMPTY_CTOR(LLVisibleFilter); - /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; + /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override; }; class LLEnabledFilter : public LLQueryFilter, public LLSingleton { LLSINGLETON_EMPTY_CTOR(LLEnabledFilter); - /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; + /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override; }; class LLTabStopFilter : public LLQueryFilter, public LLSingleton { LLSINGLETON_EMPTY_CTOR(LLTabStopFilter); - /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; + /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override; }; class LLCtrlFilter : public LLQueryFilter, public LLSingleton { LLSINGLETON_EMPTY_CTOR(LLCtrlFilter); - /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; + /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override; }; template diff --git a/indra/newview/llautoreplace.h b/indra/newview/llautoreplace.h index 23cc313646..a1eebf9dcb 100644 --- a/indra/newview/llautoreplace.h +++ b/indra/newview/llautoreplace.h @@ -203,7 +203,7 @@ public: void setSettings(const LLAutoReplaceSettings& settings); private: - /*virtual*/ void initSingleton(); + /*virtual*/ void initSingleton() override; LLAutoReplaceSettings mSettings; ///< configuration information diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index 8abe350196..22ae595d66 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -46,7 +46,7 @@ class LLChannelManager : public LLSingleton LLSINGLETON(LLChannelManager); virtual ~LLChannelManager(); - void cleanupSingleton(); + void cleanupSingleton() override; public: diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index 6c521dc1d5..c295b99962 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -43,11 +43,11 @@ class LLChicletBar public: - BOOL postBuild(); + BOOL postBuild() override; LLChicletPanel* getChicletPanel() { return mChicletPanel; } - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent) override; /** diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 820a5db491..54aeedcf9a 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -125,11 +125,11 @@ public: void removeObserver(LLConversationLogObserver* observer); // LLIMSessionObserver triggers - virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); - virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; // Stub - virtual void sessionRemoved(const LLUUID& session_id){} // Stub - virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}; // Stub - virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){}; // Stub + virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) override; + virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) override {}; // Stub + virtual void sessionRemoved(const LLUUID& session_id) override{} // Stub + virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) override{}; // Stub + virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) override{}; // Stub void notifyObservers(); diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index 42a226cd18..d9269224af 100644 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -101,7 +101,7 @@ class LLFeatureManager : public LLFeatureList, public LLSingleton mFiltersList; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 326e8f22e3..353373f3b4 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -506,7 +506,7 @@ public: static void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction, bool ended_by_agent); private: - void initSingleton(); + void initSingleton() override; void onVoiceChannelChangedInt(const LLUUID &session_id); void onVoiceChannelStateChangedInt(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction, bool ended_by_agent); diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 0d426fbd48..f86c2acd10 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -73,7 +73,7 @@ class LLMuteList : public LLSingleton { LLSINGLETON(LLMuteList); ~LLMuteList(); - /*virtual*/ void cleanupSingleton(); + /*virtual*/ void cleanupSingleton() override; public: // reasons for auto-unmuting a resident enum EAutoReason diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index 11c671294a..4649f5bcb0 100755 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -92,10 +92,10 @@ class LLNavigationBar public: - /*virtual*/ void draw(); - /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL postBuild(); - /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void draw() override; + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL postBuild() override; + /*virtual*/ void setVisible(BOOL visible) override; void handleLoginComplete(); void clearHistoryCache(); diff --git a/indra/newview/lloutfitobserver.h b/indra/newview/lloutfitobserver.h index 77041db68d..77bb3543aa 100644 --- a/indra/newview/lloutfitobserver.h +++ b/indra/newview/lloutfitobserver.h @@ -41,7 +41,7 @@ class LLOutfitObserver: public LLInventoryObserver, public LLSingleton, public: typedef boost::signals2::signal resize_signal_t; - /*virtual*/ BOOL postBuild(); - /*virtual*/ void draw(); + /*virtual*/ BOOL postBuild() override; + /*virtual*/ void draw() override; /** * Updates location and parcel icons on login complete @@ -83,7 +83,7 @@ private: */ void initParcelIcons(); - BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; /** * Handles clicks on the parcel icons. diff --git a/indra/newview/llpathfindingpathtool.h b/indra/newview/llpathfindingpathtool.h index 88cb3a15f8..f98624e30d 100644 --- a/indra/newview/llpathfindingpathtool.h +++ b/indra/newview/llpathfindingpathtool.h @@ -66,17 +66,17 @@ public: typedef boost::signals2::signal path_event_signal_t; typedef boost::signals2::connection path_event_slot_t; - virtual BOOL handleMouseDown(S32 pX, S32 pY, MASK pMask); - virtual BOOL handleMouseUp(S32 pX, S32 pY, MASK pMask); - virtual BOOL handleMiddleMouseDown(S32 pX, S32 pY, MASK pMask); - virtual BOOL handleMiddleMouseUp(S32 pX, S32 pY, MASK pMask); - virtual BOOL handleRightMouseDown(S32 pX, S32 pY, MASK pMask); - virtual BOOL handleRightMouseUp(S32 pX, S32 pY, MASK pMask); - virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + virtual BOOL handleMouseDown(S32 pX, S32 pY, MASK pMask) override; + virtual BOOL handleMouseUp(S32 pX, S32 pY, MASK pMask) override; + virtual BOOL handleMiddleMouseDown(S32 pX, S32 pY, MASK pMask) override; + virtual BOOL handleMiddleMouseUp(S32 pX, S32 pY, MASK pMask) override; + virtual BOOL handleRightMouseDown(S32 pX, S32 pY, MASK pMask) override; + virtual BOOL handleRightMouseUp(S32 pX, S32 pY, MASK pMask) override; + virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override; - virtual BOOL handleHover(S32 pX, S32 pY, MASK pMask); + virtual BOOL handleHover(S32 pX, S32 pY, MASK pMask) override; - virtual BOOL handleKey(KEY pKey, MASK pMask); + virtual BOOL handleKey(KEY pKey, MASK pMask) override; EPathStatus getPathStatus() const; diff --git a/indra/newview/llproductinforequest.h b/indra/newview/llproductinforequest.h index d1036374e8..0b94c39d11 100644 --- a/indra/newview/llproductinforequest.h +++ b/indra/newview/llproductinforequest.h @@ -46,7 +46,7 @@ public: std::string getDescriptionForSku(const std::string& sku); private: - /* virtual */ void initSingleton(); + /* virtual */ void initSingleton() override; void getLandDescriptionsCoro(std::string url); LLSD mSkuDescriptions; diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h index 1b322f2c0a..0c04222a9f 100644 --- a/indra/newview/llrecentpeople.h +++ b/indra/newview/llrecentpeople.h @@ -106,7 +106,7 @@ public: /** * LLSimpleListener interface. */ - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override; void updateAvatarsArrivalTime(uuid_vec_t& uuids); F32 getArrivalTimeByID(const LLUUID& id); diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index ed795b5155..22c9481687 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -338,7 +338,7 @@ class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton @@ -347,7 +347,7 @@ class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton speaker_ids_t; diff --git a/indra/newview/lltoolbrush.h b/indra/newview/lltoolbrush.h index c108d83256..6545ee3611 100644 --- a/indra/newview/lltoolbrush.h +++ b/indra/newview/lltoolbrush.h @@ -49,27 +49,27 @@ class LLToolBrushLand : public LLTool, public LLEditMenuHandler, public LLSingle public: // x,y in window coords, 0,0 = left,bot - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); - virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - virtual void handleSelect(); - virtual void handleDeselect(); + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ) override; + virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ) override; + virtual BOOL handleHover( S32 x, S32 y, MASK mask ) override; + virtual void handleSelect() override; + virtual void handleDeselect() override; // isAlwaysRendered() - return true if this is a tool that should // always be rendered regardless of selection. - virtual BOOL isAlwaysRendered() { return TRUE; } + virtual BOOL isAlwaysRendered() override { return TRUE; } // Draw the area that will be affected. - virtual void render(); + virtual void render() override; // on Idle is where the land modification actually occurs static void onIdle(void* brush_tool); - void onMouseCaptureLost(); + void onMouseCaptureLost() override; void modifyLandInSelectionGlobal(); - virtual void undo(); - virtual BOOL canUndo() const { return TRUE; } + virtual void undo() override; + virtual BOOL canUndo() const override { return TRUE; } protected: void brush( void ); diff --git a/indra/newview/lltoolcomp.h b/indra/newview/lltoolcomp.h index 86506f725e..f539a045b7 100644 --- a/indra/newview/lltoolcomp.h +++ b/indra/newview/lltoolcomp.h @@ -108,11 +108,11 @@ class LLToolCompInspect : public LLToolComposite, public LLSingleton public: // Overridden from LLToolComposite - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - virtual void onMouseCaptureLost(); - virtual void handleSelect(); - virtual void handleDeselect(); - virtual LLTool* getOverrideTool(MASK mask) { return NULL; } + virtual BOOL handleHover(S32 x, S32 y, MASK mask) override; + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override; + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override; + virtual void onMouseCaptureLost() override; + virtual void handleSelect() override; + virtual void handleDeselect() override; + virtual LLTool* getOverrideTool(MASK mask) override { return NULL; } protected: LLToolGun* mGun; diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 4537d73332..8ec027cb0e 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -48,12 +48,12 @@ public: typedef boost::signals2::signal enddrag_signal_t; // overridden from LLTool - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleKey(KEY key, MASK mask); - virtual BOOL handleToolTip(S32 x, S32 y, MASK mask); - virtual void onMouseCaptureLost(); - virtual void handleDeselect(); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + virtual BOOL handleHover(S32 x, S32 y, MASK mask) override; + virtual BOOL handleKey(KEY key, MASK mask) override; + virtual BOOL handleToolTip(S32 x, S32 y, MASK mask) override; + virtual void onMouseCaptureLost() override; + virtual void handleDeselect() override; void setDragStart( S32 x, S32 y ); // In screen space BOOL isOverThreshold( S32 x, S32 y ); // In screen space diff --git a/indra/newview/lltoolface.h b/indra/newview/lltoolface.h index e4b8ae12b8..7c8ff20480 100644 --- a/indra/newview/lltoolface.h +++ b/indra/newview/lltoolface.h @@ -39,11 +39,11 @@ class LLToolFace virtual ~LLToolFace(); public: - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - virtual void handleSelect(); - virtual void handleDeselect(); - virtual void render(); // draw face highlights + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override; + virtual void handleSelect() override; + virtual void handleDeselect() override; + virtual void render() override; // draw face highlights static void pickCallback(const LLPickInfo& pick_info); }; diff --git a/indra/newview/lltoolfocus.h b/indra/newview/lltoolfocus.h index cfc235b6c2..c9dd39ff4b 100644 --- a/indra/newview/lltoolfocus.h +++ b/indra/newview/lltoolfocus.h @@ -38,16 +38,16 @@ class LLToolCamera virtual ~LLToolCamera(); public: - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + virtual BOOL handleHover(S32 x, S32 y, MASK mask) override; - virtual void onMouseCaptureLost(); + virtual void onMouseCaptureLost() override; - virtual void handleSelect(); - virtual void handleDeselect(); + virtual void handleSelect() override; + virtual void handleDeselect() override; - virtual LLTool* getOverrideTool(MASK mask) { return NULL; } + virtual LLTool* getOverrideTool(MASK mask) override { return NULL; } static void pickCallback(const LLPickInfo& pick_info); BOOL mouseSteerMode() { return mMouseSteering; } diff --git a/indra/newview/lltoolindividual.h b/indra/newview/lltoolindividual.h index e7c2060fba..89dd9d9796 100644 --- a/indra/newview/lltoolindividual.h +++ b/indra/newview/lltoolindividual.h @@ -43,11 +43,9 @@ class LLToolIndividual : public LLTool, public LLSingleton virtual ~LLToolIndividual(); public: - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - virtual void handleSelect(); - //virtual void handleDeselect(); - //virtual void render(); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override; + virtual void handleSelect() override; static void pickCallback(const LLPickInfo& pick_info); diff --git a/indra/newview/lltoolobjpicker.h b/indra/newview/lltoolobjpicker.h index 5ad9b67e21..a55cd223de 100644 --- a/indra/newview/lltoolobjpicker.h +++ b/indra/newview/lltoolobjpicker.h @@ -38,16 +38,16 @@ class LLToolObjPicker : public LLTool, public LLSingleton LLSINGLETON(LLToolObjPicker); public: - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + virtual BOOL handleHover(S32 x, S32 y, MASK mask) override; - virtual void handleSelect(); - virtual void handleDeselect(); + virtual void handleSelect() override; + virtual void handleDeselect() override; - virtual void onMouseCaptureLost(); + virtual void onMouseCaptureLost() override; - virtual void setExitCallback(void (*callback)(void *), void *callback_data); + void setExitCallback(void (*callback)(void *), void *callback_data); LLUUID getObjectID() const { return mHitObjectID; } diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index 8f6100e4b4..dca0d12cf6 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -42,26 +42,26 @@ class LLToolPie : public LLTool, public LLSingleton public: // Virtual functions inherited from LLMouseHandler - virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down) override; + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) override; + virtual BOOL handleHover(S32 x, S32 y, MASK mask) override; + virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override; BOOL handleScrollWheelAny(S32 x, S32 y, S32 clicks_x, S32 clicks_y); - virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - virtual BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks); - virtual BOOL handleToolTip(S32 x, S32 y, MASK mask); + virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override; + virtual BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks) override; + virtual BOOL handleToolTip(S32 x, S32 y, MASK mask) override; - virtual void render(); + virtual void render() override; - virtual void stopEditing(); + virtual void stopEditing() override; - virtual void onMouseCaptureLost(); - virtual void handleSelect(); - virtual void handleDeselect(); - virtual LLTool* getOverrideTool(MASK mask); + virtual void onMouseCaptureLost() override; + virtual void handleSelect() override; + virtual void handleDeselect() override; + virtual LLTool* getOverrideTool(MASK mask) override; LLPickInfo& getPick() { return mPick; } U8 getClickAction() { return mClickAction; } diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h index 7575d8ad18..2636811c66 100644 --- a/indra/newview/lltoolpipette.h +++ b/indra/newview/lltoolpipette.h @@ -47,10 +47,10 @@ class LLToolPipette virtual ~LLToolPipette(); public: - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleToolTip(S32 x, S32 y, MASK mask); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + virtual BOOL handleHover(S32 x, S32 y, MASK mask) override; + virtual BOOL handleToolTip(S32 x, S32 y, MASK mask) override; // Note: Don't return connection; use boost::bind + boost::signals2::trackable to disconnect slots typedef boost::signals2::signal signal_t; diff --git a/indra/newview/lltoolselectland.h b/indra/newview/lltoolselectland.h index b5ba72f16d..88bc4e2e3d 100644 --- a/indra/newview/lltoolselectland.h +++ b/indra/newview/lltoolselectland.h @@ -39,15 +39,15 @@ class LLToolSelectLand virtual ~LLToolSelectLand(); public: - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); - /*virtual*/ void render(); // draw the select rectangle - /*virtual*/ BOOL isAlwaysRendered() { return TRUE; } + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override; + /*virtual*/ void render() override; // draw the select rectangle + /*virtual*/ BOOL isAlwaysRendered() override { return TRUE; } - /*virtual*/ void handleSelect(); - /*virtual*/ void handleDeselect(); + /*virtual*/ void handleSelect() override; + /*virtual*/ void handleDeselect() override; protected: BOOL outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y); diff --git a/indra/newview/llversioninfo.h b/indra/newview/llversioninfo.h index 02ff0c094a..37382243f6 100644 --- a/indra/newview/llversioninfo.h +++ b/indra/newview/llversioninfo.h @@ -47,7 +47,7 @@ class LLStoreListener; class LLVersionInfo: public LLSingleton { LLSINGLETON(LLVersionInfo); - void initSingleton(); + void initSingleton() override; public: ~LLVersionInfo(); diff --git a/indra/newview/llviewerhelp.h b/indra/newview/llviewerhelp.h index da50e07a43..bbd20bc07e 100644 --- a/indra/newview/llviewerhelp.h +++ b/indra/newview/llviewerhelp.h @@ -43,21 +43,21 @@ class LLViewerHelp : public LLHelp, public LLSingleton public: /// display the specified help topic in the help viewer - /*virtual*/ void showTopic(const std::string &topic); + /*virtual*/ void showTopic(const std::string &topic) override; - std::string getURL(const std::string& topic); + std::string getURL(const std::string& topic) override; // return topic derived from viewer UI focus, else default topic std::string getTopicFromFocus(); /// return default (fallback) topic name suitable for showTopic() - /*virtual*/ std::string defaultTopic(); + /*virtual*/ std::string defaultTopic() override; // return topic to use before the user logs in - /*virtual*/ std::string preLoginTopic(); + /*virtual*/ std::string preLoginTopic() override; // return topic to use for the top-level help, invoked by F1 - /*virtual*/ std::string f1HelpTopic(); + /*virtual*/ std::string f1HelpTopic() override; }; #endif // header guard diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index f1f42afd81..ad7c4bcefa 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -74,7 +74,7 @@ class LLViewerMedia: public LLSingleton { LLSINGLETON(LLViewerMedia); ~LLViewerMedia(); - void initSingleton(); + void initSingleton() override; LOG_CLASS(LLViewerMedia); public: diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h index effd08a559..2310e4dbfc 100644 --- a/indra/newview/llviewermediafocus.h +++ b/indra/newview/llviewermediafocus.h @@ -54,10 +54,10 @@ public: void setHoverFace(LLPointer objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero); void clearHover(); - /*virtual*/ bool getFocus(); - /*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); - /*virtual*/ BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent); - /*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); + bool getFocus(); + /*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override; + /*virtual*/ BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent) override; + /*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) override; BOOL handleScrollWheel(const LLVector2& texture_coords, S32 clicks_x, S32 clicks_y); BOOL handleScrollWheel(S32 x, S32 y, S32 clicks_x, S32 clicks_y); @@ -92,12 +92,12 @@ public: LLUUID getControlsMediaID(); // The MoaP object wants keyup and keydown events. Overridden to return true. - virtual bool wantsKeyUpKeyDown() const; - virtual bool wantsReturnKey() const; + virtual bool wantsKeyUpKeyDown() const override; + virtual bool wantsReturnKey() const override; protected: - /*virtual*/ void onFocusReceived(); - /*virtual*/ void onFocusLost(); + /*virtual*/ void onFocusReceived() override; + /*virtual*/ void onFocusLost() override; private: diff --git a/indra/newview/llviewerparcelaskplay.h b/indra/newview/llviewerparcelaskplay.h index dc711917d2..56faddae66 100644 --- a/indra/newview/llviewerparcelaskplay.h +++ b/indra/newview/llviewerparcelaskplay.h @@ -34,8 +34,8 @@ class LLViewerParcelAskPlay : public LLSingleton { LLSINGLETON(LLViewerParcelAskPlay); ~LLViewerParcelAskPlay(); - void initSingleton(); - void cleanupSingleton(); + void initSingleton() override; + void cleanupSingleton() override; public: // functor expects functor(region_id, parcel_id, url, play/stop) typedef boost::function ask_callback; diff --git a/indra/newview/llviewerparcelmedia.h b/indra/newview/llviewerparcelmedia.h index 779a65bdf8..790b2b71fc 100644 --- a/indra/newview/llviewerparcelmedia.h +++ b/indra/newview/llviewerparcelmedia.h @@ -74,7 +74,7 @@ public: void sendMediaNavigateMessage(const std::string& url); // inherited from LLViewerMediaObserver - virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override; private: void processParcelMediaCommandMessage(LLMessageSystem *msg); diff --git a/indra/newview/llviewerparcelmediaautoplay.h b/indra/newview/llviewerparcelmediaautoplay.h index d71fd4c075..e83085dee0 100644 --- a/indra/newview/llviewerparcelmediaautoplay.h +++ b/indra/newview/llviewerparcelmediaautoplay.h @@ -35,7 +35,7 @@ class LLViewerParcelMediaAutoPlay : LLEventTimer, public LLSingleton getUIImageByID(const LLUUID& id, S32 priority); - /*virtual*/ LLPointer getUIImage(const std::string& name, S32 priority); - void cleanUp(); + /*virtual*/ LLPointer getUIImageByID(const LLUUID& id, S32 priority) override; + /*virtual*/ LLPointer getUIImage(const std::string& name, S32 priority) override; + void cleanUp() override; bool initFromFile(); diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index 309c3eebdd..e68bfbe1ff 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -170,12 +170,12 @@ class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton &participants); - virtual bool isParticipant(const LLUUID& speaker_id); + virtual void getParticipantList(std::set &participants) override; + virtual bool isParticipant(const LLUUID& speaker_id) override; // Send a text message to the specified user, initiating the session if necessary. // virtual BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message) const {return false;}; // close any existing text IM session with the specified user - virtual void endUserIMSession(const LLUUID &uuid); + virtual void endUserIMSession(const LLUUID &uuid) override; // Returns true if calling back the session URI after the session has closed is possible. // Currently this will be false only for PSTN P2P calls. // NOTE: this will return true if the session can't be found. - virtual BOOL isSessionCallBackPossible(const LLUUID &session_id); + virtual BOOL isSessionCallBackPossible(const LLUUID &session_id) override; // Returns true if the session can accepte text IM's. // Currently this will be false only for PSTN P2P calls. // NOTE: this will return true if the session can't be found. - virtual BOOL isSessionTextIMPossible(const LLUUID &session_id); + virtual BOOL isSessionTextIMPossible(const LLUUID &session_id) override; //////////////////////////// @@ -134,21 +134,21 @@ public: //@{ // returns true iff the user is currently in a proximal (local spatial) channel. // Note that gestures should only fire if this returns true. - virtual bool inProximalChannel(); + virtual bool inProximalChannel() override; virtual void setNonSpatialChannel(const std::string &uri, - const std::string &credentials); + const std::string &credentials) override; virtual bool setSpatialChannel(const std::string &uri, - const std::string &credentials); + const std::string &credentials) override; - virtual void leaveNonSpatialChannel(); + virtual void leaveNonSpatialChannel() override; - virtual void leaveChannel(void); + virtual void leaveChannel(void) override; // Returns the URI of the current channel, or an empty string if not currently in a channel. // NOTE that it will return an empty string if it's in the process of joining a channel. - virtual std::string getCurrentChannel(); + virtual std::string getCurrentChannel() override; //@} @@ -156,59 +156,59 @@ public: /// @name invitations //@{ // start a voice channel with the specified user - virtual void callUser(const LLUUID &uuid); - virtual bool isValidChannel(std::string &channelHandle); - virtual bool answerInvite(std::string &channelHandle); - virtual void declineInvite(std::string &channelHandle); + virtual void callUser(const LLUUID &uuid) override; + virtual bool isValidChannel(std::string &channelHandle) override; + virtual bool answerInvite(std::string &channelHandle) override; + virtual void declineInvite(std::string &channelHandle) override; //@} ///////////////////////// /// @name Volume/gain //@{ - virtual void setVoiceVolume(F32 volume); - virtual void setMicGain(F32 volume); + virtual void setVoiceVolume(F32 volume) override; + virtual void setMicGain(F32 volume) override; //@} ///////////////////////// /// @name enable disable voice and features //@{ - virtual bool voiceEnabled(); - virtual void setVoiceEnabled(bool enabled); - virtual BOOL lipSyncEnabled(); - virtual void setLipSyncEnabled(BOOL enabled); - virtual void setMuteMic(bool muted); // Set the mute state of the local mic. + virtual bool voiceEnabled() override; + virtual void setVoiceEnabled(bool enabled) override; + virtual BOOL lipSyncEnabled() override; + virtual void setLipSyncEnabled(BOOL enabled) override; + virtual void setMuteMic(bool muted) override; // Set the mute state of the local mic. //@} ////////////////////////// /// @name nearby speaker accessors //@{ - virtual BOOL getVoiceEnabled(const LLUUID& id); // true if we've received data for this avatar - virtual std::string getDisplayName(const LLUUID& id); - virtual BOOL isParticipantAvatar(const LLUUID &id); - virtual BOOL getIsSpeaking(const LLUUID& id); - virtual BOOL getIsModeratorMuted(const LLUUID& id); - virtual F32 getCurrentPower(const LLUUID& id); // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is... - virtual BOOL getOnMuteList(const LLUUID& id); - virtual F32 getUserVolume(const LLUUID& id); - virtual void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal) + virtual BOOL getVoiceEnabled(const LLUUID& id) override; // true if we've received data for this avatar + virtual std::string getDisplayName(const LLUUID& id) override; + virtual BOOL isParticipantAvatar(const LLUUID &id) override; + virtual BOOL getIsSpeaking(const LLUUID& id) override; + virtual BOOL getIsModeratorMuted(const LLUUID& id) override; + virtual F32 getCurrentPower(const LLUUID& id) override; // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is... + virtual BOOL getOnMuteList(const LLUUID& id) override; + virtual F32 getUserVolume(const LLUUID& id) override; + virtual void setUserVolume(const LLUUID& id, F32 volume) override; // set's volume for specified agent, from 0-1 (where .5 is nominal) //@} // authorize the user virtual void userAuthorized(const std::string& user_id, - const LLUUID &agentID); + const LLUUID &agentID) override; ////////////////////////////// /// @name Status notification //@{ - virtual void addObserver(LLVoiceClientStatusObserver* observer); - virtual void removeObserver(LLVoiceClientStatusObserver* observer); - virtual void addObserver(LLFriendObserver* observer); - virtual void removeObserver(LLFriendObserver* observer); - virtual void addObserver(LLVoiceClientParticipantObserver* observer); - virtual void removeObserver(LLVoiceClientParticipantObserver* observer); + virtual void addObserver(LLVoiceClientStatusObserver* observer) override; + virtual void removeObserver(LLVoiceClientStatusObserver* observer) override; + virtual void addObserver(LLFriendObserver* observer) override; + virtual void removeObserver(LLFriendObserver* observer) override; + virtual void addObserver(LLVoiceClientParticipantObserver* observer) override; + virtual void removeObserver(LLVoiceClientParticipantObserver* observer) override; //@} - virtual std::string sipURIFromID(const LLUUID &id); + virtual std::string sipURIFromID(const LLUUID &id) override; //@} /// @name LLVoiceEffectInterface virtual implementations @@ -218,32 +218,32 @@ public: ////////////////////////// /// @name Accessors //@{ - virtual bool setVoiceEffect(const LLUUID& id); - virtual const LLUUID getVoiceEffect(); - virtual LLSD getVoiceEffectProperties(const LLUUID& id); + virtual bool setVoiceEffect(const LLUUID& id) override; + virtual const LLUUID getVoiceEffect() override; + virtual LLSD getVoiceEffectProperties(const LLUUID& id) override; - virtual void refreshVoiceEffectLists(bool clear_lists); - virtual const voice_effect_list_t& getVoiceEffectList() const; - virtual const voice_effect_list_t& getVoiceEffectTemplateList() const; + virtual void refreshVoiceEffectLists(bool clear_lists) override; + virtual const voice_effect_list_t& getVoiceEffectList() const override; + virtual const voice_effect_list_t& getVoiceEffectTemplateList() const override; //@} ////////////////////////////// /// @name Status notification //@{ - virtual void addObserver(LLVoiceEffectObserver* observer); - virtual void removeObserver(LLVoiceEffectObserver* observer); + virtual void addObserver(LLVoiceEffectObserver* observer) override; + virtual void removeObserver(LLVoiceEffectObserver* observer) override; //@} ////////////////////////////// /// @name Effect preview buffer //@{ - virtual void enablePreviewBuffer(bool enable); - virtual void recordPreviewBuffer(); - virtual void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null); - virtual void stopPreviewBuffer(); + virtual void enablePreviewBuffer(bool enable) override; + virtual void recordPreviewBuffer() override; + virtual void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null) override; + virtual void stopPreviewBuffer() override; - virtual bool isPreviewRecording(); - virtual bool isPreviewPlaying(); + virtual bool isPreviewRecording() override; + virtual bool isPreviewPlaying() override; //@} //@} @@ -754,7 +754,7 @@ private: std::string getAudioSessionURI(); std::string getAudioSessionHandle(); - void setHidden(bool hidden); //virtual + void setHidden(bool hidden) override; //virtual void sendPositionAndVolumeUpdate(void); void sendCaptureAndRenderDevices(); diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index ba8488b237..602e8f0711 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -413,7 +413,7 @@ public: { LLSINGLETON(ContextMenu); public: - /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); + /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y) override; void show(LLView* spawning_view, LLWearableType::EType w_type, S32 x, S32 y); @@ -426,7 +426,7 @@ public: MASK_UNKNOWN = 0x10, }; - /* virtual */ LLContextMenu* createMenu(); + /* virtual */ LLContextMenu* createMenu() override; void updateItemsVisibility(LLContextMenu* menu); void updateItemsLabels(LLContextMenu* menu); static void setMenuItemVisible(LLContextMenu* menu, const std::string& name, bool val); @@ -456,7 +456,7 @@ public: virtual ~LLWearableItemsList(); - /*virtual*/ LLPanel* createNewItem(LLViewerInventoryItem* item); + /*virtual*/ LLPanel* createNewItem(LLViewerInventoryItem* item) override; void updateList(const LLUUID& category_id); diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h index 524adba652..31dbfb8ffd 100644 --- a/indra/newview/llwindebug.h +++ b/indra/newview/llwindebug.h @@ -40,9 +40,9 @@ class LLWinDebug: { LLSINGLETON_EMPTY_CTOR(LLWinDebug); public: - void initSingleton(); + void initSingleton() override; static void generateMinidump(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL); - void cleanupSingleton(); + void cleanupSingleton() override; private: static void writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename); }; -- cgit v1.3 From a804b98e4ed127ce1a11f639babb82574f2e5204 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 26 Jan 2023 17:03:58 -0800 Subject: DRTVWR-489-emoji: A couple of tabs slipped into this file and our new no-tabs coding policy caught it and failed the build --- indra/llui/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 44c61dcdbc..4fc3836248 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -53,8 +53,8 @@ set(llui_SOURCE_FILES lldockcontrol.cpp lldraghandle.cpp lleditmenuhandler.cpp - llemojidictionary.cpp - llemojihelper.cpp + llemojidictionary.cpp + llemojihelper.cpp llf32uictrl.cpp llfiltereditor.cpp llflashtimer.cpp @@ -165,8 +165,8 @@ set(llui_HEADER_FILES lldockablefloater.h lldockcontrol.h lleditmenuhandler.h - llemojidictionary.h - llemojihelper.h + llemojidictionary.h + llemojihelper.h llf32uictrl.h llfiltereditor.h llflashtimer.h -- cgit v1.3 From ff7ebf08922293c1623b7bdb8c9923c14fc9db48 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Fri, 14 Apr 2023 07:44:56 +0200 Subject: SL-19575 Create emoji gallery access icon --- indra/llui/llemojidictionary.h | 2 + indra/llui/llemojihelper.cpp | 10 +- indra/llui/llemojihelper.h | 6 +- indra/llui/llscrolllistctrl.cpp | 2 +- indra/llui/lltexteditor.cpp | 22 ++-- indra/llui/lltexteditor.h | 3 +- indra/newview/CMakeLists.txt | 2 + indra/newview/llfloateremojipicker.cpp | 143 +++++++++++++++++++++ indra/newview/llfloateremojipicker.h | 59 +++++++++ indra/newview/llfloaterimsessiontab.cpp | 30 ++++- indra/newview/llfloaterimsessiontab.h | 4 + indra/newview/llviewerfloaterreg.cpp | 20 +-- .../default/textures/icons/emoji_picker_icon.png | Bin 0 -> 316 bytes indra/newview/skins/default/textures/textures.xml | 5 +- .../skins/default/xui/en/floater_emoji_picker.xml | 39 ++++++ .../skins/default/xui/en/floater_im_session.xml | 14 +- indra/newview/skins/default/xui/en/strings.xml | 10 +- 17 files changed, 335 insertions(+), 36 deletions(-) create mode 100644 indra/newview/llfloateremojipicker.cpp create mode 100644 indra/newview/llfloateremojipicker.h create mode 100644 indra/newview/skins/default/textures/icons/emoji_picker_icon.png create mode 100644 indra/newview/skins/default/xui/en/floater_emoji_picker.xml (limited to 'indra/llui') diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h index 46a61f1cd7..adc22ced58 100644 --- a/indra/llui/llemojidictionary.h +++ b/indra/llui/llemojidictionary.h @@ -61,6 +61,8 @@ public: const LLEmojiDescriptor* getDescriptorFromShortCode(const std::string& short_code) const; std::string getNameFromEmoji(llwchar ch) const; + const std::map& getEmoji2Descr() const { return mEmoji2Descr; } + private: void addEmoji(LLEmojiDescriptor&& descr); diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index 1e4c19a183..fb660a9e5b 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -82,12 +82,12 @@ bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S return isShortCode; } -void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function cb) +void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function cb) { // Commit immediately if the user already typed a full shortcode if (const auto* emojiDescrp = LLEmojiDictionary::instance().getDescriptorFromShortCode(short_code)) { - cb(LLWString(1, emojiDescrp->Character)); + cb(emojiDescrp->Character); hideHelper(); return; } @@ -96,7 +96,7 @@ void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, c { LLFloater* pHelperFloater = LLFloaterReg::getInstance(DEFAULT_EMOJI_HELPER_FLOATER); mHelperHandle = pHelperFloater->getHandle(); - mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())); }, std::placeholders::_2)); + mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())[0]); }, std::placeholders::_2)); } setHostCtrl(hostctrl_p); mEmojiCommitCb = cb; @@ -135,11 +135,11 @@ bool LLEmojiHelper::handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask) return mHelperHandle.get()->handleKey(key, mask, true); } -void LLEmojiHelper::onCommitEmoji(const LLWString& wstr) +void LLEmojiHelper::onCommitEmoji(llwchar emoji) { if (!mHostHandle.isDead() && mEmojiCommitCb) { - mEmojiCommitCb(wstr); + mEmojiCommitCb(emoji); } } diff --git a/indra/llui/llemojihelper.h b/indra/llui/llemojihelper.h index 63f5c640c9..58f68d12a4 100644 --- a/indra/llui/llemojihelper.h +++ b/indra/llui/llemojihelper.h @@ -44,12 +44,12 @@ public: std::string getToolTip(llwchar ch) const; bool isActive(const LLUICtrl* ctrl_p) const; static bool isCursorInEmojiCode(const LLWString& wtext, S32 cursor_pos, S32* short_code_pos_p = nullptr); - void showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function commit_cb); + void showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function commit_cb); void hideHelper(const LLUICtrl* ctrl_p = nullptr); // Eventing bool handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask); - void onCommitEmoji(const LLWString& wstr); + void onCommitEmoji(llwchar emoji); protected: LLUICtrl* getHostCtrl() const { return mHostHandle.get(); } @@ -60,5 +60,5 @@ private: LLHandle mHelperHandle; boost::signals2::connection mHostCtrlFocusLostConn; boost::signals2::connection mHelperCommitConn; - std::function mEmojiCommitCb; + std::function mEmojiCommitCb; }; diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 219667f766..2a6e8a6b76 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -411,7 +411,7 @@ void LLScrollListCtrl::clearRows() LLScrollListItem* LLScrollListCtrl::getFirstSelected() const { item_list::const_iterator iter; - for(iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; if (item->getSelected()) diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index a85ac2a5a3..95d8b666ab 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -680,18 +680,24 @@ void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_p endSelection(); } -void LLTextEditor::handleEmojiCommit(const LLWString& wstr) +void LLTextEditor::insertEmoji(llwchar emoji) { - LLWString wtext(getWText()); S32 shortCodePos; - if (LLEmojiHelper::isCursorInEmojiCode(wtext, mCursorPos, &shortCodePos)) + auto styleParams = LLStyle::Params(); + styleParams.font = LLFontGL::getFontEmoji(); + auto segment = new LLEmojiTextSegment(new LLStyle(styleParams), mCursorPos, mCursorPos + 1, *this); + insert(mCursorPos, LLWString(1, emoji), false, segment); + setCursorPos(mCursorPos + 1); +} + +void LLTextEditor::handleEmojiCommit(llwchar emoji) +{ + S32 shortCodePos; + if (LLEmojiHelper::isCursorInEmojiCode(getWText(), mCursorPos, &shortCodePos)) { remove(shortCodePos, mCursorPos - shortCodePos, true); + setCursorPos(shortCodePos); - auto styleParams = LLStyle::Params(); - styleParams.font = LLFontGL::getFontEmoji(); - insert(shortCodePos, wstr, false, new LLEmojiTextSegment(new LLStyle(styleParams), shortCodePos, shortCodePos + wstr.size(), *this)); - - setCursorPos(shortCodePos + 1); + insertEmoji(emoji); } } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index dabd0460c6..f830732cb8 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -92,7 +92,8 @@ public: static S32 spacesPerTab(); - void handleEmojiCommit(const LLWString& wstr); + void insertEmoji(llwchar emoji); + void handleEmojiCommit(llwchar emoji); // mousehandler overrides virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ab0c60a402..1f8b937965 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -205,6 +205,7 @@ set(viewer_SOURCE_FILES llfloaterdisplayname.cpp llfloatereditenvironmentbase.cpp llfloatereditextdaycycle.cpp + llfloateremojipicker.cpp llfloaterenvironmentadjust.cpp llfloaterevent.cpp llfloaterexperiencepicker.cpp @@ -845,6 +846,7 @@ set(viewer_HEADER_FILES llfloaterdisplayname.h llfloatereditenvironmentbase.h llfloatereditextdaycycle.h + llfloateremojipicker.h llfloaterenvironmentadjust.h llfloaterevent.h llfloaterexperiencepicker.h diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp new file mode 100644 index 0000000000..c828a95a59 --- /dev/null +++ b/indra/newview/llfloateremojipicker.cpp @@ -0,0 +1,143 @@ +/** + * @file llfloateremojipicker.cpp + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloateremojipicker.h" + +#include "llfloaterreg.h" +#include "llscrolllistctrl.h" +#include "llscrolllistitem.h" +#include "llemojidictionary.h" + +class LLEmojiScrollListItem : public LLScrollListItem +{ +public: + LLEmojiScrollListItem(const llwchar emoji, const LLScrollListItem::Params& params) + : LLScrollListItem(params) + , mEmoji(emoji) + { + } + + llwchar getEmoji() const { return mEmoji; } + + virtual void draw(const LLRect& rect, + const LLColor4& fg_color, + const LLColor4& hover_color, // highlight/hover selection of whole item or cell + const LLColor4& select_color, // highlight/hover selection of whole item or cell + const LLColor4& highlight_color, // highlights contents of cells (ex: text) + S32 column_padding) override + { + LLScrollListItem::draw(rect, fg_color, hover_color, select_color, highlight_color, column_padding); + + S32 width = getColumn(0)->getWidth(); + LLFontGL::getFontEmoji()->render(LLWString(1, mEmoji), 0, rect.mLeft + width / 2, rect.getCenterY(), LLColor4::white, + LLFontGL::HCENTER, LLFontGL::VCENTER, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW_SOFT, 1, S32_MAX, nullptr, false, true); + } + +private: + llwchar mEmoji; +}; + +LLFloaterEmojiPicker* LLFloaterEmojiPicker::getInstance() +{ + LLFloaterEmojiPicker* floater = LLFloaterReg::getTypedInstance("emoji_picker"); + if (!floater) + LL_WARNS() << "Cannot instantiate emoji picker" << LL_ENDL; + return floater; +} + +LLFloaterEmojiPicker* LLFloaterEmojiPicker::showInstance(select_callback_t callback) +{ + LLFloaterEmojiPicker* floater = getInstance(); + if (LLFloaterEmojiPicker* floater = getInstance()) + floater->show(callback); + return floater; +} + +void LLFloaterEmojiPicker::show(select_callback_t callback) +{ + mSelectCallback = callback; + openFloater(mKey); + setFocus(TRUE); +} + +LLFloaterEmojiPicker::LLFloaterEmojiPicker(const LLSD& key) +: LLFloater(key) +{ +} + +BOOL LLFloaterEmojiPicker::postBuild() +{ + if (mEmojis = getChild("Emojis")) + { + mEmojis->setDoubleClickCallback(boost::bind(&LLFloaterEmojiPicker::onSelect, this)); + + mEmojis->clearRows(); + + const std::map& emoji2Descr = LLEmojiDictionary::instance().getEmoji2Descr(); + for (const std::pair& it : emoji2Descr) + { + LLScrollListItem::Params params; + params.columns.add().column("name").value(it.second->Name); + mEmojis->addRow(new LLEmojiScrollListItem(it.first, params), params); + } + } + + return TRUE; +} + +LLFloaterEmojiPicker::~LLFloaterEmojiPicker() +{ + gFocusMgr.releaseFocusIfNeeded( this ); +} + +void LLFloaterEmojiPicker::onSelect() +{ + if (mEmojis && mSelectCallback) + { + if (LLEmojiScrollListItem* item = dynamic_cast(mEmojis->getFirstSelected())) + { + mSelectCallback(item->getEmoji()); + } + } +} + +// virtual +BOOL LLFloaterEmojiPicker::handleKeyHere(KEY key, MASK mask) +{ + if (key == KEY_RETURN && mask == MASK_NONE) + { + onSelect(); + return TRUE; + } + else if (key == KEY_ESCAPE && mask == MASK_NONE) + { + closeFloater(); + return TRUE; + } + + return LLFloater::handleKeyHere(key, mask); +} diff --git a/indra/newview/llfloateremojipicker.h b/indra/newview/llfloateremojipicker.h new file mode 100644 index 0000000000..9b442064d0 --- /dev/null +++ b/indra/newview/llfloateremojipicker.h @@ -0,0 +1,59 @@ +/** + * @file llfloateremojipicker.h + * @brief Header file for llfloateremojipicker + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLFLOATEREMOJIPICKER_H +#define LLFLOATEREMOJIPICKER_H + +#include "llfloater.h" + +class LLFloaterEmojiPicker : public LLFloater +{ +public: + // The callback function will be called with an emoji char. + typedef boost::function select_callback_t; + + // Call this to select an emoji. + static LLFloaterEmojiPicker* getInstance(); + static LLFloaterEmojiPicker* showInstance(select_callback_t callback); + + LLFloaterEmojiPicker(const LLSD& key); + virtual ~LLFloaterEmojiPicker(); + + virtual BOOL postBuild(); + + void show(select_callback_t callback); + +private: + void onSelect(); + + virtual BOOL handleKeyHere(KEY key, MASK mask); + + class LLScrollListCtrl* mEmojis; + select_callback_t mSelectCallback; + std::string mEmojiName; +}; + +#endif diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 78271369d2..3d9751dd35 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -40,6 +40,7 @@ #include "llchicletbar.h" #include "lldraghandle.h" #include "llfloaterreg.h" +#include "llfloateremojipicker.h" #include "llfloaterimsession.h" #include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container #include "lllayoutstack.h" @@ -250,10 +251,13 @@ BOOL LLFloaterIMSessionTab::postBuild() mTearOffBtn = getChild("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this)); + mEmojiBtn = getChild("emoji_panel_btn"); + mEmojiBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onEmojiPanelBtnClicked, this)); + mGearBtn = getChild("gear_btn"); mAddBtn = getChild("add_btn"); mVoiceButton = getChild("voice_call_btn"); - + mParticipantListPanel = getChild("speakers_list_panel"); mRightPartPanel = getChild("right_part_holder"); @@ -424,6 +428,30 @@ void LLFloaterIMSessionTab::onInputEditorClicked() gToolBarView->flashCommand(LLCommandId("chat"), false); } +void LLFloaterIMSessionTab::onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self) +{ + if (LLFloaterEmojiPicker* picker = LLFloaterEmojiPicker::getInstance()) + { + if (!picker->isShown()) + { + picker->show(boost::bind(&LLFloaterIMSessionTab::onEmojiSelected, self, _1)); + if (LLFloater* root_floater = gFloaterView->getParentFloater(self)) + { + root_floater->addDependentFloater(picker); + } + } + else + { + picker->closeFloater(); + } + } +} + +void LLFloaterIMSessionTab::onEmojiSelected(llwchar emoji) +{ + mInputEditor->insertEmoji(emoji); +} + std::string LLFloaterIMSessionTab::appendTime() { time_t utc_time; diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 9f00917647..cd5065420d 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -181,6 +181,7 @@ protected: LLButton* mExpandCollapseLineBtn; LLButton* mExpandCollapseBtn; LLButton* mTearOffBtn; + LLButton* mEmojiBtn; LLButton* mCloseBtn; LLButton* mGearBtn; LLButton* mAddBtn; @@ -206,6 +207,9 @@ private: void onInputEditorClicked(); + static void onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self); + void onEmojiSelected(llwchar emoji); + bool checkIfTornOff(); bool mIsHostAttached; bool mHasVisibleBeenInitialized; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 1c1aa9ea47..483b22adc8 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -65,6 +65,7 @@ #include "llfloaterdestinations.h" #include "llfloaterdisplayname.h" #include "llfloatereditextdaycycle.h" +#include "llfloateremojipicker.h" #include "llfloaterenvironmentadjust.h" #include "llfloaterexperienceprofile.h" #include "llfloaterexperiences.h" @@ -329,7 +330,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("camera_presets", "floater_camera_presets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater); - LLFloaterReg::add("classified", "floater_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("classified", "floater_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("add_landmark", "floater_create_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); @@ -337,19 +338,20 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("delete_pref_preset", "floater_delete_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", &LLFloaterReg::build); + LLFloaterReg::add("emoji_picker", "floater_emoji_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("env_adjust_snapshot", "floater_adjust_environment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("env_adjust_snapshot", "floater_adjust_environment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("env_edit_extdaycycle", "floater_edit_ext_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("my_environments", "floater_my_environments.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("env_edit_extdaycycle", "floater_edit_ext_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("my_environments", "floater_my_environments.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("experience_profile", "floater_experienceprofile.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("experience_search", "floater_experience_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/skins/default/textures/icons/emoji_picker_icon.png b/indra/newview/skins/default/textures/icons/emoji_picker_icon.png new file mode 100644 index 0000000000..668dcaf193 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/emoji_picker_icon.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 1f2c0867c4..f69f1df71a 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -205,6 +205,7 @@ with the same filename but different name + @@ -212,7 +213,7 @@ with the same filename but different name - + @@ -328,7 +329,7 @@ with the same filename but different name - + diff --git a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml new file mode 100644 index 0000000000..a3e504cc31 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index da84fbeea6..1592352d1b 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -297,8 +297,20 @@ tab_group="3" bottom="-8" left_pad="5" - right="-5" + right="-30" wrap="true" /> +