diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 5cc9add1e2a0bf948d844e13e68037b28a09f629..0ff7557ead620c4cf002eeeace15ff68d02a5f23 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -368,6 +368,22 @@ S32 LLLayoutStack::getDefaultWidth(S32 cur_width)
 	return cur_width;
 }
 
+void LLLayoutStack::movePanel(LLPanel* panel_to_move, LLPanel* target_panel, bool move_to_front)
+{
+	LayoutPanel* embedded_panel_to_move = findEmbeddedPanel(panel_to_move);
+	LayoutPanel* embedded_target_panel = move_to_front ? *mPanels.begin() : findEmbeddedPanel(target_panel);
+
+	if (!embedded_panel_to_move || !embedded_target_panel || embedded_panel_to_move == embedded_target_panel)
+	{
+		llwarns << "One of the panels was not found in stack or NULL was passed instead of valid panel" << llendl;
+		return;
+	}
+	e_panel_list_t::iterator it = std::find(mPanels.begin(), mPanels.end(), embedded_panel_to_move);
+	mPanels.erase(it);
+	it = move_to_front ? mPanels.begin() : std::find(mPanels.begin(), mPanels.end(), embedded_target_panel);
+	mPanels.insert(it, embedded_panel_to_move);
+}
+
 void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, S32 max_width, S32 max_height, BOOL auto_resize, BOOL user_resize, EAnimate animate, S32 index)
 {
 	// panel starts off invisible (collapsed)
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index cd59ee3966f58ad32863cc5deea02169af81d4d9..6fcc8e2ac34a6c092b6155f3ed47fc41f447f44a 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -72,6 +72,11 @@ class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
 	void removePanel(LLPanel* panel);
 	void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
 	S32 getNumPanels() { return mPanels.size(); }
+	/**
+	 * Moves panel_to_move before target_panel inside layout stack (both panels should already be there).
+	 * If move_to_front is true target_panel is ignored and panel_to_move is moved to the beginning of mPanels
+	 */
+	void movePanel(LLPanel* panel_to_move, LLPanel* target_panel, bool move_to_front = false);
 
 	void updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize);
 	void setPanelUserResize(const std::string& panel_name, BOOL user_resize);
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 6ee438723656d303f24fa8ec8b50cb22ac399e03..f3ade83d00cc0b183b1df07a49fa74b2c325086f 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -49,6 +49,48 @@
 #include "lltoolmgr.h"
 #include "llviewerparcelmgr.h"
 
+#include "llviewerwindow.h"
+#include "llsdserialize.h"
+
+// Distance from mouse down on which drag'n'drop should be started.
+#define DRAG_START_DISTANCE 3
+
+static const std::string SORTING_DATA_FILE_NAME = "bottomtray_buttons_order.xml";
+
+LLDefaultChildRegistry::Register<LLBottomtrayButton> bottomtray_button("bottomtray_button");
+
+// LLBottomtrayButton methods
+
+// virtual
+BOOL LLBottomtrayButton::handleHover(S32 x, S32 y, MASK mask)
+{
+	S32 screenX, screenY;
+	localPointToScreen(x, y, &screenX, &screenY);
+	// pass hover to bottomtray
+	LLBottomTray::getInstance()->handleHover(screenX, screenY, mask);
+	return FALSE;
+}
+//virtual
+BOOL LLBottomtrayButton::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+	S32 screenX, screenY;
+	localPointToScreen(x, y, &screenX, &screenY);
+	// pass mouse up to bottomtray
+	LLBottomTray::getInstance()->onDraggableButtonMouseUp(this,screenX, screenY, mask);
+	LLButton::handleMouseUp(x, y, mask);
+	return FALSE;
+}
+//virtual
+BOOL LLBottomtrayButton::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+	S32 screenX, screenY;
+	localPointToScreen(x, y, &screenX, &screenY);
+	// pass mouse up to bottomtray
+	LLBottomTray::getInstance()->onDraggableButtonMouseDown(this,screenX, screenY, mask);
+	LLButton::handleMouseDown(x, y, mask);
+	return FALSE;
+}
+
 static void update_build_button_enable_state()
 {
 	bool can_edit = LLToolMgr::getInstance()->canEdit();
@@ -153,6 +195,10 @@ LLBottomTray::LLBottomTray(const LLSD&)
 ,	mCamButton(NULL)
 ,	mBottomTrayLite(NULL)
 ,	mIsInLiteMode(false)
+,	mDragStarted(false)
+,	mDraggedItem(NULL)
+,	mLandingTab(NULL)
+,	mCheckForDrag(false)
 {
 	// Firstly add ourself to IMSession observers, so we catch session events
 	// before chiclets do that.
@@ -177,6 +223,8 @@ LLBottomTray::LLBottomTray(const LLSD&)
 		mBottomTrayLite->setFollowsAll();
 		mBottomTrayLite->setVisible(FALSE);
 	}
+
+	mImageDragIndication = LLUI::getUIImage(getString("DragIndicationImageName"));
 }
 
 LLBottomTray::~LLBottomTray()
