From a7c084735ee43d94272d4cebe6894e2ec5cbd8ec Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 23 Apr 2026 16:16:37 +0300 Subject: [PATCH 1/7] #5450 add Leap non-ascii input support for keyDown --- indra/newview/llwindowlistener.cpp | 42 ++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/indra/newview/llwindowlistener.cpp b/indra/newview/llwindowlistener.cpp index 31005fb734..38e49d0750 100644 --- a/indra/newview/llwindowlistener.cpp +++ b/indra/newview/llwindowlistener.cpp @@ -91,7 +91,8 @@ LLWindowListener::LLWindowListener(LLViewerWindow *window, const KeyboardGetter& &LLWindowListener::getPaths, LLSDMap("reply", LLSD())); add("keyDown", - keySomething + "keypress event.\n" + keyExplain + mask, + keySomething + "keypress event.\n" + keyExplain + + "The [\"char\"] parameter detects and handles non-ASCII characters seperately\n" + mask, &LLWindowListener::keyDown); add("keyUp", keySomething + "key release event.\n" + keyExplain + mask, @@ -270,6 +271,20 @@ void LLWindowListener::keyDown(LLSD const & evt) KEY key = getKEY(evt); MASK mask = getMask(evt); + bool is_non_ascii = false; + llwchar uni_char = 0; + + if (evt.has("char")) + { + LLWString wstr = utf8str_to_wstring(evt["char"].asString()); + if (!wstr.empty()) + { + uni_char = wstr[0]; + // If the Unicode code point is outside ASCII range, use Unicode-only handling + is_non_ascii = (uni_char >= 0x80); + } + } + if (evt.has("path")) { std::string path(evt["path"]); @@ -284,8 +299,17 @@ void LLWindowListener::keyDown(LLSD const & evt) response.setResponse(target_view->getInfo()); gFocusMgr.setKeyboardFocus(target_view); - gViewerInput.handleKey(key, mask, false); - if(key < 0x80) mWindow->handleUnicodeChar(key, mask); + + if (is_non_ascii) + { + // For non-ASCII characters, only send the Unicode event + mWindow->handleUnicodeChar(uni_char, mask); + } + else + { + gViewerInput.handleKey(key, mask, false); + if(key < 0x80) mWindow->handleUnicodeChar(key, mask); + } } else { @@ -296,8 +320,16 @@ void LLWindowListener::keyDown(LLSD const & evt) } else { - gViewerInput.handleKey(key, mask, false); - if(key < 0x80) mWindow->handleUnicodeChar(key, mask); + if (is_non_ascii) + { + // For non-ASCII characters, only send the Unicode event + mWindow->handleUnicodeChar(uni_char, mask); + } + else + { + gViewerInput.handleKey(key, mask, false); + if(key < 0x80) mWindow->handleUnicodeChar(key, mask); + } } } From 4ccf6d90efe34475a39c89bf40f17c0d56a3ce1a Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 24 Apr 2026 21:45:25 +0300 Subject: [PATCH 2/7] #5439 fix Avatar Welcome Pack not being opened on the first session --- indra/newview/llviewerwindow.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 8695b96952..0f3f24d1af 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2330,14 +2330,22 @@ void LLViewerWindow::initWorldUI() physical_mem = LLMemory::getMaxMemKB(); } - if (!gNonInteractive && physical_mem > MIN_PHYSICAL_MEMORY) + if (!gNonInteractive) { - LL_INFOS() << "Preloading cef instances" << LL_ENDL; + if (physical_mem > MIN_PHYSICAL_MEMORY) + { + LL_INFOS() << "Preloading cef instances" << LL_ENDL; - LLFloaterReg::getInstance("destinations"); - LLFloaterReg::getInstance("avatar_welcome_pack"); - LLFloaterReg::getInstance("search"); - LLFloaterReg::getInstance("marketplace"); + LLFloaterReg::getInstance("destinations"); + LLFloaterReg::getInstance("avatar_welcome_pack"); + LLFloaterReg::getInstance("search"); + LLFloaterReg::getInstance("marketplace"); + } + else if (gSavedSettings.getBOOL("FirstLoginThisInstall")) + { + // Preload the welcome pack for first-time login even on low end hardware + LLFloaterReg::getInstance("avatar_welcome_pack"); + } } } From 7719e6c16dc182ede6ed4b766d8cec4adf8feeba Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Mon, 27 Apr 2026 14:38:49 -0700 Subject: [PATCH 3/7] Fix P2P text chat timeout on WebRTC regions and delay voice renegotiation on disconnect (#5706) * Fix P2P text chat timeout on WebRTC regions and delay voice renegotiation on disconnect Text chat: On WebRTC regions, getOutgoingCallInterface() returns nullptr, causing mP2PAsAdhocCall to be true for all P2P sessions including text-only IMs. This routed text chat through startP2PVoiceCoro which sent a "start p2p voice" request and waited for a server reply that never came, resulting in a 30-second session initialization timeout. Fix by gating the p2p-as-adhoc server init on mStartedAsIMCall so text-only sessions initialize immediately. WebRTC: Split kFailed and kDisconnected handling in OnConnectionChange. kFailed still renegotiates immediately. kDisconnected now waits 10 seconds before renegotiating, giving the connection time to recover on its own. Uses a sequence counter to ensure only the most recent disconnect transition can trigger renegotiation, preventing stale delayed tasks from firing early after disconnect/reconnect cycles. Co-Authored-By: Claude Opus 4.6 (1M context) * Revert im-change for not using the voice subsystem when doing a text-only IM --------- Co-authored-by: Claude Opus 4.6 (1M context) --- indra/llwebrtc/llwebrtc.cpp | 29 +++++++++++++++++++++++++++-- indra/llwebrtc/llwebrtc_impl.h | 11 +++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index 6bf38cc1f6..a286f75f42 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -811,6 +811,8 @@ LLWebRTCPeerConnectionImpl::LLWebRTCPeerConnectionImpl() : mPeerConnection(nullptr), mMute(MUTE_INITIAL), mAnswerReceived(false), + mPeerConnectionState(webrtc::PeerConnectionInterface::PeerConnectionState::kNew), + mDisconnectCount(0), mPendingJobs(0) { } @@ -1237,11 +1239,15 @@ void LLWebRTCPeerConnectionImpl::OnIceGatheringChange(webrtc::PeerConnectionInte } } +static const webrtc::TimeDelta DISCONNECT_RENEGOTIATE_DELAY = webrtc::TimeDelta::Millis(10000); + // Called any time the PeerConnectionState changes. void LLWebRTCPeerConnectionImpl::OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState new_state) { RTC_LOG(LS_ERROR) << __FUNCTION__ << " Peer Connection State Change " << new_state; + mPeerConnectionState = new_state; + switch (new_state) { case webrtc::PeerConnectionInterface::PeerConnectionState::kConnected: @@ -1257,13 +1263,32 @@ void LLWebRTCPeerConnectionImpl::OnConnectionChange(webrtc::PeerConnectionInterf break; } case webrtc::PeerConnectionInterface::PeerConnectionState::kFailed: - case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected: { for (auto &observer : mSignalingObserverList) { observer->OnRenegotiationNeeded(); } - + break; + } + case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected: + { + // Wait 10 seconds before renegotiating in case the connection recovers on its own. + // Use a sequence count so that only the most recent disconnect transition can trigger + // a renegotiation, avoiding stale delayed tasks from earlier disconnect/reconnect cycles. + uint32_t disconnect_count = ++mDisconnectCount; + mWebRTCImpl->PostDelayedSignalingTask( + [this, disconnect_count]() + { + if (disconnect_count == mDisconnectCount + && mPeerConnectionState == webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected) + { + for (auto &observer : mSignalingObserverList) + { + observer->OnRenegotiationNeeded(); + } + } + }, + DISCONNECT_RENEGOTIATE_DELAY); break; } default: diff --git a/indra/llwebrtc/llwebrtc_impl.h b/indra/llwebrtc/llwebrtc_impl.h index 2ff85c92ee..bd7a2e0bcf 100644 --- a/indra/llwebrtc/llwebrtc_impl.h +++ b/indra/llwebrtc/llwebrtc_impl.h @@ -480,6 +480,13 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceO mSignalingThread->PostTask(std::move(task), location); } + void PostDelayedSignalingTask(absl::AnyInvocable task, + webrtc::TimeDelta delay, + const webrtc::Location& location = webrtc::Location::Current()) + { + mSignalingThread->PostDelayedTask(std::move(task), delay, location); + } + void PostNetworkTask(absl::AnyInvocable task, const webrtc::Location& location = webrtc::Location::Current()) { @@ -676,6 +683,10 @@ class LLWebRTCPeerConnectionImpl : public LLWebRTCPeerConnectionInterface, std::vector mDataObserverList; webrtc::scoped_refptr mDataChannel; + // connection state tracking for delayed renegotiation on disconnect + webrtc::PeerConnectionInterface::PeerConnectionState mPeerConnectionState; + uint32_t mDisconnectCount; + std::atomic mPendingJobs; }; From 5a1ca24fa9378c57de16b6443e4e9dde7799b6cb Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Tue, 28 Apr 2026 02:36:56 +0300 Subject: [PATCH 4/7] #5726 Crash initing in-viewer console --- indra/llui/llconsole.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp index 91e6f281da..ca512a9883 100644 --- a/indra/llui/llconsole.cpp +++ b/indra/llui/llconsole.cpp @@ -67,6 +67,10 @@ LLConsole::LLConsole(const LLConsole::Params& p) { setFontSize(p.font_size_index); } + if (mFont == nullptr) + { + setFontSize(0); // sans-serif + } mFadeTime = mLinePersistTime - FADE_DURATION; setMaxLines(LLUI::getInstance()->mSettingGroups["config"]->getS32("ConsoleMaxLines")); } @@ -79,6 +83,13 @@ void LLConsole::setLinePersistTime(F32 seconds) void LLConsole::reshape(S32 width, S32 height, bool called_from_parent) { + if (mFont == nullptr) + { + // not initialized yet + LL_WARNS() << "LLConsole::reshape called before font is set" << LL_ENDL; + return; + } + S32 new_width = llmax(50, llmin(getRect().getWidth(), width)); S32 new_height = llmax(mFont->getLineHeight() + 15, llmin(getRect().getHeight(), height)); From fd4533261e46c080591b06cec030c464e5fe9a90 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Thu, 30 Apr 2026 01:39:30 +0300 Subject: [PATCH 5/7] #5084 Improve watchdog's behavior #2 --- indra/llcommon/llapp.h | 2 +- indra/llcommon/llwatchdog.cpp | 9 ++++++--- indra/newview/llappviewerwin32.cpp | 12 ++++++------ indra/newview/llappviewerwin32.h | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index fef7dc80b3..3a855bc480 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -285,7 +285,7 @@ public: #ifdef LL_WINDOWS virtual bool reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { return false; } - virtual bool reportCustomToBugsplat(const std::string& desription) { return false; } + virtual bool reportCustomToBugsplat(const std::string& description) { return false; } #endif public: diff --git a/indra/llcommon/llwatchdog.cpp b/indra/llcommon/llwatchdog.cpp index 1622aeb180..66b565c763 100644 --- a/indra/llcommon/llwatchdog.cpp +++ b/indra/llcommon/llwatchdog.cpp @@ -191,6 +191,7 @@ void LLWatchdog::remove(LLWatchdogEntry* e) { lockThread(); mSuspects.erase(e); + mFrozeList.erase(e); unlockThread(); } @@ -284,8 +285,9 @@ void LLWatchdog::run() // Sets watchdog marker file mCreateMarkerFnc(false); // If it's mainloop and it somehow recovers, it will re-add itself - mSuspects.erase(*result); - mFrozeList.insert(*result); + LLWatchdogEntry* froze_entry = *result; + mSuspects.erase(result); + mFrozeList.insert(froze_entry); LL_WARNS() << description << LL_ENDL; } else @@ -307,8 +309,9 @@ void LLWatchdog::run() mCreateMarkerFnc(false); // Already reported, don't report again. // If it's mainloop and it somehow recovers, it will re-add itself + LLWatchdogEntry* froze_entry = *result; mSuspects.erase(result); - mFrozeList.insert(*result); + mFrozeList.insert(froze_entry); } } } diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 6b26127925..2e4e9e29d5 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -119,7 +119,7 @@ namespace // MiniDmpSender pointer. As things stand, though, we must define an // actual function and store the pointer statically. static MiniDmpSender *sBugSplatSender = nullptr; - static std::string sBugsplatDesriptionField; + static std::string sBugsplatDescriptionField; bool bugsplatSendLog(UINT nCode, LPVOID lpVal1, LPVOID lpVal2) { @@ -156,15 +156,15 @@ namespace WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "settings_per_account.xml"))); } - if (!sBugsplatDesriptionField.empty()) + if (!sBugsplatDescriptionField.empty()) { // Can be set by watchdog or other code that detects a problem // and wants to add some context to the crash report. // Will be visible in the BugSplat web UI. - sBugSplatSender->setDefaultUserDescription(WCSTR(LLError::getFatalMessage())); - // This type of crash is not nessesarily a crash, or final. + sBugSplatSender->setDefaultUserDescription(WCSTR(sBugsplatDescriptionField)); + // This type of crash is not necessarily a crash, or final. // Prepare for the next one. - sBugsplatDesriptionField.clear(); + sBugsplatDescriptionField.clear(); } else { @@ -878,7 +878,7 @@ bool LLAppViewerWin32::reportCustomToBugsplat(const std::string &description) #if defined(LL_BUGSPLAT) if (sBugSplatSender) { - sBugsplatDesriptionField = description; + sBugsplatDescriptionField = description; __try { diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h index b31fa49cb2..53177f7f95 100644 --- a/indra/newview/llappviewerwin32.h +++ b/indra/newview/llappviewerwin32.h @@ -44,7 +44,7 @@ public: bool cleanup() override; bool reportCrashToBugsplat(void* pExcepInfo) override; - bool reportCustomToBugsplat(const std::string& desription) override; + bool reportCustomToBugsplat(const std::string& description) override; protected: bool initWindow() override; // Override to initialize the viewer's window. From c8797d9297cf070f7793f55d961eec2cdb3a494a Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Tue, 5 May 2026 01:23:46 +0300 Subject: [PATCH 6/7] #5759 The fonts going bold --- indra/newview/skins/default/xui/en/fonts.xml | 8 ++++---- indra/newview/skins/default/xui/ja/fonts.xml | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml index 3c6e100541..1ad01ee120 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -37,7 +37,7 @@ - InterVariableFont.ttf + InterVariableFont.ttf DejaVuSans-Bold.ttf arialbd.ttf @@ -64,7 +64,7 @@ name="SansSerif" comment="Name of bold sans-serif font" font_style="BOLD"> - InterVariableFont.ttf + InterVariableFont.ttf DejaVuSans-Bold.ttf @@ -80,7 +80,7 @@ name="SansSerif" comment="Name of bold italic sans-serif font" font_style="BOLD|ITALIC"> - InterItalicVariableFont.ttf + InterItalicVariableFont.ttf DejaVuSans-BoldOblique.ttf @@ -135,7 +135,7 @@ name="Helvetica" comment="Name of Helvetica font (bold)" font_style="BOLD"> - InterVariableFont.ttf + InterVariableFont.ttf DejaVuSans-Bold.ttf arialbd.ttf diff --git a/indra/newview/skins/default/xui/ja/fonts.xml b/indra/newview/skins/default/xui/ja/fonts.xml index 06922d2b02..7abb3593b6 100644 --- a/indra/newview/skins/default/xui/ja/fonts.xml +++ b/indra/newview/skins/default/xui/ja/fonts.xml @@ -80,7 +80,7 @@ NotoSansCJKjp-Bold.otf - InterVariableFont.ttf + InterVariableFont.ttf YuGothB.ttc @@ -115,13 +115,13 @@ - InterVariableFont.ttf + InterVariableFont.ttf InterItalicVariableFont.ttf - InterItalicVariableFont.ttf + InterItalicVariableFont.ttf @@ -163,7 +163,7 @@ - InterVariableFont.ttf + InterVariableFont.ttf arialbd.ttf @@ -189,7 +189,7 @@ - InterItalicVariableFont.ttf + InterItalicVariableFont.ttf arialbi.ttf From b44809f740d307615526060e7b57e7705c292347 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Tue, 5 May 2026 16:45:27 +0300 Subject: [PATCH 7/7] #5755 fix for notifications layout --- indra/newview/app_settings/settings.xml | 11 ++++++ indra/newview/lltoastnotifypanel.cpp | 46 +++++++++++++++---------- indra/newview/lltoastnotifypanel.h | 2 ++ 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 7844e07d7c..dbc16ef47e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5887,6 +5887,17 @@ If required width will be less then this one, a button will be reshaped to default size , otherwise to required Change of this parameter will affect the layout of buttons in notification toast. + Persist + 1 + Type + S32 + Value + 90 + + ScriptToastButtonWidth + + Comment + Default width of buttons in the Script dialog toast. Persist 1 Type diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 846642841a..8a7095f8ca 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -46,7 +46,7 @@ const S32 BOTTOM_PAD = VPAD * 3; const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding -S32 BUTTON_WIDTH = 110; +const S32 BUTTON_WIDTH = 90; //static @@ -58,7 +58,8 @@ LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) : LLCheckBoxToastPanel(notification) , LLInstanceTracker(notification->getID()) -, mTextBox(NULL) +, mTextBox(NULL), + mButtonWidth(BUTTON_WIDTH) { init(rect, show_images); } @@ -69,9 +70,9 @@ void LLToastNotifyPanel::addDefaultButton() LLButton* ok_btn = createButton(form_element, false); LLRect new_btn_rect(ok_btn->getRect()); - new_btn_rect.setOriginAndSize(llabs(getRect().getWidth() - BUTTON_WIDTH)/ 2, BOTTOM_PAD, + new_btn_rect.setOriginAndSize(llabs(getRect().getWidth() - mButtonWidth) / 2, BOTTOM_PAD, //auto_size for ok button makes it very small, so let's make it wider - BUTTON_WIDTH, new_btn_rect.getHeight()); + mButtonWidth, new_btn_rect.getHeight()); ok_btn->setRect(new_btn_rect); addChild(ok_btn, -1); mNumButtons = 1; @@ -98,7 +99,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, bool is_opt p.font = font; p.rect.height = BTN_HEIGHT; p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata)); - p.rect.width = BUTTON_WIDTH; + p.rect.width = mButtonWidth; p.auto_resize = false; p.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); p.enabled = !form_element.has("enabled") || form_element["enabled"].asBoolean(); @@ -108,7 +109,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, bool is_opt p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); } // for the scriptdialog buttons we use fixed button size. This is a limit! - if (!mIsScriptDialog && font->getWidth(form_element["text"].asString()) > (BUTTON_WIDTH-2*HPAD)) + if (!mIsScriptDialog && font->getWidth(form_element["text"].asString()) > (mButtonWidth - 2 * HPAD)) { p.rect.width = 1; p.auto_resize = true; @@ -273,7 +274,7 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) mInfoPanel = getChild("info_panel"); mControlPanel = getChild("control_panel"); - BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); + // customize panel's attributes // is it intended for displaying a tip? mIsTip = mNotification->getType() == "notifytip"; @@ -282,6 +283,10 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) // is it a script dialog? mIsScriptDialog = (notif_name == "ScriptDialog" || notif_name == "ScriptDialogGroup"); + static LLCachedControl btn_width(gSavedSettings, "ToastButtonWidth", 90); + static LLCachedControl script_button_width(gSavedSettings, "ScriptToastButtonWidth", 110); + mButtonWidth = mIsScriptDialog ? script_button_width : btn_width; + bool is_content_trusted = (notif_name != "LoadWebPage"); // is it a caution? // @@ -365,17 +370,20 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) S32 button_panel_width = mControlPanel->getRect().getWidth();// get initial width from XML S32 button_panel_height = mControlPanel->getRect().getHeight(); - // width for 3 columns: 3 buttons + 2 gaps - S32 min_width_required = 3 * BUTTON_WIDTH + 2 * (2 * HPAD); - if (min_width_required > button_panel_width) + // Script dialog has wider buttons so it requires wider layout to ensure proper spacing + if (mIsScriptDialog) { - button_panel_width = min_width_required; - S32 width_increase = button_panel_width - mControlPanel->getRect().getWidth(); - reshape(getRect().getWidth() + width_increase, getRect().getHeight()); - mInfoPanel->reshape(mInfoPanel->getRect().getWidth() + width_increase, mInfoPanel->getRect().getHeight()); - mTextBox->reshape(mTextBox->getRect().getWidth() + width_increase, mTextBox->getRect().getHeight()); + // width for 3 columns: 3 buttons + 2 gaps + S32 min_width_required = 3 * mButtonWidth + 2 * (2 * HPAD); + if (min_width_required > button_panel_width) + { + button_panel_width = min_width_required; + S32 width_increase = button_panel_width - mControlPanel->getRect().getWidth(); + reshape(getRect().getWidth() + width_increase, getRect().getHeight()); + mInfoPanel->reshape(mInfoPanel->getRect().getWidth() + width_increase, mInfoPanel->getRect().getHeight()); + mTextBox->reshape(mTextBox->getRect().getWidth() + width_increase, mTextBox->getRect().getHeight()); + } } - //try get an average h_pad to spread out buttons S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); if(h_pad < 2*HPAD) @@ -385,8 +393,8 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. * In last case set default h_pad to avoid heaping of buttons */ - S32 button_per_row = button_panel_width / BUTTON_WIDTH; - h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row + S32 button_per_row = button_panel_width / mButtonWidth; + h_pad = (button_panel_width % mButtonWidth) / (button_per_row - 1);// -1 because we do not need space after last button in a row if(h_pad < 2*HPAD) // still not enough space between buttons ? { h_pad = 2*HPAD; @@ -397,7 +405,7 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) // we are using default width for script buttons so we can determinate button_rows // to get a number of rows we divide the required width of the buttons to button_panel_width // buttons.size() is reduced by -2 due to presence of ignore button which is calculated independently a bit lower - S32 button_rows = llceil(F32(buttons.size() - 2) * (BUTTON_WIDTH + h_pad) / (button_panel_width + h_pad)); + S32 button_rows = llceil(F32(buttons.size() - 2) * (mButtonWidth + h_pad) / (button_panel_width + h_pad)); //reserve one row for the ignore_btn button_rows++; //calculate required panel height for scripdialog notification. diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index d694513aba..71b9eaf8f5 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -134,6 +134,8 @@ protected: S32 mNumOptions { 0 }; S32 mNumButtons { 0 }; + S32 mButtonWidth; + static const std::string sFontDefault; static const std::string sFontScript; };