SL-20416 Avoid of taking focus by EmojiPicker

master
Alexander Gavriliuk 2024-01-22 06:40:41 +01:00 committed by Guru
parent ae91ae43a5
commit f6ceafee5b
15 changed files with 863 additions and 686 deletions

View File

@ -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
{
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++]);
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;
std::map<llwchar, 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))
if (!d.ShortCodes.empty())
{
results[begin].emplace_back(d.Character, shortCode, begin, end);
const std::string& shortCode = d.ShortCodes.front();
if (shortCode.size() >= needle.size() && shortCode.front() == needle.front())
{
std::size_t begin, end;
if (searchInShortCode(begin, end, shortCode, needle))
{
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()

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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)

View File

@ -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;

View File

@ -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();
}

View File

@ -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; }

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,10 @@
#include "llfloater.h"
class LLEmojiGridRow;
class LLEmojiGridIcon;
struct LLEmojiDescriptor;
struct LLEmojiSearchResult;
class LLFloaterEmojiPicker : public LLFloater
{
@ -40,36 +43,40 @@ public:
typedef boost::function<void (llwchar)> pick_callback_t;
typedef boost::function<void ()> close_callback_t;
// Call this to select an emoji.
static LLFloaterEmojiPicker* getInstance();
static LLFloaterEmojiPicker* showInstance(pick_callback_t pick_callback = nullptr, close_callback_t close_callback = nullptr);
LLFloaterEmojiPicker(const LLSD& key);
virtual ~LLFloaterEmojiPicker();
virtual BOOL postBuild() override;
virtual void dirtyRect() override;
virtual void goneFromFront() override;
void show(pick_callback_t pick_callback = nullptr, close_callback_t close_callback = nullptr);
virtual void closeFloater(bool app_quitting = false) override;
void hideFloater() const;
static std::list<llwchar>& getRecentlyUsed();
static void onEmojiUsed(llwchar emoji);
static void onRecentlyUsedChanged();
static void loadState();
static void saveState();
private:
void initialize();
void fillGroups();
void moveGroups();
void showPreview(bool show);
void fillCategoryRecentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats);
void fillCategoryFrequentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats);
void fillGroupEmojis(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats, U32 index);
void createGroupButton(LLButton::Params& params, const LLRect& rect, llwchar emoji);
void resizeGroupButtons();
void selectEmojiGroup(U32 index);
void fillEmojis(bool fromResize = false);
void fillEmojisCategory(const std::vector<LLEmojiSearchResult>& emojis,
const std::string& category, const LLPanel::Params& row_panel_params, const LLUICtrl::Params& row_list_params,
const LLPanel::Params& icon_params, const LLRect& icon_rect, S32 max_icons, const LLColor4& bg);
void createEmojiIcon(const LLEmojiSearchResult& emoji,
const std::string& category, const LLPanel::Params& row_panel_params, const LLUICtrl::Params& row_list_params,
const LLPanel::Params& icon_params, const LLRect& icon_rect, S32 max_icons, const LLColor4& bg,
LLEmojiGridRow*& row, int& icon_index);
void showPreview(bool show);
void onGroupButtonClick(LLUICtrl* ctrl);
void onFilterChanged();
void onGridMouseEnter();
void onGridMouseLeave();
void onGroupButtonMouseEnter(LLUICtrl* ctrl);
void onGroupButtonMouseLeave(LLUICtrl* ctrl);
void onEmojiMouseEnter(LLUICtrl* ctrl);
@ -77,40 +84,37 @@ private:
void onEmojiMouseDown(LLUICtrl* ctrl);
void onEmojiMouseUp(LLUICtrl* ctrl);
bool enterArrowMode();
void exitArrowMode();
void selectFocusedIcon();
bool moveFocusedIconUp();
bool moveFocusedIconDown();
bool moveFocusedIconLeft();
bool moveFocusedIconRight();
bool moveFocusedIconPrev();
bool moveFocusedIconNext();
void selectGridIcon(LLUICtrl* ctrl);
void unselectGridIcon(LLUICtrl* ctrl);
void selectGridIcon(LLEmojiGridIcon* icon);
void unselectGridIcon(LLEmojiGridIcon* icon);
void onOpen(const LLSD& key) override;
virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override;
virtual BOOL handleKeyHere(KEY key, MASK mask) override;
class LLPanel* mGroups { nullptr };
class LLPanel* mBadge { nullptr };
class LLFilterEditor* mFilter { nullptr };
class LLScrollContainer* mEmojiScroll { nullptr };
class LLScrollingPanelList* mEmojiGrid { nullptr };
class LLEmojiPreviewPanel* mPreview { nullptr };
class LLTextBox* mDummy { nullptr };
pick_callback_t mEmojiPickCallback;
close_callback_t mFloaterCloseCallback;
std::vector<S32> mFilteredEmojiGroups;
std::vector<std::map<std::string, std::vector<LLEmojiSearchResult>>> mFilteredEmojis;
std::vector<class LLButton*> mGroupButtons;
S32 mRecentBadgeWidth { 0 };
S32 mRecentGridWidth { 0 };
std::string mHint;
std::string mFilterPattern;
U32 mSelectedGroupIndex { 0 };
S32 mRecentMaxIcons { 0 };
S32 mFocusedIconRow { 0 };
S32 mFocusedIconCol { 0 };
LLUICtrl* mFocusedIcon { nullptr };
LLUICtrl* mHoveredIcon { nullptr };
LLEmojiGridIcon* mFocusedIcon { nullptr };
LLEmojiGridIcon* mHoveredIcon { nullptr };
U64 mRecentReturnPressedMs { 0 };
};
#endif

