summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/CMakeLists.txt2
-rw-r--r--indra/llui/llfocusmgr.cpp6
-rw-r--r--indra/llui/llfocusmgr.h1
-rw-r--r--indra/llui/lllineeditor.cpp49
-rw-r--r--indra/llui/lllineeditor.h2
-rw-r--r--indra/llui/lltexteditor.cpp106
-rw-r--r--indra/llui/lltexteditor.h4
-rw-r--r--indra/llui/llui.cpp5
-rw-r--r--indra/llui/llview.cpp19
-rw-r--r--indra/llui/llview.h2
10 files changed, 196 insertions, 0 deletions
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index a0314cb5f2..5991a5b35e 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -270,6 +270,8 @@ target_link_libraries(llui
llcommon
)
+include(LibraryInstall)
+
# Add tests
if(LL_TESTS)
include(LLAddBuildTest)
diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp
index 0d7c98294f..4f3d2328aa 100644
--- a/indra/llui/llfocusmgr.cpp
+++ b/indra/llui/llfocusmgr.cpp
@@ -59,6 +59,12 @@ bool LLFocusableElement::handleUnicodeChar(llwchar uni_char, bool called_from_pa
}
// virtual
+bool LLFocusableElement::handleUnicodeString(char *uni_str, bool editing, bool called_from_parent)
+{
+ return FALSE;
+}
+
+// virtual
bool LLFocusableElement::wantsKeyUpKeyDown() const
{
return false;
diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h
index 1fa0ac137e..1ca6f50354 100644
--- a/indra/llui/llfocusmgr.h
+++ b/indra/llui/llfocusmgr.h
@@ -59,6 +59,7 @@ public:
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);
+ virtual bool handleUnicodeString(char *uni_str, bool editing, bool called_from_parent);
/**
* If true this LLFocusableElement wants to receive KEYUP and KEYDOWN messages
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 66b274c33f..1f2aed48cc 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -1050,6 +1050,25 @@ void LLLineEditor::addChar(const llwchar uni_char)
getWindow()->hideCursorUntilMouseMove();
}
+void LLLineEditor::addString(char *s, bool editing)
+{
+ if (hasSelection())
+ deleteSelection();
+ else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) {
+ if (!prevalidateInput(mText.getWString()
+ .substr(getCursor(), 1)))
+ return;
+ mText.erase(getCursor(), 1);
+ } else if (editing) {
+ mText.clear();
+ setCursor(0);
+ }
+ mText.insert(getCursor(), utf8str_to_wstring(s));
+ if (editing) setCursor(strlen(s));
+ else setCursor(getCursor() + 1);
+ getWindow()->hideCursorUntilMouseMove();
+}
+
// Extends the selection box to the new cursor position
void LLLineEditor::extendSelection( S32 new_cursor_pos )
{
@@ -1720,6 +1739,36 @@ bool LLLineEditor::handleUnicodeCharHere(llwchar uni_char)
return handled;
}
+bool LLLineEditor::handleUnicodeStringHere(char *uni_str, bool editing)
+{
+ auto handled = FALSE;
+
+ if ((gFocusMgr.getKeyboardFocus() == this)
+ && getVisible() && !mReadOnly) {
+ handled = TRUE;
+ LLLineEditorRollback rollback(this);
+
+ addString(uni_str, editing);
+
+ mKeystrokeTimer.reset();
+ deselect();
+ auto need_to_rollback = mPrevalidator
+ && !mPrevalidator.validate(mText.getWString());
+
+ if (need_to_rollback) {
+ rollback.doRollback(this);
+ LLUI::getInstance()->reportBadKeystroke();
+ mPrevalidator.showLastErrorUsingTimeout();
+ }
+
+ if (!need_to_rollback && handled) {
+ onKeystroke();
+ mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY);
+ }
+ }
+
+ return handled;
+}
bool LLLineEditor::canDoDelete() const
{
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index 12fe800acb..47ff321b54 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -134,6 +134,7 @@ public:
/*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask) override;
/*virtual*/ bool handleKeyHere(KEY key, MASK mask) override;
/*virtual*/ bool handleUnicodeCharHere(llwchar uni_char) override;
+ /*virtual*/ bool handleUnicodeStringHere(char *uni_str, bool editing) override;
/*virtual*/ void onMouseCaptureLost() override;
// LLEditMenuHandler overrides
@@ -301,6 +302,7 @@ public:
void removeChar();
void addChar(const llwchar c);
+ void addString(char *s, bool editing);
void setCursorAtLocalPos(S32 local_mouse_x);
S32 findPixelNearestPos(S32 cursor_offset = 0) const;
S32 calcCursorPos(S32 mouse_x);
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 3537c764b9..cbbb164cb2 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -167,6 +167,50 @@ private:
};
///////////////////////////////////////////////////////////////////
+class LLTextEditor::TextCmdAddString : public LLTextBase::TextCmd
+{
+public:
+ TextCmdAddString(S32 pos, bool group_with_next, char *str,
+ LLTextSegmentPtr segment) :
+ TextCmd(pos, group_with_next, segment),
+ mWString(utf8str_to_wstring(str)),
+ mBlockExtensions(FALSE)
+ {
+ }
+ virtual void blockExtensions()
+ {
+ mBlockExtensions = TRUE;
+ }
+ virtual bool canExtend(S32 pos) const
+ {
+ if (!mSegments.empty()) return FALSE;
+
+ return !mBlockExtensions
+ && (pos == getPosition() + (S32)mWString.length());
+ }
+ virtual bool execute(LLTextBase* editor, S32* delta)
+ {
+ *delta = insert(editor, getPosition(), mWString);
+ LLWStringUtil::truncate(mWString, *delta);
+ return (*delta != 0);
+ }
+ virtual S32 undo(LLTextBase* editor)
+ {
+ remove(editor, getPosition(), mWString.length());
+ return getPosition();
+ }
+ virtual S32 redo(LLTextBase* editor)
+ {
+ insert(editor, getPosition(), mWString);
+ return getPosition() + mWString.length();
+ }
+
+private:
+ LLWString mWString;
+ bool mBlockExtensions;
+};
+
+///////////////////////////////////////////////////////////////////
class LLTextEditor::TextCmdOverwriteChar : public LLTextBase::TextCmd
{
@@ -1164,6 +1208,18 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc)
return execute(new TextCmdAddChar(pos, false, wc, LLTextSegmentPtr()));
}
+S32 LLTextEditor::addString(S32 pos, char *str)
+{
+ if ((wstring_utf8_length(getWText()) + strlen(str))
+ > mMaxTextByteLength) {
+ make_ui_sound("UISndBadKeystroke");
+ return 0;
+ }
+
+ return execute(new TextCmdAddString(pos, FALSE, str,
+ LLTextSegmentPtr()));
+}
+
void LLTextEditor::addChar(llwchar wc)
{
if (!getEnabled())
@@ -1201,6 +1257,38 @@ void LLTextEditor::addChar(llwchar wc)
}
}
+void LLTextEditor::addString(char *str, bool editing)
+{
+ if (!getEnabled())
+ return;
+ if (hasSelection())
+ deleteSelection(TRUE);
+ else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
+ removeChar(mCursorPos);
+ else if (editing) {
+ clear();
+ setCursorPos(0);
+ }
+
+ setCursorPos(mCursorPos + addString(mCursorPos, str));
+
+ if (!mReadOnly && mAutoreplaceCallback != NULL) {
+ S32 replacement_start;
+ S32 replacement_length;
+ LLWString replacement_string;
+ S32 new_cursor_pos = mCursorPos;
+ mAutoreplaceCallback(replacement_start, replacement_length,
+ replacement_string, new_cursor_pos, getWText());
+
+ if (replacement_length > 0 || !replacement_string.empty()) {
+ remove(replacement_start, replacement_length, true);
+ insert(replacement_start, replacement_string, false,
+ LLTextSegmentPtr());
+ setCursorPos(new_cursor_pos);
+ }
+ }
+}
+
void LLTextEditor::showEmojiHelper()
{
if (mReadOnly || !mShowEmojiHelper)
@@ -1972,6 +2060,24 @@ bool LLTextEditor::handleUnicodeCharHere(llwchar uni_char)
return handled;
}
+bool LLTextEditor::handleUnicodeStringHere(char *uni_str, bool editing)
+{
+ auto handled = FALSE;
+
+ if (!mReadOnly) {
+ addString(uni_str, editing);
+ getWindow()->hideCursorUntilMouseMove();
+ handled = TRUE;
+ }
+
+ if (handled) {
+ resetCursorBlink();
+ deselect();
+ onKeyStroke();
+ }
+
+ return handled;
+}
// virtual
bool LLTextEditor::canDoDelete() const
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index e9e7070414..b46b3b595b 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -105,6 +105,7 @@ public:
virtual bool handleKeyHere(KEY key, MASK mask );
virtual bool handleUnicodeCharHere(llwchar uni_char);
+ virtual bool handleUnicodeStringHere(char *uni_str, bool editing);
virtual void onMouseCaptureLost();
@@ -249,6 +250,8 @@ protected:
// Undoable operations
void addChar(llwchar c); // at mCursorPos
S32 addChar(S32 pos, llwchar wc);
+ void addString(char *s, bool editing);
+ S32 addString(S32 pos, char *str);
void addLineBreakChar(bool group_together = false);
S32 overwriteChar(S32 pos, llwchar wc);
void removeChar();
@@ -312,6 +315,7 @@ private:
// Concrete TextCmd sub-classes used by the LLTextEditor base class
class TextCmdInsert;
class TextCmdAddChar;
+ class TextCmdAddString;
class TextCmdOverwriteChar;
class TextCmdRemove;
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index e36dae3955..e7dea79eaa 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -231,6 +231,11 @@ void LLUI::getMousePositionScreen(S32 *x, S32 *y)
LLCoordGL cursor_pos_gl(cursor_pos_window.convert());
*x = ll_round((F32)cursor_pos_gl.mX / getScaleFactor().mV[VX]);
*y = ll_round((F32)cursor_pos_gl.mY / getScaleFactor().mV[VY]);
+#if defined(LL_SDL)
+ *x = *x * LLView::getWindow()->getSystemUISize();
+ *y = *y * LLView::getWindow()->getSystemUISize();
+#endif
+
}
void LLUI::setMousePositionLocal(const LLView* viewp, S32 x, S32 y)
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 7d6c937b85..f2a1e16aad 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -1080,12 +1080,31 @@ bool LLView::handleUnicodeChar(llwchar uni_char, bool called_from_parent)
return handled;
}
+bool LLView::handleUnicodeString(char *uni_str, bool editing, bool called_from_parent)
+{
+ auto handled = FALSE;
+
+ if (getVisible() && getEnabled() && !handled) {
+ handled = handleUnicodeStringHere(uni_str, editing);
+ if (handled && LLView::sDebugKeys)
+ LL_INFOS() << "Unicode key handled by " << getName() << LL_ENDL;
+ }
+
+ if (!handled && !called_from_parent && mParentView)
+ handled = mParentView->handleUnicodeString(uni_str, editing, FALSE);
+
+ return handled;
+}
bool LLView::handleUnicodeCharHere(llwchar uni_char )
{
return false;
}
+bool LLView::handleUnicodeStringHere(char *uni_str, bool editing)
+{
+ return FALSE;
+}
bool LLView::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
EDragAndDropType cargo_type, void* cargo_data,
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 710ec3d05e..876bfafaa3 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -385,6 +385,7 @@ public:
/* 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);
+ /* virtual */ bool handleUnicodeString(char *uni_str, bool editing, bool called_from_parent);
virtual bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
EDragAndDropType cargo_type,
@@ -518,6 +519,7 @@ public:
virtual bool handleKeyHere(KEY key, MASK mask);
virtual bool handleKeyUpHere(KEY key, MASK mask);
virtual bool handleUnicodeCharHere(llwchar uni_char);
+ virtual bool handleUnicodeStringHere(char *uni_str, bool editing);
virtual void handleReshape(const LLRect& rect, bool by_user);
virtual void dirtyRect();