diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 7985ccc2a1d0a549e3e552dee366e39fc36081e4..c53a5152de75efa4546acabbd02dbdbf9b8afdd1 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -48,6 +48,7 @@
 LLBottomTray::LLBottomTray(const LLSD&)
 :	mChicletPanel(NULL),
 	mSysWell(NULL),
+	mSpeakPanel(NULL),
 	mSpeakBtn(NULL),
 	mNearbyChatBar(NULL),
 	mToolbarStack(NULL)
@@ -304,6 +305,7 @@ BOOL LLBottomTray::postBuild()
 	mSnapshotPanel = getChild<LLPanel>("snapshot_panel");
 	setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4));
 
+	mSpeakPanel = getChild<LLPanel>("speak_panel");
 	mSpeakBtn = getChild<LLSpeakButton>("talk");
 
 	// Speak button should be initially disabled because
@@ -320,6 +322,7 @@ BOOL LLBottomTray::postBuild()
 	mObjectDefaultWidthMap[RS_BUTTON_GESTURES] = mGesturePanel->getRect().getWidth();
 	mObjectDefaultWidthMap[RS_BUTTON_MOVEMENT] = mMovementPanel->getRect().getWidth();
 	mObjectDefaultWidthMap[RS_BUTTON_CAMERA]   = mCamPanel->getRect().getWidth();
+	mObjectDefaultWidthMap[RS_BUTTON_SPEAK]	   = mSpeakPanel->getRect().getWidth();
 
 	return TRUE;
 }
@@ -476,7 +479,7 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width)
 	S32 buttons_freed_width = 0;
 	if (still_should_be_processed)
 	{
-		processShrinkButtons(&delta_width);
+		processShrinkButtons(&delta_width, &buttons_freed_width);
 
 		if (delta_width < 0)
 		{
@@ -532,9 +535,16 @@ void LLBottomTray::processWidthIncreased(S32 delta_width)
 	const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width;
 
 	// how many room we have to show hidden buttons
-	S32 available_width = delta_width + chatbar_available_shrink_width + available_width_chiclet;
+	S32 total_available_width = delta_width + chatbar_available_shrink_width + available_width_chiclet;
 	S32 buttons_required_width = 0; //How many room will take shown buttons
 
+	lldebugs << "Processing extending, available width:"
+		<< ", chatbar - " << chatbar_available_shrink_width
+		<< ", chiclets - " << available_width_chiclet
+		<< ", total - " << total_available_width
+		<< llendl;
+
+	S32 available_width = total_available_width;
 	if (available_width > 0)
 	{
 		lldebugs << "Trying to process: RS_BUTTON_GESTURES" << llendl;
@@ -559,11 +569,14 @@ void LLBottomTray::processWidthIncreased(S32 delta_width)
 		processShowButton(RS_BUTTON_SNAPSHOT, &available_width, &buttons_required_width);
 	}
 
-	// if we have to show some buttons but width increasing is not enough...
-	if (buttons_required_width > 0 && delta_width < buttons_required_width)
+	processExtendButtons(&available_width);
+
+	// if we have to show/extend some buttons but resized delta width is not enough...
+	S32 processed_width = total_available_width - available_width;
+	if (processed_width > delta_width)
 	{
 		// ... let's shrink nearby chat & chiclet panels
-		S32 required_to_process_width = buttons_required_width;
+		S32 required_to_process_width = processed_width;
 
 		// 1. use delta width of resizing
 		required_to_process_width -= delta_width;
@@ -593,9 +606,8 @@ void LLBottomTray::processWidthIncreased(S32 delta_width)
 	}
 
 	// shown buttons take some space, rest should be processed by nearby chatbar & chiclet panels
-	delta_width -= buttons_required_width;
+	delta_width -= processed_width;
 
-	processExtendButtons(&delta_width);
 
 	// how many space can nearby chatbar take?
 	S32 chatbar_panel_width_ = mNearbyChatBar->getRect().getWidth();
@@ -603,8 +615,14 @@ void LLBottomTray::processWidthIncreased(S32 delta_width)
 	{
 		S32 delta_panel_max = chatbar_panel_max_width - chatbar_panel_width_;
 		S32 delta_panel = llmin(delta_width, delta_panel_max);
+		lldebugs << "Unprocesed delta width: " << delta_width
+			<< ", can be applied to chatbar: " << delta_panel_max
+			<< ", will be applied: " << delta_panel
+			<< llendl;
+
 		delta_width -= delta_panel_max;
 		mNearbyChatBar->reshape(chatbar_panel_width_ + delta_panel, mNearbyChatBar->getRect().getHeight());
+		log(mNearbyChatBar, "applied unprocessed delta width");
 	}
 }
 
@@ -666,7 +684,7 @@ void LLBottomTray::processHideButton(EResizeState processed_object_type, S32* re
 	}
 }
 