View File

@ -259,7 +259,7 @@ BOOL LLFloaterIMSessionTab::postBuild()
mEmojiRecentPanelToggleBtn = getChild<LLButton>("emoji_recent_panel_toggle_btn");
mEmojiRecentPanelToggleBtn->setLabel(LLUIString(LLWString(1, 128512)));
mEmojiRecentPanelToggleBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiRecentPanelToggleBtnClicked(this); });
mEmojiRecentPanelToggleBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiRecentPanelToggleBtnClicked(); });
mEmojiRecentPanel = getChild<LLLayoutPanel>("emoji_recent_layout_panel");
mEmojiRecentPanel->setVisible(false);
@ -272,8 +272,8 @@ BOOL LLFloaterIMSessionTab::postBuild()
mEmojiRecentIconsCtrl->setCommitCallback([this](LLUICtrl*, const LLSD& value) { onRecentEmojiPicked(value); });
mEmojiRecentIconsCtrl->setVisible(false);
mEmojiPickerToggleBtn = getChild<LLButton>("emoji_picker_toggle_btn");
mEmojiPickerToggleBtn->setClickedCallback([](LLUICtrl*, const LLSD&) { onEmojiPickerToggleBtnClicked(); });
mEmojiPickerShowBtn = getChild<LLButton>("emoji_picker_show_btn");
mEmojiPickerShowBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerShowBtnClicked(); });
mGearBtn = getChild<LLButton>("gear_btn");
mAddBtn = getChild<LLButton>("add_btn");
@ -452,56 +452,30 @@ void LLFloaterIMSessionTab::onInputEditorClicked()
gToolBarView->flashCommand(LLCommandId("chat"), false);
}
void LLFloaterIMSessionTab::onEmojiRecentPanelToggleBtnClicked(LLFloaterIMSessionTab* self)
void LLFloaterIMSessionTab::onEmojiRecentPanelToggleBtnClicked()
{
bool show = !self->mEmojiRecentPanel->getVisible();
bool restore_focus = !show || (gFocusMgr.getLastKeyboardFocus() == self->mInputEditor);
BOOL show = mEmojiRecentPanel->getVisible() ? FALSE : TRUE;
if (show)
{
self->initEmojiRecentPanel(!restore_focus);
initEmojiRecentPanel();
}
self->mEmojiRecentPanel->setVisible(show ? TRUE : FALSE);
if (restore_focus)
{
self->mInputEditor->setFocus(true);
}
mEmojiRecentPanel->setVisible(show);
mInputEditor->setFocus(TRUE);
}
void LLFloaterIMSessionTab::onEmojiPickerToggleBtnClicked()
void LLFloaterIMSessionTab::onEmojiPickerShowBtnClicked()
{
if (LLFloaterEmojiPicker* picker = LLFloaterEmojiPicker::getInstance())
{
if (!picker->isShown())
{
picker->show(
[](llwchar emoji) { onEmojiPicked(emoji); },
[]() { onEmojiPickerClosed(); });
if (LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance())
{
im_box->addDependentFloater(picker, TRUE, TRUE);
}
}
else
{
picker->closeFloater();
}
}
mInputEditor->showEmojiHelper();
}
void LLFloaterIMSessionTab::initEmojiRecentPanel(bool moveFocus)
void LLFloaterIMSessionTab::initEmojiRecentPanel()
{
std::list<llwchar>& recentlyUsed = LLFloaterEmojiPicker::getRecentlyUsed();
if (recentlyUsed.empty())
{
mEmojiRecentEmptyText->setVisible(TRUE);
mEmojiRecentIconsCtrl->setVisible(FALSE);
if (moveFocus)
{
mEmojiPickerToggleBtn->setFocus(TRUE);
}
}
else
{
@ -513,10 +487,6 @@ void LLFloaterIMSessionTab::initEmojiRecentPanel(bool moveFocus)
mEmojiRecentIconsCtrl->setEmojis(emojis);
mEmojiRecentEmptyText->setVisible(FALSE);
mEmojiRecentIconsCtrl->setVisible(TRUE);
if (moveFocus)
{
mEmojiRecentIconsCtrl->setFocus(TRUE);
}
}
}
@ -534,31 +504,6 @@ void LLFloaterIMSessionTab::onRecentEmojiPicked(const LLSD& value)
}
}
// static
void LLFloaterIMSessionTab::onEmojiPicked(llwchar emoji)
{
if (LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance())
{
if (LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(im_box->getSelectedSession()))
{
session_floater->mInputEditor->insertEmoji(emoji);
session_floater->mInputEditor->setFocus(TRUE);
}
}
}
// static
void LLFloaterIMSessionTab::onEmojiPickerClosed()
{
if (LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance())
{
if (LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(im_box->getSelectedSession()))
{
session_floater->mInputEditor->setFocus(TRUE);
}
}
}
void LLFloaterIMSessionTab::closeFloater(bool app_quitting)
{
LLFloaterEmojiPicker::saveState();
@ -624,11 +569,11 @@ void LLFloaterIMSessionTab::updateUsedEmojis(LLWString text)
if (!emojiSent)
return;
LLFloaterEmojiPicker::onRecentlyUsedChanged();
LLFloaterEmojiPicker::saveState();
if (mEmojiRecentPanel->getVisible())
{
initEmojiRecentPanel(false);
initEmojiRecentPanel();
}
}

