summaryrefslogtreecommitdiff
path: root/indra/llui/lltexteditor.cpp
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-03-12 16:52:30 +0100
committerAnsariel <ansariel.hiller@phoenixviewer.com>2024-03-12 16:52:30 +0100
commiteb1ed3896fd82d4f115b2ef6ba742315ad32cc27 (patch)
tree110015e1703b331715fbf7fb1a01639c74c47e62 /indra/llui/lltexteditor.cpp
parent748c0eb50d87a3f8895b25791409ce5e2e4926c4 (diff)
parentafc943acbc2bb79e2e1aa5d5eaf448e01b6c2b00 (diff)
Merge branch 'main' of https://github.com/secondlife/viewer into DRTVWR-600-maint-A
# Conflicts: # autobuild.xml # indra/llrender/llfontbitmapcache.cpp # indra/llrender/llfontbitmapcache.h # indra/llrender/llfontfreetype.cpp # indra/llrender/llfontfreetype.h # indra/llrender/llfontgl.cpp # indra/llrender/llfontgl.h # indra/llui/llbutton.h # indra/llui/llfloater.cpp # indra/llui/llfloater.h # indra/llui/llfolderviewitem.cpp # indra/llui/lllineeditor.cpp # indra/llui/lllineeditor.h # indra/llui/llscrollcontainer.cpp # indra/llui/llscrollingpanellist.cpp # indra/llui/llscrollingpanellist.h # indra/llui/llscrolllistctrl.h # indra/llui/lltextbase.cpp # indra/llui/lltextbase.h # indra/llui/lltexteditor.cpp # indra/llui/lltexteditor.h # indra/llui/lluictrl.cpp # indra/llui/llview.cpp # indra/llui/llview.h # indra/newview/llchicletbar.h # indra/newview/llconversationlog.h # indra/newview/llfloaterimsessiontab.cpp # indra/newview/llfloaterimsessiontab.h # indra/newview/llfloateruipreview.cpp # indra/newview/llnavigationbar.h # indra/newview/llpaneltopinfobar.h # indra/newview/llpathfindingpathtool.h # indra/newview/lltextureview.cpp # indra/newview/lltoolbrush.h # indra/newview/lltoolcomp.h # indra/newview/lltooldraganddrop.h # indra/newview/lltoolface.h # indra/newview/lltoolfocus.h # indra/newview/lltoolindividual.h # indra/newview/lltoolobjpicker.h # indra/newview/lltoolpie.h # indra/newview/lltoolpipette.h # indra/newview/lltoolselectland.h # indra/newview/llviewermediafocus.h # indra/newview/llviewerparcelmediaautoplay.h # indra/newview/llviewerwindow.cpp # indra/newview/llvoicechannel.h # indra/newview/llvoicevivox.h # indra/newview/llworldmapview.cpp
Diffstat (limited to 'indra/llui/lltexteditor.cpp')
-rw-r--r--indra/llui/lltexteditor.cpp112
1 files changed, 103 insertions, 9 deletions
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 2250ed5cb3..ee6ddf553e 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");
@@ -258,6 +260,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mTabsToNextField(p.ignore_tab),
mPrevalidateFunc(p.prevalidate_callback()),
mShowContextMenu(p.show_context_menu),
+ mShowEmojiHelper(p.show_emoji_helper),
mEnableTooltipPaste(p.enable_tooltip_paste),
mPassDelete(false),
mKeepSelectionOnReturn(false)
@@ -505,6 +508,16 @@ 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())
@@ -668,6 +681,28 @@ void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_p
endSelection();
}
+void LLTextEditor::insertEmoji(llwchar emoji)
+{
+ LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL;
+ 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);
+
+ insertEmoji(emoji);
+ }
+}
+
bool LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
{
bool handled = false;
@@ -934,6 +969,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) )
{
@@ -983,7 +1024,7 @@ S32 LLTextEditor::remove(S32 pos, S32 length, bool group_with_next_op)
// store text segments
getSegmentsInRange(segments_to_remove, pos, pos + length, false);
- if(pos <= end_pos)
+ if (pos <= end_pos)
{
removedChar = execute( new TextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) );
}
@@ -1007,11 +1048,12 @@ S32 LLTextEditor::overwriteChar(S32 pos, llwchar wc)
// a pseudo-tab (up to for spaces in a row)
void LLTextEditor::removeCharOrTab()
{
- if( !getEnabled() )
+ if (!getEnabled())
{
return;
}
- if( mCursorPos > 0 )
+
+ if (mCursorPos > 0)
{
S32 chars_to_remove = 1;
@@ -1023,14 +1065,14 @@ void LLTextEditor::removeCharOrTab()
if (offset > 0)
{
chars_to_remove = offset % SPACES_PER_TAB;
- if( chars_to_remove == 0 )
+ if (chars_to_remove == 0)
{
chars_to_remove = SPACES_PER_TAB;
}
- for( S32 i = 0; i < chars_to_remove; i++ )
+ for (S32 i = 0; i < chars_to_remove; i++)
{
- if (text[ mCursorPos - i - 1] != ' ')
+ if (text[mCursorPos - i - 1] != ' ')
{
// Fewer than a full tab's worth of spaces, so
// just delete a single character.
@@ -1044,8 +1086,10 @@ void LLTextEditor::removeCharOrTab()
for (S32 i = 0; i < chars_to_remove; i++)
{
setCursorPos(mCursorPos - 1);
- remove( mCursorPos, 1, false );
+ remove(mCursorPos, 1, false);
}
+
+ tryToShowEmojiHelper();
}
else
{
@@ -1056,7 +1100,7 @@ void LLTextEditor::removeCharOrTab()
// Remove a single character from the text
S32 LLTextEditor::removeChar(S32 pos)
{
- return remove( pos, 1, false );
+ return remove(pos, 1, false);
}
void LLTextEditor::removeChar()
@@ -1065,10 +1109,12 @@ void LLTextEditor::removeChar()
{
return;
}
+
if (mCursorPos > 0)
{
setCursorPos(mCursorPos - 1);
removeChar(mCursorPos);
+ tryToShowEmojiHelper();
}
else
{
@@ -1127,6 +1173,7 @@ void LLTextEditor::addChar(llwchar wc)
}
setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
+ tryToShowEmojiHelper();
if (!mReadOnly && mAutoreplaceCallback != NULL)
{
@@ -1146,6 +1193,37 @@ void LLTextEditor::addChar(llwchar wc)
}
}
+void LLTextEditor::showEmojiHelper()
+{
+ if (mReadOnly || !mShowEmojiHelper)
+ return;
+
+ const LLRect cursorRect(getLocalRectFromDocIndex(mCursorPos));
+ auto cb = [this](llwchar emoji) { insertEmoji(emoji); };
+ LLEmojiHelper::instance().showHelper(this, cursorRect.mLeft, cursorRect.mTop, LLStringUtil::null, cb);
+}
+
+void LLTextEditor::tryToShowEmojiHelper()
+{
+ if (mReadOnly || !mShowEmojiHelper)
+ return;
+
+ S32 shortCodePos;
+ LLWString wtext(getWText());
+ if (LLEmojiHelper::isCursorInEmojiCode(wtext, mCursorPos, &shortCodePos))
+ {
+ const LLRect cursorRect(getLocalRectFromDocIndex(shortCodePos));
+ const LLWString wpart(wtext.substr(shortCodePos, mCursorPos - shortCodePos));
+ const std::string part(wstring_to_utf8str(wpart));
+ auto cb = [this](llwchar emoji) { handleEmojiCommit(emoji); };
+ LLEmojiHelper::instance().showHelper(this, cursorRect.mLeft, cursorRect.mTop, part, cb);
+ }
+ else
+ {
+ LLEmojiHelper::instance().hideHelper();
+ }
+}
+
void LLTextEditor::addLineBreakChar(bool group_together)
{
if( !getEnabled() )
@@ -1778,6 +1856,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)
@@ -1819,6 +1902,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;
@@ -1837,7 +1926,12 @@ bool LLTextEditor::handleUnicodeCharHere(llwchar uni_char)
// Handle most keys only if the text editor is writeable.
if( !mReadOnly )
{
- if( mAutoIndent && '}' == uni_char )
+ if (mShowEmojiHelper && uni_char < 0x80 && LLEmojiHelper::instance().handleKey(this, (KEY)uni_char, MASK_NONE))
+ {
+ return true;
+ }
+
+ if( mAutoIndent && '}' == uni_char )
{
unindentLineBeforeCloseBrace();
}