@@ -504,11 +552,253 @@ BOOL LLBottomTray::postBuild()
 	showWellButton(RS_IM_WELL, !LLIMWellWindow::getInstance()->isWindowEmpty());
 	showWellButton(RS_NOTIFICATION_WELL, !LLNotificationWellWindow::getInstance()->isWindowEmpty());
 
+	loadButtonsOrder();
+
 	LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&update_build_button_enable_state));
 
 	return TRUE;
 }
 
+//Drag-n-drop
+
+void LLBottomTray::onDraggableButtonMouseDown(LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
+{
+	if (ctrl == NULL) return;
+	LLView* parent_view = ctrl->getParent();
+	if(parent_view != NULL)
+	{
+		// we actually drag'n'drop panel (not button) in code, so have to find a parent
+		// of button which called this method on mouse down.
+		LLPanel* parent = dynamic_cast<LLPanel*>(parent_view);
+		// It may happen that we clicked not usual button, but button inside widget(speak, gesture)
+		// so we'll need to get a level higher to reach layout panel as a parent.
+		if(parent == NULL) parent = dynamic_cast<LLPanel*>(parent_view->getParent());
+		if (parent && parent->getVisible())
+		{
+			mDraggedItem = parent;
+			mCheckForDrag = true;
+			mStartX = x;
+			mStartY = y;
+		}
+	}
+}
+
+LLPanel* LLBottomTray::findChildPanelByLocalCoords(S32 x, S32 y)
+{
+	LLPanel* ctrl = 0;
+	S32 screenX, screenY;
+	const child_list_t* list = mToolbarStack->getChildList();
+
+	localPointToScreen(x, y, &screenX, &screenY);
+
+	// look for a child panel which contains the point (screenX, screenY) in it's rectangle
+	for (child_list_const_iter_t i = list->begin(); i != list->end(); ++i)
+	{
+		LLRect rect;
+		localRectToScreen((*i)->getRect(), &rect);
+
+		if (rect.pointInRect(screenX, screenY))
+		{
+			ctrl = dynamic_cast<LLPanel*>(*i);
+			break;
+		}
+	}
+
+	return ctrl;
+}
+
+BOOL LLBottomTray::handleHover(S32 x, S32 y, MASK mask)
+{
+	// if mouse down on draggable item was done, check whether we should start DnD
+	if (mCheckForDrag)
+	{
+		// Start drag'n'drop if mouse cursor was dragged away frome mouse down location enough
+		if(sqrt((float)((mStartX-x)*(mStartX-x)+(mStartY-y)*(mStartY-y))) > DRAG_START_DISTANCE)
+		{
+			mDragStarted = true;
+			mCheckForDrag = false;
+		}
+	}
+	if (mDragStarted)
+	{
+		// Check whether the cursor is over draggable area, find which panel it is and set is as
+		// landing tab for drag'n'drop
+		if(isCursorOverDraggableArea(x, y))
+		{
+			LLPanel* panel = findChildPanelByLocalCoords(x,y);
+			if (panel && panel != mDraggedItem) mLandingTab = panel;
+			gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROWDRAG);
+		}
+		else
+		{
+			gViewerWindow->getWindow()->setCursor(UI_CURSOR_NO);
+		}
+	}
+
+	return TRUE;
+}
+
+bool LLBottomTray::isCursorOverDraggableArea(S32 x, S32 y)
+{
+	bool result = getRect().pointInRect(x, y);
+	result = result && mNearbyChatBar->calcScreenRect().mRight < x;
+	result = result && mChicletPanel->calcScreenRect().mRight > x;
+	return result;
+}
+
+void LLBottomTray::updateButtonsOrdersAfterDnD()
+{
+	// *TODO: change implementation of this method to support simplify it
+	// (and according to future possible changes in the way button order is saved between sessions).
+	state_object_map_t::const_iterator it = mStateProcessedObjectMap.begin();
+	state_object_map_t::const_iterator it_end = mStateProcessedObjectMap.end();
+	// Speak button is currently the only draggable button not in mStateProcessedObjectMap,
+	// so if dragged_state is not found in that map, it should be RS_BUTTON_SPEAK. Change this code if any other
+	// exclusions from mStateProcessedObjectMap will become draggable.
+	EResizeState dragged_state = RS_BUTTON_SPEAK;
+	EResizeState landing_state = RS_NORESIZE;
+	bool landing_state_found = false;
+	// Find states for dragged item and landing tab
+	for (; it != it_end; ++it)
+	{
+		if (it->second == mDraggedItem)
+		{
+			dragged_state = it->first;
+		}
+		else if (it->second == mLandingTab)
+		{
+			landing_state = it->first;
+			landing_state_found = true;
+		}
+	}
+	
+	// Update order of buttons according to drag'n'drop
+	mButtonsOrder.erase(std::find(mButtonsOrder.begin(), mButtonsOrder.end(), dragged_state));
+	if (!landing_state_found && mLandingTab == getChild<LLPanel>(PANEL_CHICLET_NAME))
+	{
+		mButtonsOrder.push_back(dragged_state);
+	}
+	else
+	{
+		if (!landing_state_found) landing_state = RS_BUTTON_SPEAK;
+		mButtonsOrder.insert(std::find(mButtonsOrder.begin(), mButtonsOrder.end(), landing_state), dragged_state);
+	}
+	// Synchronize button process order with their order
+	resize_state_vec_t::const_iterator it1 = mButtonsOrder.begin();
+	const resize_state_vec_t::const_iterator it_end1 = mButtonsOrder.end();
+	resize_state_vec_t::iterator it2 = mButtonsProcessOrder.begin();
+	for (; it1 != it_end1; ++it1)
+	{
+		// Skip Speak because it is not in mButtonsProcessOrder(it's the reason why mButtonsOrder was introduced).
+		// If any other draggable items will be added to bottomtray later, they should also be skipped here.
+		if (*it1 != RS_BUTTON_SPEAK)
+		{
+			*it2 = *it1;
+			++it2;
+		}
+	}
+
+	saveButtonsOrder();
+}
+
+void LLBottomTray::saveButtonsOrder()
+{
+	std::string user_dir = gDirUtilp->getLindenUserDir();
+	if (user_dir.empty()) return;
+	
+	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME);
+	LLSD settings_llsd;
+	int i = 0;
+	const resize_state_vec_t::const_iterator it_end = mButtonsOrder.end();
+	// we use numbers as keys for map which is saved in file and contains resize states as its values
+	for (resize_state_vec_t::const_iterator it = mButtonsOrder.begin(); it != it_end; ++it, i++)
+	{
+		std::string str = llformat("%d", i);
+		settings_llsd[str] = *it;		
+	}
+	llofstream file;
+	file.open(filename);
+	LLSDSerialize::toPrettyXML(settings_llsd, file);
+}
+
+void LLBottomTray::loadButtonsOrder()
+{
+	// load per-resident sorting information
+	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME);
+
+	LLSD settings_llsd;
+	llifstream file;
+	file.open(filename);
+	if (!file.is_open()) return;
+	
+	LLSDSerialize::fromXML(settings_llsd, file);
+	
+
+	mButtonsOrder.clear();
+	mButtonsProcessOrder.clear();
+	int i = 0;
+	// getting button order from file
+	for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
+		iter != settings_llsd.endMap(); ++iter, ++i)
+	{
+		std::string str = llformat("%d", i);
+		EResizeState state = (EResizeState)settings_llsd[str].asInteger();
+		mButtonsOrder.push_back(state);
+		// RS_BUTTON_SPEAK is skipped, because it shouldn't be in mButtonsProcessOrder (it does not hide or shrink).
+		if (state != RS_BUTTON_SPEAK)
+		{
+			mButtonsProcessOrder.push_back(state);
+		}		
+	}
+
+	// There are other panels in layout stack order of which is not saved. Also, panels order of which is saved,
+	// are already in layout stack but in wrong order. The most convenient way to place them is moving them 
+	// to front one by one (because in this case we don't have to pass the panel before which we want to insert our
+	// panel to movePanel()). So panels are moved in order from the end of mButtonsOrder vector(reverse iterator is used).
+	const resize_state_vec_t::const_reverse_iterator it_end = mButtonsOrder.rend();
+	// placing panels in layout stack according to button order which we loaded in previous for
+	for (resize_state_vec_t::const_reverse_iterator it = mButtonsOrder.rbegin(); it != it_end; ++it, ++i)
+	{
+		LLPanel* panel_to_move = *it == RS_BUTTON_SPEAK ? mSpeakPanel : mStateProcessedObjectMap[*it];
+		mToolbarStack->movePanel(panel_to_move, NULL, true); // prepend 		
+	}
+	// Nearbychat is not stored in order settings file, but it must be the first of the panels, so moving it
+	// manually here
+	mToolbarStack->movePanel(mNearbyChatBar, NULL, true);
+}
+
+void LLBottomTray::onDraggableButtonMouseUp(LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
+{
+	//if mouse up happened over area where drop is possible, change order of buttons
+	if (mLandingTab != NULL && mDraggedItem != NULL && mDragStarted)
+	{
+		if(isCursorOverDraggableArea(x, y))
+		{
+			// change order of panels in layout stack
+			mToolbarStack->movePanel(mDraggedItem, (LLPanel*)mLandingTab);
+			// change order of buttons in order vectors
+			updateButtonsOrdersAfterDnD();
+		}
+	}
+	gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+	mDragStarted = false;
+	mDraggedItem = NULL;
+	mLandingTab = NULL;
+	mCheckForDrag = false;
+}
+
+void LLBottomTray::draw()
+{
+	LLPanel::draw();
+	if (mLandingTab)
+	{
+		static S32 w = mImageDragIndication->getWidth();
+		static S32 h = mImageDragIndication->getHeight();
+		LLRect rect = mLandingTab->calcScreenRect();
+		mImageDragIndication->draw(rect.mLeft - w/2, rect.getHeight(), w, h);
+	}
+}
+
 bool LLBottomTray::onContextMenuItemEnabled(const LLSD& userdata)
 {
 	std::string item = userdata.asString();
@@ -1181,6 +1471,9 @@ void LLBottomTray::initResizeStateContainers()
 	mButtonsProcessOrder.push_back(RS_BUTTON_WORLD_MAP);
 	mButtonsProcessOrder.push_back(RS_BUTTON_MINI_MAP);
 
+	mButtonsOrder.push_back(RS_BUTTON_SPEAK);
+	mButtonsOrder.insert(mButtonsOrder.end(), mButtonsProcessOrder.begin(), mButtonsProcessOrder.end());
+
 	// init default widths
 
 	// process buttons that can be hidden on resize...
diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h
index bd9d35f209a880ca1cb44449e4140232da438c24..14a29895f594939a7a54115d3662fc938a3ebaa1 100644
--- a/indra/newview/llbottomtray.h
+++ b/indra/newview/llbottomtray.h
@@ -47,6 +47,30 @@ class LLBottomTrayLite;
 extern template class LLBottomTray* LLSingleton<class LLBottomTray>::getInstance();
 #endif
 
+/**
+ * Class for buttons that should have drag'n'drop ability in bottomtray.
+ * These buttons pass mouse events handling to bottomtray.
+ */
+class LLBottomtrayButton : public LLButton
+{
+public:
+	struct Params : public LLInitParam::Block<Params, LLButton::Params>
+	{
+		Params(){}
+	};
+	/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+	/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+	/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+
+protected:
+	LLBottomtrayButton(const Params& p)
+		:	LLButton(p)
+	{
+
+	}
+	friend class LLUICtrlFactory;
+};
+
 class LLBottomTray 
 	: public LLSingleton<LLBottomTray>
 	, public LLPanel
@@ -101,6 +125,18 @@ class LLBottomTray
 	 */
 	LLIMChiclet* createIMChiclet(const LLUUID& session_id);
 
+	// Below are methods that were introduced or overriden in bottomtray to handle drag'n'drop
+
+	virtual void draw();
+
+	/**
+	 * These three methods handle drag'n'drop, they may be called directly from child buttons.
+	 */
+	/*virtual*/ BOOL	handleHover(S32 x, S32 y, MASK mask);
+	void onDraggableButtonMouseDown(LLUICtrl* button, S32 x, S32 y, MASK mask);
+	void onDraggableButtonMouseUp(LLUICtrl* button, S32 x, S32 y, MASK mask);
+
+
 private:
 	typedef enum e_resize_status_type
 	{
@@ -134,6 +170,29 @@ class LLBottomTray
 									| RS_BUTTON_BUILD | RS_BUTTON_SEARCH | RS_BUTTON_WORLD_MAP | RS_BUTTON_MINI_MAP
 	}EResizeState;
 
+	// Below are three methods that were introduced to handle drag'n'drop
+
+	/**
+	 * finds a panel under the specified LOCAL point
+	 */
+	LLPanel* findChildPanelByLocalCoords(S32 x, S32 y);
+
+	/**
+	 * checks whether the cursor is over an area where the dragged button may be dropped
+	 */
+	bool isCursorOverDraggableArea(S32 x, S32 y);
+
+	/**
+	 * Updates process(shrink/show/hide) order of buttons and order in which they'll be stored for further save/load.
+	 * It is called when dragged button is dropped
+	 */
+	void updateButtonsOrdersAfterDnD();
+
+	// saves order of buttons to file on disk
+	void saveButtonsOrder();
+	// reads order of buttons from file on disk
+	void loadButtonsOrder();
+
 	/**
 	 * Updates child controls size and visibility when it is necessary to reduce total width.
 	 *
@@ -360,6 +419,13 @@ class LLBottomTray
 	 * Contains order in which child buttons should be processed in show/hide, extend/shrink methods.
 	 */
 	resize_state_vec_t mButtonsProcessOrder;
+	/**
+	 * Contains order in which child buttons are shown.
+	 * It traces order of all bottomtray buttons that may change place via drag'n'drop and should
+	 * save and load it between sessions. mButtonsProcessOrder is not enough for it because it contains only
+	 * buttons that may be hidden.
+	 */
+	resize_state_vec_t mButtonsOrder;
 
 protected:
 
@@ -381,6 +447,38 @@ class LLBottomTray
 	LLButton*			mMovementButton;
 	LLBottomTrayLite*   mBottomTrayLite;
 	bool                mIsInLiteMode;
+
+	// Drag'n'Drop
+
+	/**
+	 * Is true if mouse down happened on draggable button.
+	 * Set false whether on drag start or on mouse up.
+	 */
+	bool mCheckForDrag;
+	/**
+	 * These two variables hold corrdinates of mouse down on draggable button.
+	 * They are used to compare with current coordinates of cursor and determine whether drag'n'drop should start.
+	 */
+	S32 mStartX;
+	S32 mStartY;
+	/**
+	 * True if drag'n'drop is happening.
+	 */
+	bool mDragStarted;
+
+	/**
+	 * Pointer to panel which is currently dragged (though it seems to user that button is dragged,
+	 * we are changing place of layout panel).
+	 */
+	LLPanel* mDraggedItem;
+	/**
+	 * Panel before which the dragged button will be inserted.
+	 */
+	LLPanel* mLandingTab;
+	/**
+	 * Image used to show position where dragged button will be dropped.
+	 */
+	LLUIImage* mImageDragIndication;
 };
 
 #endif // LL_LLBOTTOMPANEL_H
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index 43630c13fd7f9cf5fd2597166a95f0a8e64c26b7..a8e4a759b7a3f1ac1a2e5ee4544c789c038e12bc 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -103,10 +103,10 @@ LLGestureComboList::LLGestureComboList(const LLGestureComboList::Params& p)
 	, mViewAllItemIndex(0)
 	, mGetMoreItemIndex(0)
 {
-	LLButton::Params button_params = p.combo_button;
+	LLBottomtrayButton::Params button_params = p.combo_button;
 	button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT);
 
-	mButton = LLUICtrlFactory::create<LLButton>(button_params);
+	mButton = LLUICtrlFactory::create<LLBottomtrayButton>(button_params);
 	mButton->reshape(getRect().getWidth(),getRect().getHeight());
 	mButton->setCommitCallback(boost::bind(&LLGestureComboList::onButtonCommit, this));
 
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index 955a665624b40f1a8aaaec330072a85c06d4bfe7..cc905736fd315ebe9f6ad479752137845618228e 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -34,6 +34,7 @@
 #include "llvoiceclient.h"
 #include "lloutputmonitorctrl.h"
 #include "llspeakers.h"
+#include "llbottomtray.h"
 
 
 class LLGestureComboList
@@ -43,7 +44,7 @@ class LLGestureComboList
 public:
 	struct Params :	public LLInitParam::Block<Params, LLUICtrl::Params>
 	{
-		Optional<LLButton::Params>			combo_button;
+		Optional<LLBottomtrayButton::Params>			combo_button;
 		Optional<LLScrollListCtrl::Params>	combo_list;
 		
 		Params();
diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp
index b8838346d06a7e265bb80b333dbf80a8c436c60d..3dce66f394d49fef75b17a0e77188d710c656052 100644
--- a/indra/newview/llspeakbutton.cpp
+++ b/indra/newview/llspeakbutton.cpp
@@ -37,6 +37,8 @@
 
 #include "llspeakbutton.h"
 
+#include "llbottomtray.h"
+
 static LLDefaultChildRegistry::Register<LLSpeakButton> t1("talk_button");
 
 //////////////////////////////////////////////////////////////////////////
@@ -67,7 +69,7 @@ void LLSpeakButton::setSpeakBtnEnabled(bool enabled)
 }
 void LLSpeakButton::setFlyoutBtnEnabled(bool enabled)
 {
-	LLButton* show_btn = getChild<LLButton>("speak_flyout_btn");
+	LLButton* show_btn = getChild<LLBottomtrayButton>("speak_flyout_btn");
 	show_btn->setEnabled(enabled);
 }
 
@@ -96,9 +98,9 @@ LLSpeakButton::LLSpeakButton(const Params& p)
 	mSpeakBtn->setMouseUpCallback(boost::bind(&LLSpeakButton::onMouseUp_SpeakBtn, this));
 	mSpeakBtn->setToggleState(FALSE);
 
-	LLButton::Params show_params = p.show_button;
+	LLBottomtrayButton::Params show_params = p.show_button;
 	show_params.rect(show_rect);
-	mShowBtn = LLUICtrlFactory::create<LLButton>(show_params);
+	mShowBtn = LLUICtrlFactory::create<LLBottomtrayButton>(show_params);
 	addChild(mShowBtn);
 	LLTransientFloaterMgr::getInstance()->addControlView(mShowBtn);
 
diff --git a/indra/newview/llspeakbutton.h b/indra/newview/llspeakbutton.h
index ec1d07b6338470b82d609a4dc61a120dbeadd731..2fdf80c1f2fe91257172b1bc8b11d10e237c4dc5 100644
--- a/indra/newview/llspeakbutton.h
+++ b/indra/newview/llspeakbutton.h
@@ -33,6 +33,7 @@
 class LLCallFloater;
 class LLButton;
 class LLOutputMonitorCtrl;
+class LLBottomtrayButton;
 
 /*
  * Button displaying voice chat status. Displays voice chat options when
@@ -44,10 +45,8 @@ class LLSpeakButton : public LLUICtrl
 
 	struct Params :	public LLInitParam::Block<Params, LLUICtrl::Params>
 	{
-		Optional<LLButton::Params>
-			speak_button,
-			show_button;
-
+		Optional<LLButton::Params> speak_button;
+		Optional<LLBottomtrayButton::Params> show_button;
 		Optional<LLOutputMonitorCtrl::Params> monitor;
 
 		Params();
@@ -86,7 +85,7 @@ class LLSpeakButton : public LLUICtrl
 
 private:
 	LLButton*	mSpeakBtn;
-	LLButton*	mShowBtn;
+	LLBottomtrayButton*	mShowBtn;
 	LLHandle<LLFloater> mPrivateCallPanel;
 	LLOutputMonitorCtrl* mOutputMonitor;
 };
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
index 4b622691b383fc34a9dc565c0b6366de2c4200f8..cdd596222d988eae7f2ed032006b9bb37aebe59a 100644
--- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
@@ -11,6 +11,9 @@
  name="bottom_tray"
  top="28"
  width="1310">
+    <string
+     name="DragIndicationImageName"
+     value="Accordion_ArrowOpened_Off" />
     <string
      name="SpeakBtnToolTip"
      value="Turns microphone on/off" />
@@ -135,7 +138,7 @@
          name="movement_panel"
          user_resize="false"
          width="83">
-            <button
+            <bottomtray_button
              follows="left|right"
              height="23"
              image_pressed="PushButton_Press"
@@ -152,7 +155,8 @@
                 <init_callback
                  function="Button.SetDockableFloaterToggle"
                  parameter="moveview" />
-            </button>
+            </bottomtray_button>
+
         </layout_panel>
         <layout_panel
          auto_resize="false"
@@ -165,7 +169,7 @@
          name="cam_panel"
          user_resize="false"
          width="83">
-            <button
+            <bottomtray_button
              follows="left|right"
              height="23"
              image_pressed="PushButton_Press"
@@ -183,7 +187,7 @@
                 <init_callback
                  function="Button.SetDockableFloaterToggle"
                  parameter="camera" />
-            </button>
+            </bottomtray_button>
         </layout_panel>
         <layout_panel
          auto_resize="false"
@@ -195,7 +199,7 @@
          name="snapshot_panel"
          user_resize="false"
          width="39">
-            <button
+            <bottomtray_button
              follows="left|right"
              height="23"
              image_overlay="Snapshot_Off"
@@ -212,7 +216,7 @@
                 <init_callback
                  function="Button.SetFloaterToggle"
                  parameter="snapshot" />
-            </button>
+            </bottomtray_button>
         </layout_panel>
         <layout_panel
          auto_resize="false"
@@ -228,7 +232,7 @@
 <!--*FIX: Build Floater is not opened with default registration. Will be fixed soon.
 Disabled for now.
 -->
-            <button
+            <bottomtray_button
              follows="left|right"
              height="23"
              image_pressed="PushButton_Press"
@@ -246,7 +250,7 @@ Disabled for now.
                 <commit_callback
                  function="Build.Toggle"
                  parameter="build" />
-            </button>
+            </bottomtray_button>
         </layout_panel>
         <layout_panel
          auto_resize="false"
@@ -259,7 +263,7 @@ Disabled for now.
          name="search_btn_panel"
          user_resize="false"
          width="83">
-            <button
+            <bottomtray_button
              follows="left|right"
              height="23"
              image_pressed="PushButton_Press"
@@ -277,7 +281,7 @@ Disabled for now.
                 <init_callback
                  function="Button.SetFloaterToggle"
                  parameter="search" />
-            </button>
+            </bottomtray_button>
         </layout_panel>
         <layout_panel
          auto_resize="false"
@@ -290,7 +294,7 @@ Disabled for now.
          name="world_map_btn_panel"
          user_resize="false"
          width="83">
-            <button
+            <bottomtray_button
              follows="left|right"
              height="23"
              image_pressed="PushButton_Press"
@@ -308,7 +312,7 @@ Disabled for now.
                 <init_callback
                  function="Button.SetFloaterToggle"
                  parameter="world_map" />
-            </button>
+            </bottomtray_button>
         </layout_panel>
         <layout_panel
          auto_resize="false"
@@ -321,7 +325,7 @@ Disabled for now.
          name="mini_map_btn_panel"
          user_resize="false"
          width="83">
-            <button
+            <bottomtray_button
              follows="left|right"
              height="23"
              image_pressed="PushButton_Press"
@@ -339,7 +343,7 @@ Disabled for now.
                 <init_callback
                  function="Button.SetFloaterToggle"
                  parameter="mini_map" />
-            </button>
+            </bottomtray_button>
         </layout_panel>
         <layout_panel
          follows="left|right"