View File

@ -189,7 +189,7 @@ protected:
LLButton* mExpandCollapseBtn;
LLButton* mTearOffBtn;
LLButton* mEmojiRecentPanelToggleBtn;
LLButton* mEmojiPickerToggleBtn;
LLButton* mEmojiPickerShowBtn;
LLButton* mCloseBtn;
LLButton* mGearBtn;
LLButton* mAddBtn;
@ -215,12 +215,10 @@ private:
void onInputEditorClicked();
static void onEmojiRecentPanelToggleBtnClicked(LLFloaterIMSessionTab* self);
static void onEmojiPickerToggleBtnClicked();
void initEmojiRecentPanel(bool moveFocus);
void onEmojiRecentPanelToggleBtnClicked();
void onEmojiPickerShowBtnClicked();
void initEmojiRecentPanel();
void onRecentEmojiPicked(const LLSD& value);
static void onEmojiPicked(llwchar emoji);
static void onEmojiPickerClosed();
bool checkIfTornOff();
bool mIsHostAttached;

View File

@ -3,33 +3,26 @@
name="emojipicker"
title="CHOOSE EMOJI"
help_topic="emojipicker"
positioning="cascading"
legacy_header_height="0"
single_instance="true"
can_minimize="false"
can_tear_off="false"
can_resize="true"
auto_close="true"
layout="topleft"
min_width="250"
height="400"
width="250">
chrome="true"
height="350"
width="304">
<floater.string name="title_for_recently_used" value="Recently used"/>
<floater.string name="title_for_frequently_used" value="Frequently used"/>
<filter_editor
name="Filter"
label="Start typing to filter"
layout="topleft"
follows="top|left|right"
top="27"
left="10"
height="23"
width="230" />
<scroll_container
name="EmojiGridContainer"
layout="topleft"
follows="all"
ignore_arrow_keys="true"
top="50"
top="25"
left="0"
height="300"
width="250">
height="275">
<scrolling_panel_list
name="EmojiGrid"
layout="topleft"
@ -37,8 +30,7 @@
padding="4"
spacing="0"
top="0"
left="0"
width="250"/>
left="0"/>
</scroll_container>
<panel
name="Groups"
@ -46,8 +38,7 @@
follows="top|left|right"
top="0"
left="0"
height="25"
width="250">
height="25">
<panel
name="Badge"
layout="bottomleft"
@ -70,6 +61,5 @@
valign="center"
bottom="14"
left="10"
height="23"
width="230">No emoji selected</text>
height="25">No emoji selected</text>
</floater>

View File

@ -306,6 +306,7 @@
follows="right|bottom"
use_font_color="true"
font="EmojiLarge"
tab_stop="false"
image_hover_unselected="Toolbar_Middle_Over"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
@ -353,17 +354,19 @@
name="emoji_recent_icons_ctrl"
follows="top|left|right"
layout="topleft"
tab_stop="false"
max_visible="20"
top="0"
left="1"
right="-65"
height="30"/>
<button
name="emoji_picker_toggle_btn"
name="emoji_picker_show_btn"
label="More"
tool_tip="Shows/hides emoji picker"
follows="right|bottom"
layout="topleft"
tab_stop="false"
bottom="-5"
right="-3"
height="20"