summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llemojidictionary.cpp132
-rw-r--r--indra/llui/llemojidictionary.h1
-rw-r--r--indra/llui/llemojihelper.cpp7
-rw-r--r--indra/llui/llemojihelper.h4
-rw-r--r--indra/llui/llfloater.cpp28
-rw-r--r--indra/llui/llfloater.h5
-rw-r--r--indra/llui/lltexteditor.cpp24
-rw-r--r--indra/llui/lltexteditor.h1
-rw-r--r--indra/llui/lluictrl.cpp25
9 files changed, 132 insertions, 95 deletions
diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp
index e29f3436cf..f16c38a11a 100644
--- a/indra/llui/llemojidictionary.cpp
+++ b/indra/llui/llemojidictionary.cpp
@@ -41,9 +41,9 @@
static const std::string SKINNED_EMOJI_FILENAME("emoji_characters.xml");
static const std::string SKINNED_CATEGORY_FILENAME("emoji_categories.xml");
static const std::string COMMON_GROUP_FILENAME("emoji_groups.xml");
-static const std::string GROUP_NAME_ALL("all");
-static const std::string GROUP_NAME_OTHERS("others");
static const std::string GROUP_NAME_SKIP("skip");
+// https://www.compart.com/en/unicode/U+1F302
+static const S32 GROUP_OTHERS_IMAGE_INDEX = 0x1F302;
// ============================================================================
// Helper functions
@@ -143,68 +143,76 @@ LLWString LLEmojiDictionary::findMatchingEmojis(const std::string& needle) const
return result;
}
-void LLEmojiDictionary::findByShortCode(std::vector<LLEmojiSearchResult>& result, const std::string& needle) const
+// static
+bool LLEmojiDictionary::searchInShortCode(std::size_t& begin, std::size_t& end, const std::string& shortCode, const std::string& needle)
+{
+ begin = 0;
+ end = 1;
+ std::size_t index = 1;
+ // Search for begin
+ char d = tolower(needle[index++]);
+ while (end < shortCode.size())
+ {
+ char s = tolower(shortCode[end++]);
+ if (s == d)
+ {
+ begin = end - 1;
+ break;
+ }
+ }
+ if (!begin)
+ return false;
+ // Search for end
+ d = tolower(needle[index++]);
+ if (!d)
+ return true;
+ while (end < shortCode.size() && index <= needle.size())
+ {
+ char s = tolower(shortCode[end++]);
+ if (s == d)
+ {
+ if (index == needle.size())
+ return true;
+ d = tolower(needle[index++]);
+ continue;
+ }
+ switch (s)
+ {
+ case L'-':
+ case L'_':
+ case L'+':
+ continue;
+ }
+ break;
+ }
+ return false;
+}
+
+void LLEmojiDictionary::findByShortCode(
+ std::vector<LLEmojiSearchResult>& result,
+ const std::string& needle
+) const
{
result.clear();
if (needle.empty() || needle.front() != ':')
return;
- auto search = [needle](std::size_t& begin, std::size_t& end, const std::string& shortCode) -> bool
+ std::map<llwchar, std::vector<LLEmojiSearchResult>> results;
+
+ for (const LLEmojiDescriptor& d : mEmojis)
+ {
+ if (!d.ShortCodes.empty())
{
- begin = 0;
- end = 1;
- std::size_t index = 1;
- // Search for begin
- char d = tolower(needle[index++]);
- while (end < shortCode.size())
+ const std::string& shortCode = d.ShortCodes.front();
+ if (shortCode.size() >= needle.size() && shortCode.front() == needle.front())
{
- char s = tolower(shortCode[end++]);
- if (s == d)
+ std::size_t begin, end;
+ if (searchInShortCode(begin, end, shortCode, needle))
{
- begin = end - 1;
- break;
+ results[begin].emplace_back(d.Character, shortCode, begin, end);
}
}
- if (!begin)
- return false;
- // Search for end
- d = tolower(needle[index++]);
- while (end < shortCode.size() && index <= needle.size())
- {
- char s = tolower(shortCode[end++]);
- if (s == d)
- {
- if (index == needle.size())
- return true;
- d = tolower(needle[index++]);
- continue;
- }
- switch (s)
- {
- case L'-':
- case L'_':
- case L'+':
- continue;
- }
- break;
- }
- return false;
- };
-
- std::map<std::size_t, std::vector<LLEmojiSearchResult>> results;
-
- for (const LLEmojiDescriptor& d : mEmojis)
- {
- if (d.ShortCodes.empty())
- continue;
- const std::string& shortCode = d.ShortCodes.front();
- if (shortCode.size() < needle.size() || shortCode.front() != needle.front())
- continue;
- std::size_t begin, end;
- if (search(begin, end, shortCode))
- {
- results[begin].emplace_back(d.Character, shortCode, begin, end);
}
}
@@ -312,27 +320,13 @@ void LLEmojiDictionary::loadGroups()
}
mGroups.clear();
- // Add group "all"
- mGroups.emplace_back();
- // https://www.compart.com/en/unicode/U+1F50D
- mGroups.front().Character = 0x1F50D;
- // https://www.compart.com/en/unicode/U+1F302
- llwchar iconOthers = 0x1F302;
// Register all groups
for (LLSD::array_const_iterator it = data.beginArray(), end = data.endArray(); it != end; ++it)
{
const LLSD& sd = *it;
const std::string& name = sd["Name"].asStringRef();
- if (name == GROUP_NAME_ALL)
- {
- mGroups.front().Character = loadIcon(sd);
- }
- else if (name == GROUP_NAME_OTHERS)
- {
- iconOthers = loadIcon(sd);
- }
- else if (name == GROUP_NAME_SKIP)
+ if (name == GROUP_NAME_SKIP)
{
mSkipCategories = loadCategories(sd);
translateCategories(mSkipCategories);
@@ -355,7 +349,7 @@ void LLEmojiDictionary::loadGroups()
// Add group "others"
mGroups.emplace_back();
- mGroups.back().Character = iconOthers;
+ mGroups.back().Character = GROUP_OTHERS_IMAGE_INDEX;
}
void LLEmojiDictionary::loadEmojis()
diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h
index 66b564b70a..4af376df64 100644
--- a/indra/llui/llemojidictionary.h
+++ b/indra/llui/llemojidictionary.h
@@ -89,6 +89,7 @@ public:
static void initClass();
LLWString findMatchingEmojis(const std::string& needle) const;
+ static bool searchInShortCode(std::size_t& begin, std::size_t& end, const std::string& shortCode, const std::string& needle);
void findByShortCode(std::vector<LLEmojiSearchResult>& result, const std::string& needle) const;
const LLEmojiDescriptor* getDescriptorFromEmoji(llwchar emoji) const;
const LLEmojiDescriptor* getDescriptorFromShortCode(const std::string& short_code) const;
diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp
index 9411f7cac5..89e6ddf987 100644
--- a/indra/llui/llemojihelper.cpp
+++ b/indra/llui/llemojihelper.cpp
@@ -36,7 +36,7 @@
// Constants
//
-constexpr char DEFAULT_EMOJI_HELPER_FLOATER[] = "emoji_complete";
+constexpr char DEFAULT_EMOJI_HELPER_FLOATER[] = "emoji_picker";
constexpr S32 HELPER_FLOATER_OFFSET_X = 0;
constexpr S32 HELPER_FLOATER_OFFSET_Y = 0;
@@ -117,9 +117,10 @@ void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, c
pHelperFloater->openFloater(LLSD().with("hint", short_code));
}
-void LLEmojiHelper::hideHelper(const LLUICtrl* ctrl_p)
+void LLEmojiHelper::hideHelper(const LLUICtrl* ctrl_p, bool strict)
{
- if (ctrl_p && !isActive(ctrl_p))
+ mIsHideDisabled &= !strict;
+ if (mIsHideDisabled || (ctrl_p && !isActive(ctrl_p)))
{
return;
}
diff --git a/indra/llui/llemojihelper.h b/indra/llui/llemojihelper.h
index 58f68d12a4..e826ff93e6 100644
--- a/indra/llui/llemojihelper.h
+++ b/indra/llui/llemojihelper.h
@@ -45,7 +45,8 @@ 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<void(llwchar)> commit_cb);
- void hideHelper(const LLUICtrl* ctrl_p = nullptr);
+ void hideHelper(const LLUICtrl* ctrl_p = nullptr, bool strict = false);
+ void setIsHideDisabled(bool disabled) { mIsHideDisabled = disabled; };
// Eventing
bool handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask);
@@ -61,4 +62,5 @@ private:
boost::signals2::connection mHostCtrlFocusLostConn;
boost::signals2::connection mHelperCommitConn;
std::function<void(llwchar)> mEmojiCommitCb;
+ bool mIsHideDisabled;
};
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 23d3a66631..31019f6c33 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -182,6 +182,7 @@ LLFloater::Params::Params()
save_visibility("save_visibility", false),
can_dock("can_dock", false),
show_title("show_title", true),
+ auto_close("auto_close", false),
positioning("positioning", LLFloaterEnums::POSITIONING_RELATIVE),
header_height("header_height", 0),
legacy_header_height("legacy_header_height", 0),
@@ -254,6 +255,7 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
mCanClose(p.can_close),
mDragOnLeft(p.can_drag_on_left),
mResizable(p.can_resize),
+ mAutoClose(p.auto_close),
mPositioning(p.positioning),
mMinWidth(p.min_width),
mMinHeight(p.min_height),
@@ -681,7 +683,7 @@ void LLFloater::openFloater(const LLSD& key)
if (getHost() != NULL)
{
getHost()->setMinimized(FALSE);
- getHost()->setVisibleAndFrontmost(mAutoFocus);
+ getHost()->setVisibleAndFrontmost(mAutoFocus && !getIsChrome());
getHost()->showFloater(this);
}
else
@@ -693,7 +695,7 @@ void LLFloater::openFloater(const LLSD& key)
}
applyControlsAndPosition(floater_to_stack);
setMinimized(FALSE);
- setVisibleAndFrontmost(mAutoFocus);
+ setVisibleAndFrontmost(mAutoFocus && !getIsChrome());
}
mOpenSignal(this, key);
@@ -1551,7 +1553,7 @@ void LLFloater::addDependentFloater(LLFloater* floaterp, BOOL reposition, BOOL r
if (floaterp->isFrontmost())
{
// make sure to bring self and sibling floaters to front
- gFloaterView->bringToFront(floaterp);
+ gFloaterView->bringToFront(floaterp, floaterp->getAutoFocus() && !getIsChrome());
}
}
@@ -1696,6 +1698,7 @@ BOOL LLFloater::handleDoubleClick(S32 x, S32 y, MASK mask)
return was_minimized || LLPanel::handleDoubleClick(x, y, mask);
}
+// virtual
void LLFloater::bringToFront( S32 x, S32 y )
{
if (getVisible() && pointInView(x, y))
@@ -1710,12 +1713,20 @@ void LLFloater::bringToFront( S32 x, S32 y )
LLFloaterView* parent = dynamic_cast<LLFloaterView*>( getParent() );
if (parent)
{
- parent->bringToFront( this );
+ parent->bringToFront(this, !getIsChrome());
}
}
}
}
+// virtual
+void LLFloater::goneFromFront()
+{
+ if (mAutoClose)
+ {
+ closeFloater();
+ }
+}
// virtual
void LLFloater::setVisibleAndFrontmost(BOOL take_focus,const LLSD& key)
@@ -2561,6 +2572,11 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus, BOOL restore
return;
}
+ if (mFrontChild && !mFrontChild->isDead())
+ {
+ mFrontChild->goneFromFront();
+ }
+
mFrontChild = child;
// *TODO: make this respect floater's mAutoFocus value, instead of
@@ -3060,6 +3076,9 @@ LLFloater *LLFloaterView::getBackmost() const
void LLFloaterView::syncFloaterTabOrder()
{
+ if (mFrontChild && !mFrontChild->isDead() && mFrontChild->getIsChrome())
+ return;
+
// look for a visible modal dialog, starting from first
LLModalDialog* modal_dialog = NULL;
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
@@ -3307,6 +3326,7 @@ void LLFloater::initFromParams(const LLFloater::Params& p)
mDefaultRelativeY = p.rel_y;
mPositioning = p.positioning;
+ mAutoClose = p.auto_close;
mSaveRect = p.save_rect;
if (p.save_visibility)
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 860a6f9e2a..5f4e1a2cad 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -163,7 +163,8 @@ public:
save_visibility,
save_dock_state,
can_dock,
- show_title;
+ show_title,
+ auto_close;
Optional<LLFloaterEnums::EOpenPositioning> positioning;
@@ -390,6 +391,7 @@ protected:
void setInstanceName(const std::string& name);
virtual void bringToFront(S32 x, S32 y);
+ virtual void goneFromFront();
void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized
const LLRect& getExpandedRect() const { return mExpandedRect; }
@@ -488,6 +490,7 @@ private:
bool mFocusStealsFrontmost = true; // FALSE if we don't want the currently focused floater to cover this floater without user interaction
BOOL mDragOnLeft;
BOOL mResizable;
+ BOOL mAutoClose;
LLFloaterEnums::EOpenPositioning mPositioning;
LLCoordFloater mPosition;
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 3910be1443..092739a538 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -508,7 +508,8 @@ void LLTextEditor::getSegmentsInRange(LLTextEditor::segment_vec_t& segments_out,
}
}
-void LLTextEditor::setShowEmojiHelper(bool show) {
+void LLTextEditor::setShowEmojiHelper(bool show)
+{
if (!mShowEmojiHelper)
{
LLEmojiHelper::instance().hideHelper(this);
@@ -1192,6 +1193,16 @@ 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)
@@ -1207,6 +1218,10 @@ void LLTextEditor::tryToShowEmojiHelper()
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)
@@ -1911,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();
}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 7a96e17899..521405ec25 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -206,6 +206,7 @@ public:
void setShowContextMenu(bool show) { mShowContextMenu = show; }
bool getShowContextMenu() const { return mShowContextMenu; }
+ void showEmojiHelper();
void setShowEmojiHelper(bool show);
bool getShowEmojiHelper() const { return mShowEmojiHelper; }
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 21afcae7c3..7eb9ae69fb 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -768,25 +768,20 @@ void LLUICtrl::setIsChrome(BOOL is_chrome)
// virtual
BOOL LLUICtrl::getIsChrome() const
-{
+{
+ if (mIsChrome)
+ return TRUE;
+
LLView* parent_ctrl = getParent();
- while(parent_ctrl)
+ while (parent_ctrl)
{
- if(parent_ctrl->isCtrl())
- {
- break;
- }
+ if (parent_ctrl->isCtrl())
+ return ((LLUICtrl*)parent_ctrl)->getIsChrome();
+
parent_ctrl = parent_ctrl->getParent();
}
-
- if(parent_ctrl)
- {
- return mIsChrome || ((LLUICtrl*)parent_ctrl)->getIsChrome();
- }
- else
- {
- return mIsChrome ;
- }
+
+ return FALSE;
}