-void LLBottomTray::processShrinkButtons(S32* required_width)
+void LLBottomTray::processShrinkButtons(S32* required_width, S32* buttons_freed_width)
 {
 	processShrinkButton(RS_BUTTON_CAMERA, required_width);
 
@@ -678,9 +696,44 @@ void LLBottomTray::processShrinkButtons(S32* required_width)
 	{
 		processShrinkButton(RS_BUTTON_GESTURES, required_width);
 	}
+	if (*required_width < 0)
+	{
+
+		S32 panel_min_width = 0;
+		std::string panel_name = mSpeakPanel->getName();
+		bool success = mToolbarStack->getPanelMinSize(panel_name, &panel_min_width, NULL);
+		if (!success)
+		{
+			lldebugs << "Panel was not found to get its min width: " << panel_name << llendl;
+		}
+		else
+		{
+			//
+			mSpeakBtn->setLabelVisible(false);
+			S32 panel_width = mSpeakPanel->getRect().getWidth();
+			S32 possible_shrink_width = panel_width - panel_min_width;
+
+			if (possible_shrink_width > 0)
+			{
+				mSpeakPanel->reshape(panel_width - possible_shrink_width, mSpeakPanel->getRect().getHeight());
+
+				*required_width += possible_shrink_width;
+
+				if (*required_width > 0)
+				{
+					*buttons_freed_width += *required_width;
+				}
+
+				lldebugs << "Shrunk panel: " << panel_name
+					<< ", shrunk width: " << possible_shrink_width
+					<< ", rest width to process: " << *required_width
+					<< llendl;
+			}
+		}
+	}
 }
 
