From afc9252372b2b511bb3f7caaaa0856989bbd3f46 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Thu, 8 Feb 2024 21:55:59 +0100 Subject: [PATCH 1/4] SL-20363 Option 'Debug Unicode' - show unicode values --- indra/llcommon/llstring.cpp | 87 ++++++++++++++++++++++++++++++++----- indra/llcommon/llstring.h | 2 + 2 files changed, 78 insertions(+), 11 deletions(-) diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index ab34262515..82dc7c9f80 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -645,49 +645,114 @@ std::string utf8str_removeCRLF(const std::string& utf8str) return out; } +llwchar utf8str_to_wchar(const std::string& utf8str, size_t offset, size_t length) +{ + switch (length) + { + case 2: + return ((utf8str[offset] & 0x1F) << 6) + + (utf8str[offset + 1] & 0x3F); + case 3: + return ((utf8str[offset] & 0x0F) << 12) + + ((utf8str[offset + 1] & 0x3F) << 6) + + (utf8str[offset + 2] & 0x3F); + case 4: + return ((utf8str[offset] & 0x07) << 18) + + ((utf8str[offset + 1] & 0x3F) << 12) + + ((utf8str[offset + 2] & 0x3F) << 6) + + (utf8str[offset + 3] & 0x3F); + case 5: + return ((utf8str[offset] & 0x03) << 24) + + ((utf8str[offset + 1] & 0x3F) << 18) + + ((utf8str[offset + 2] & 0x3F) << 12) + + ((utf8str[offset + 3] & 0x3F) << 6) + + (utf8str[offset + 4] & 0x3F); + case 6: + return ((utf8str[offset] & 0x01) << 30) + + ((utf8str[offset + 1] & 0x3F) << 24) + + ((utf8str[offset + 2] & 0x3F) << 18) + + ((utf8str[offset + 3] & 0x3F) << 12) + + ((utf8str[offset + 4] & 0x3F) << 6) + + (utf8str[offset + 5] & 0x3F); + case 7: + return ((utf8str[offset + 1] & 0x03) << 30) + + ((utf8str[offset + 2] & 0x3F) << 24) + + ((utf8str[offset + 3] & 0x3F) << 18) + + ((utf8str[offset + 4] & 0x3F) << 12) + + ((utf8str[offset + 5] & 0x3F) << 6) + + (utf8str[offset + 6] & 0x3F); + } + return LL_UNKNOWN_CHAR; +} + std::string utf8str_showBytesUTF8(const std::string& utf8str) { std::string result; bool in_sequence = false; - for (U8 byte : utf8str) + size_t sequence_size = 0; + size_t byte_index = 0; + size_t source_length = utf8str.size(); + + auto open_sequence = [&]() + { + if (!result.empty() && result.back() != '\n') + result += '\n'; // Use LF as a separator before new UTF-8 sequence + result += '['; + in_sequence = true; + }; + + auto close_sequence = [&]() + { + llwchar unicode = utf8str_to_wchar(utf8str, byte_index - sequence_size, sequence_size); + if (unicode != LL_UNKNOWN_CHAR) + { + result += llformat("+%04X", unicode); + } + result += ']'; + in_sequence = false; + sequence_size = 0; + }; + + while (byte_index < source_length) { + U8 byte = utf8str[byte_index]; if (byte >= 0x80) // Part of an UTF-8 sequence { if (!in_sequence) // Start new UTF-8 sequence { - if (!result.empty() && result.back() != ' ') - result += ' '; // Use space as separator between ASCII and UTF-8 - result += '['; + open_sequence(); } else if (byte >= 0xC0) // Start another UTF-8 sequence { - result += "] ["; // Use space as separator between UTF-8 and UTF-8 + close_sequence(); + open_sequence(); } else // Continue the same UTF-8 sequence { result += '.'; } result += llformat("%02X", byte); // The byte is represented in hexadecimal form - in_sequence = true; + ++sequence_size; } else // ASCII symbol is represented as a character { if (in_sequence) // End of UTF-8 sequence { - result += ']'; - if (byte != ' ') + close_sequence(); + if (byte != '\n') { - result += ' '; // Use space as separator between UTF-8 and ASCII + result += '\n'; // Use LF as a separator between UTF-8 and ASCII } } result += byte; - in_sequence = false; } + ++byte_index; } + if (in_sequence) // End of UTF-8 sequence { - result += ']'; + close_sequence(); } return result; diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 38b9c3e23c..bfbf25d9ab 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -743,6 +743,8 @@ LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str); LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str); +LL_COMMON_API llwchar utf8str_to_wchar(const std::string& utf8str, size_t offset, size_t length); + LL_COMMON_API std::string utf8str_showBytesUTF8(const std::string& utf8str); #if LL_WINDOWS From b4e29ec0e922368f23fc735fd4719f205cc760eb Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Fri, 9 Feb 2024 12:54:09 +0100 Subject: [PATCH 2/4] #68 The 'Recently used emoji' can not be selected by the 'Tab' key --- indra/newview/llfloaterimsessiontab.cpp | 1 + indra/newview/skins/default/xui/en/floater_im_session.xml | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 2cb2ea0553..24cc398f3b 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -465,6 +465,7 @@ void LLFloaterIMSessionTab::onEmojiRecentPanelToggleBtnClicked() void LLFloaterIMSessionTab::onEmojiPickerShowBtnClicked() { + mInputEditor->setFocus(TRUE); mInputEditor->showEmojiHelper(); } 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 1b6bc7025a..a6493c5e24 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -305,7 +305,6 @@ tool_tip="Shows/hides recent emojis" follows="right|bottom" font="EmojiLarge" - tab_stop="false" image_hover_unselected="Toolbar_Middle_Over" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" @@ -354,7 +353,6 @@ name="emoji_recent_icons_ctrl" follows="top|left|right" layout="topleft" - tab_stop="false" max_visible="20" top="0" left="1" @@ -366,7 +364,6 @@ tool_tip="Shows/hides emoji picker" follows="right|bottom" layout="topleft" - tab_stop="false" bottom="-5" right="-3" height="20" From 1820095dd4a64c142e14869c76ae09e1e0ca6a12 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Mon, 12 Feb 2024 19:01:00 +0100 Subject: [PATCH 3/4] #779 Emoji picker is an unintuitive UX disaster --- indra/newview/llfloateremojipicker.cpp | 68 ++++++++++++++++++++++---- indra/newview/llfloateremojipicker.h | 2 + 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp index 2380fd357b..1578caa39c 100644 --- a/indra/newview/llfloateremojipicker.cpp +++ b/indra/newview/llfloateremojipicker.cpp @@ -953,6 +953,43 @@ void LLFloaterEmojiPicker::selectFocusedIcon() } } +bool LLFloaterEmojiPicker::moveFocusedIconUp() +{ + for (S32 i = mFocusedIconRow - 1; i >= 0; --i) + { + LLScrollingPanel* panel = mEmojiGrid->getPanelList()[i]; + LLEmojiGridRow* row = dynamic_cast(panel); + if (row && row->mList->getPanelList().size() > mFocusedIconCol) + { + mEmojiScroll->scrollToShowRect(row->getBoundingRect()); + mFocusedIconRow = i; + selectFocusedIcon(); + return true; + } + } + + return false; +} + +bool LLFloaterEmojiPicker::moveFocusedIconDown() +{ + S32 rowCount = mEmojiGrid->getPanelList().size(); + for (S32 i = mFocusedIconRow + 1; i < rowCount; ++i) + { + LLScrollingPanel* panel = mEmojiGrid->getPanelList()[i]; + LLEmojiGridRow* row = dynamic_cast(panel); + if (row && row->mList->getPanelList().size() > mFocusedIconCol) + { + mEmojiScroll->scrollToShowRect(row->getBoundingRect()); + mFocusedIconRow = i; + selectFocusedIcon(); + return true; + } + } + + return false; +} + bool LLFloaterEmojiPicker::moveFocusedIconPrev() { if (mHoveredIcon) @@ -1031,6 +1068,28 @@ void LLFloaterEmojiPicker::unselectGridIcon(LLEmojiGridIcon* icon) BOOL LLFloaterEmojiPicker::handleKey(KEY key, MASK mask, BOOL called_from_parent) { if (mask == MASK_NONE) + { + switch (key) + { + case KEY_UP: + moveFocusedIconUp(); + return TRUE; + case KEY_DOWN: + moveFocusedIconDown(); + return TRUE; + case KEY_LEFT: + moveFocusedIconPrev(); + return TRUE; + case KEY_RIGHT: + moveFocusedIconNext(); + return TRUE; + case KEY_ESCAPE: + hideFloater(); + return TRUE; + } + } + + if (mask == MASK_ALT) { switch (key) { @@ -1040,15 +1099,6 @@ BOOL LLFloaterEmojiPicker::handleKey(KEY key, MASK mask, BOOL called_from_parent case KEY_RIGHT: selectEmojiGroup((mSelectedGroupIndex + 1) % mGroupButtons.size()); return TRUE; - case KEY_UP: - moveFocusedIconPrev(); - return TRUE; - case KEY_DOWN: - moveFocusedIconNext(); - return TRUE; - case KEY_ESCAPE: - hideFloater(); - return TRUE; } } diff --git a/indra/newview/llfloateremojipicker.h b/indra/newview/llfloateremojipicker.h index f169d67a4e..5d0402ca83 100644 --- a/indra/newview/llfloateremojipicker.h +++ b/indra/newview/llfloateremojipicker.h @@ -85,6 +85,8 @@ private: void onEmojiMouseUp(LLUICtrl* ctrl); void selectFocusedIcon(); + bool moveFocusedIconUp(); + bool moveFocusedIconDown(); bool moveFocusedIconPrev(); bool moveFocusedIconNext(); From bf2fb55fe74f81c160a0ec0d989c3a2fa7730e13 Mon Sep 17 00:00:00 2001 From: Brad Linden <46733234+brad-linden@users.noreply.github.com> Date: Tue, 13 Feb 2024 17:03:00 -0800 Subject: [PATCH 4/4] Update cla.yaml allowlist to clear spurious errors --- .github/workflows/cla.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml index fa180c66c9..b4b2565889 100644 --- a/.github/workflows/cla.yaml +++ b/.github/workflows/cla.yaml @@ -23,3 +23,4 @@ jobs: path-to-signatures: signatures.json remote-organization-name: secondlife remote-repository-name: cla-signatures + allowlist: callum@mbp.localdomain