-void LLBottomTray::processShrinkButton(EResizeState processed_object_type, /*const std::string& panel_name, */S32* required_width)
+void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32* required_width)
 {
 	LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
 	if (NULL == panel)
@@ -729,6 +782,9 @@ void LLBottomTray::processShrinkButton(EResizeState processed_object_type, /*con
 
 void LLBottomTray::processExtendButtons(S32* available_width)
 {
+	// do not allow extending any buttons if we have some buttons hidden
+	if (mResizeState & RS_BUTTONS_CAN_BE_HIDDEN) return;
+
 	processExtendButton(RS_BUTTON_GESTURES, available_width);
 
 	if (*available_width > 0)
@@ -739,6 +795,25 @@ void LLBottomTray::processExtendButtons(S32* available_width)
 	{
 		processExtendButton(RS_BUTTON_MOVEMENT, available_width);
 	}
+	if (*available_width > 0)
+	{
+		S32 panel_max_width = mObjectDefaultWidthMap[RS_BUTTON_SPEAK];
+		S32 panel_width = mSpeakPanel->getRect().getWidth();
+		S32 possible_extend_width = panel_max_width - panel_width;
+		if (possible_extend_width > 0 && possible_extend_width <= *available_width)
+		{
+			mSpeakBtn->setLabelVisible(true);
+			mSpeakPanel->reshape(panel_max_width, mSpeakPanel->getRect().getHeight());
+			log(mSpeakBtn, "speak button is extended");
+
+			*available_width -= possible_extend_width;
+
+			lldebugs << "Extending panel: " << mSpeakPanel->getName()
+				<< ", extended width: " << possible_extend_width
+				<< ", rest width to process: " << *available_width
+				<< llendl;
+		}
+	}
 }
 
 void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32* available_width)
diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h
index 97bcc23403a2493793df2b3a543e326f1dee20c5..f4f8397799f52106345061a7e7fbc48eb812c3db 100644
--- a/indra/newview/llbottomtray.h
+++ b/indra/newview/llbottomtray.h
@@ -98,6 +98,12 @@ class LLBottomTray
 		, RS_BUTTON_MOVEMENT	= 0x0010
 		, RS_BUTTON_GESTURES	= 0x0020
 		, RS_BUTTON_SPEAK		= 0x0040
+
+		/**
+		 * Specifies buttons which can be hidden when bottom tray is shrunk.
+		 * They are: Gestures, Movement (Move), Camera (View), Snapshot
+		 */
+		, RS_BUTTONS_CAN_BE_HIDDEN = RS_BUTTON_SNAPSHOT | RS_BUTTON_CAMERA | RS_BUTTON_MOVEMENT | RS_BUTTON_GESTURES
 	}EResizeState;
 
 	S32 processWidthDecreased(S32 delta_width);
@@ -112,7 +118,7 @@ class LLBottomTray
 	 * @param - required_width - width which buttons can use to be shrunk. It is a negative value.
 	 * It is increased on the value processed by buttons.
 	 */
-	void processShrinkButtons(S32* required_width);
+	void processShrinkButtons(S32* required_width, S32* buttons_freed_width);
 	void processShrinkButton(EResizeState processed_object_type, S32* required_width);
 
 	/**
@@ -175,6 +181,7 @@ class LLBottomTray
 
 	LLChicletPanel* 	mChicletPanel;
 	LLNotificationChiclet* 	mSysWell;
+	LLPanel*			mSpeakPanel;
 	LLSpeakButton* 		mSpeakBtn;
 	LLNearbyChatBar*	mNearbyChatBar;
 	LLLayoutStack*		mToolbarStack;
diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp
index 51d53b267406beefb09b4721b7b7fa18779b0ab5..54f776ca6a7fa5253e228375a5a189b59cf282bd 100644
--- a/indra/newview/llspeakbutton.cpp
+++ b/indra/newview/llspeakbutton.cpp
@@ -143,6 +143,27 @@ void LLSpeakButton::setShowToolTip(const std::string& msg)
 	mShowBtn->setToolTip(msg);
 }
 
+void LLSpeakButton::setLabelVisible(bool visible)
+{
+	static std::string label_selected = mSpeakBtn->getLabelSelected();
+	static std::string label_unselected = mSpeakBtn->getLabelUnselected();
+
+	if (visible)
+	{
+		mSpeakBtn->setLabelSelected(label_selected);
+		mSpeakBtn->setLabelUnselected(label_unselected);
+	}
+	else
+	{
+		static LLStringExplicit empty_string("");
+		mSpeakBtn->setLabelSelected(empty_string);
+		mSpeakBtn->setLabelUnselected(empty_string);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// PROTECTED SECTION
+//////////////////////////////////////////////////////////////////////////
 void LLSpeakButton::onMouseDown_SpeakBtn()
 {
 	bool down = true;
diff --git a/indra/newview/llspeakbutton.h b/indra/newview/llspeakbutton.h
index 02c8ab38909031b48f48b721f6a38bc326e0bf45..424ee5357a440f7dc6f28897bae4a491099bdde7 100644
--- a/indra/newview/llspeakbutton.h
+++ b/indra/newview/llspeakbutton.h
@@ -67,6 +67,18 @@ class LLSpeakButton : public LLUICtrl
 	void setSpeakToolTip(const std::string& msg);
 	void setShowToolTip(const std::string& msg);
 
+	/**
+	 * Sets visibility of speak button's label according to passed parameter.
+	 *
+	 * It removes label/selected label if "visible" is false and restores otherwise.
+	 *
+	 * @param visible if true - show label and selected label.
+	 * 
+	 * @see mSpeakBtn
+	 * @see LLBottomTray::processShrinkButtons()
+	 */
+	void setLabelVisible(bool visible);
+
 protected:
 	friend class LLUICtrlFactory;
 	LLSpeakButton(const Params& p);
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
index 00711a29e010fb1cb5506ec5b65497f5d7cc6f00..6480469f43f959323958f96e8d7fba2a46832c23 100644
--- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
@@ -60,11 +60,11 @@
          min_height="28"
          width="104"
          top_delta="0"
-         min_width="104"
+         min_width="54"
          name="speak_panel"
          user_resize="false">
           <talk_button
-           follows="right"
+           follows="left|right"
            height="23"
            speak_button.tab_stop="true"
            show_button.tab_stop="true"
diff --git a/indra/newview/skins/default/xui/en/widgets/talk_button.xml b/indra/newview/skins/default/xui/en/widgets/talk_button.xml
index 1d8257fbc8ae0b308d4c09f24a1cdaef40e18dc6..64c2e65a6e0d2902049a3f359a1700967e61314a 100644
--- a/indra/newview/skins/default/xui/en/widgets/talk_button.xml
+++ b/indra/newview/skins/default/xui/en/widgets/talk_button.xml
@@ -6,6 +6,7 @@
     image_unselected="SegmentedBtn_Left_Off"
   -->
   <speak_button
+    follows="left|right" 
     name="left"
     label="Speak"
     label_selected="Speak"
@@ -13,6 +14,7 @@
     tab_stop="false"
     />
   <show_button
+    follows="right" 
     name="right"
     label=""
     left="0"
@@ -25,6 +27,7 @@
     image_unselected="ComboButton_UpOff"
     />
   <monitor
+    follows="right" 
     name="monitor"
     left="0"
     top="18"