Commits

richard_linden committed 91b76ca

Comments (0)

Files changed (120)

indra/llmath/llcoord.h

 	{}
 	LLCoordGL(S32 x, S32 y) : LLCoord(x, y)
 	{}
+	bool operator==(const LLCoordGL& other) const { return mX == other.mX && mY == other.mY; }
+	bool operator!=(const LLCoordGL& other) const { return !(*this == other); }
 };
 
+//bool operator ==(const LLCoordGL& a, const LLCoordGL& b);
 
 // Window coords include things like window borders,
 // menu regions, etc.
 	{}
 	LLCoordWindow(S32 x, S32 y) : LLCoord(x, y)
 	{}
+	bool operator==(const LLCoordWindow& other) const { return mX == other.mX && mY == other.mY; }
+	bool operator!=(const LLCoordWindow& other) const { return !(*this == other); }
 };
 
 
 	{}
 	LLCoordScreen(S32 x, S32 y) : LLCoord(x, y)
 	{}
+	bool operator==(const LLCoordScreen& other) const { return mX == other.mX && mY == other.mY; }
+	bool operator!=(const LLCoordScreen& other) const { return !(*this == other); }
 };
 
 class LLCoordFont : public LLCoord
 	
 	void set(S32 x, S32 y) { LLCoord::set(x,y); mZ = 0.f; }
 	void set(S32 x, S32 y, F32 z) { mX = x; mY = y; mZ = z; }
+	bool operator==(const LLCoordFont& other) const { return mX == other.mX && mY == other.mY; }
+	bool operator!=(const LLCoordFont& other) const { return !(*this == other); }
 };
 	
 

indra/llplugin/llpluginclassmedia.h

 #ifndef LL_LLPLUGINCLASSMEDIA_H
 #define LL_LLPLUGINCLASSMEDIA_H
 
-#include "llgl.h"
+#include "llgltypes.h"
 #include "llpluginprocessparent.h"
 #include "llrect.h"
 #include "llpluginclassmediaowner.h"

indra/llplugin/llpluginclassmediaowner.h

 #ifndef LL_LLPLUGINCLASSMEDIAOWNER_H
 #define LL_LLPLUGINCLASSMEDIAOWNER_H
 
-#include "llgl.h"
 #include "llpluginprocessparent.h"
 #include "llrect.h"
 #include <queue>

indra/llui/CMakeLists.txt

     lllayoutstack.cpp
     lllineeditor.cpp
     lllistctrl.cpp
+    lllocalcliprect.cpp
     llmenugl.cpp
     llmodaldialog.cpp
     llmultifloater.cpp 
     lltexteditor.cpp
     lltextparser.cpp
     lltransutil.cpp
+    lltooltip.cpp
     llui.cpp
     lluicolortable.cpp
     lluictrl.cpp
     lllazyvalue.h
     lllineeditor.h
     lllistctrl.h
+    lllocalcliprect.h
     llmenugl.h
     llmodaldialog.h
     llmultifloater.h 
     lltextbox.h
     lltexteditor.h
     lltextparser.h
+    lltooltip.h
     lltransutil.h
     lluicolortable.h
     lluiconstants.h

indra/llui/llbutton.cpp

 // virtual
 void LLButton::draw()
 {
+	F32 alpha = getDrawContext().mAlpha;
 	bool flash = FALSE;
 	static LLUICachedControl<F32> button_flash_rate("ButtonFlashRate", 0);
 	static LLUICachedControl<S32> button_flash_count("ButtonFlashCount", 0);
 	// Unselected image assignments
 	S32 local_mouse_x;
 	S32 local_mouse_y;
-	LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y);
+	LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y);
 
 	bool enabled = isInEnabledChain();
 
 	if (hasFocus())
 	{
 		F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
-		drawBorder(imagep, gFocusMgr.getFocusColor(), llround(lerp(1.f, 3.f, lerp_amt)));
+		drawBorder(imagep, gFocusMgr.getFocusColor() % alpha, llround(lerp(1.f, 3.f, lerp_amt)));
 	}
 	
 	if (use_glow_effect)
 		LLColor4 disabled_color = mFadeWhenDisabled ? mDisabledImageColor.get() % 0.5f : mDisabledImageColor.get();
 		if ( mScaleImage)
 		{
-			imagep->draw(getLocalRect(), enabled ? mImageColor.get() : disabled_color  );
+			imagep->draw(getLocalRect(), (enabled ? mImageColor.get() : disabled_color) % alpha  );
 			if (mCurGlowStrength > 0.01f)
 			{
 				gGL.setSceneBlendType(glow_type);
-				imagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % mCurGlowStrength);
+				imagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % (mCurGlowStrength * alpha));
 				gGL.setSceneBlendType(LLRender::BT_ALPHA);
 			}
 		}
 		else
 		{
-			imagep->draw(0, 0, enabled ? mImageColor.get() : disabled_color );
+			imagep->draw(0, 0, (enabled ? mImageColor.get() : disabled_color) % alpha );
 			if (mCurGlowStrength > 0.01f)
 			{
 				gGL.setSceneBlendType(glow_type);
-				imagep->drawSolid(0, 0, glow_color % mCurGlowStrength);
+				imagep->drawSolid(0, 0, glow_color % (mCurGlowStrength * alpha));
 				gGL.setSceneBlendType(LLRender::BT_ALPHA);
 			}
 		}
 		// no image
 		lldebugs << "No image for button " << getName() << llendl;
 		// draw it in pink so we can find it
-		gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1, FALSE);
+		gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1 % alpha, FALSE);
 	}
 
 	// let overlay image and text play well together
 		{
 			overlay_color.mV[VALPHA] = 0.5f;
 		}
+		overlay_color.mV[VALPHA] *= alpha;
 
 		switch(mImageOverlayAlignment)
 		{
 		// Due to U32_MAX is equal to S32 -1 value I have rest this value for non-ellipses mode.
 		// Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars.
 		mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset), 
-			label_color,
+			label_color % alpha,
 			mHAlign, LLFontGL::BOTTOM,
 			LLFontGL::NORMAL,
 			mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW,
 	setImageColor(color);
 }
 
-void LLButton::setAlpha(F32 alpha)
-{
-	LLColor4 temp = mImageColor.get();
-	temp.setAlpha(alpha);
-	mImageColor.set(temp);
-	
-	temp = mDisabledImageColor.get();
-	temp.setAlpha(alpha * 0.5f);
-	mDisabledImageColor.set(temp);
-}
-
 void LLButton::setImageDisabled(LLPointer<LLUIImage> image)
 {
 	mImageDisabled = image;

indra/llui/llbutton.h

 	void			setImageColor(const std::string& color_control);
 	void			setImageColor(const LLColor4& c);
 	/*virtual*/ void	setColor(const LLColor4& c);
-	/*virtual*/ void	setAlpha(F32 alpha);
 
 	void			setImages(const std::string &image_name, const std::string &selected_name);
 	

indra/llui/llcombobox.cpp

 #include "lllineeditor.h"
 #include "v2math.h"
 #include "lluictrlfactory.h"
+#include "lltooltip.h"
 
 // Globals
 S32 LLCOMBOBOX_HEIGHT = 0;
 	}
 }
 
-BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
 {
     std::string tool_tip;
 
 		return TRUE;
 	}
 	
-	if (LLUI::sShowXUINames)
+	tool_tip = getToolTip();
+	if (tool_tip.empty())
 	{
-		tool_tip = getShowNamesToolTip();
-	}
-	else
-	{
-		tool_tip = getToolTip();
-		if (tool_tip.empty())
-		{
-			tool_tip = getSelectedItemLabel();
-		}
+		tool_tip = getSelectedItemLabel();
 	}
 	
 	if( !tool_tip.empty() )
 	{
-		msg = tool_tip;
-
-		// Convert rect local to screen coordinates
-		*sticky_rect_screen = calcScreenRect();
+		LLToolTipMgr::instance().show(LLToolTipParams()
+			.message(tool_tip)
+			.sticky_rect(calcScreenRect()));
 	}
 	return TRUE;
 }

indra/llui/llcombobox.h

 	// LLView interface
 	virtual void	onFocusLost();
 
-	virtual BOOL	handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
+	virtual BOOL	handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
 	virtual BOOL	handleKeyHere(KEY key, MASK mask);
 	virtual BOOL	handleUnicodeCharHere(llwchar uni_char);
 

indra/llui/llfloater.cpp

 	close_callback("close_callback"),
 	can_dock("can_dock", false)
 {
-	name = "floater";
-	// defaults that differ from LLPanel:
-	background_visible = true;
 	visible = false;
 }
 
 	}
 }
 
+// defaults for floater param block pulled from widgets/floater.xml
+static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(&typeid(LLFloater::Params), "floater");
+
 LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
-	:	LLPanel(),
-		mDragHandle(NULL),
-		mTitle(p.title),
-		mShortTitle(p.short_title),
-		mSingleInstance(p.single_instance),
-		mKey(key),
-		mAutoTile(p.auto_tile),
-		mCanTearOff(p.can_tear_off),
-		mCanMinimize(p.can_minimize),
-		mCanClose(p.can_close),
-		mDragOnLeft(p.can_drag_on_left),
-		mResizable(p.can_resize),
-		mMinWidth(p.min_width),
-		mMinHeight(p.min_height),
-		mMinimized(FALSE),
-		mForeground(FALSE),
-		mFirstLook(TRUE),
-		mEditing(FALSE),
-		mButtonScale(1.0f),
-		mAutoFocus(TRUE), // automatically take focus when opened
-		mCanDock(false),
-		mDocked(false),
-		mHasBeenDraggedWhileMinimized(FALSE),
-		mPreviousMinimizedBottom(0),
-		mPreviousMinimizedLeft(0),
-		mNotificationContext(NULL)
+:	LLPanel(),
+	mDragHandle(NULL),
+	mTitle(p.title),
+	mShortTitle(p.short_title),
+	mSingleInstance(p.single_instance),
+	mKey(key),
+	mAutoTile(p.auto_tile),
+	mCanTearOff(p.can_tear_off),
+	mCanMinimize(p.can_minimize),
+	mCanClose(p.can_close),
+	mDragOnLeft(p.can_drag_on_left),
+	mResizable(p.can_resize),
+	mMinWidth(p.min_width),
+	mMinHeight(p.min_height),
+	mMinimized(FALSE),
+	mForeground(FALSE),
+	mFirstLook(TRUE),
+	mEditing(FALSE),
+	mButtonScale(1.0f),
+	mAutoFocus(TRUE), // automatically take focus when opened
+	mCanDock(false),
+	mDocked(false),
+	mHasBeenDraggedWhileMinimized(FALSE),
+	mPreviousMinimizedBottom(0),
+	mPreviousMinimizedLeft(0),
+	mNotificationContext(NULL)
 {
-	static LLUIColor default_background_color = LLUIColorTable::instance().getColor("FloaterDefaultBackgroundColor");
-	static LLUIColor focus_background_color = LLUIColorTable::instance().getColor("FloaterFocusBackgroundColor");
-	
 	mHandle.bind(this);
 	mNotificationContext = new LLFloaterNotificationContext(getHandle());
-	mBgColorAlpha        = default_background_color;
-	mBgColorOpaque       = focus_background_color;
 
 	// Clicks stop here.
 	setMouseOpaque(TRUE);
 
 void LLFloater::applyTitle()
 {
-	if (gNoRender)
-	{
-		return;
-	}
-
 	if (!mDragHandle)
 	{
 		return;
 // virtual
 void LLFloater::draw()
 {
+	F32 alpha = getDrawContext().mAlpha;
 	// draw background
 	if( isBackgroundVisible() )
 	{
 			shadow_color.mV[VALPHA] *= 0.5f;
 		}
 		gl_drop_shadow(left, top, right, bottom, 
-			shadow_color, 
+			shadow_color % alpha, 
 			llround(shadow_offset));
 
 		// No transparent windows in simple UI
 		if (isBackgroundOpaque())
 		{
-			gl_rect_2d( left, top, right, bottom, mBgColorOpaque );
+			gl_rect_2d( left, top, right, bottom, getBackgroundColor() % alpha );
 		}
 		else
 		{
-			gl_rect_2d( left, top, right, bottom, mBgColorAlpha );
+			gl_rect_2d( left, top, right, bottom, getTransparentColor() % alpha );
 		}
 
-		if(gFocusMgr.childHasKeyboardFocus(this) && !getIsChrome() && !getCurrentTitle().empty())
+		if(hasFocus() 
+			&& !getIsChrome() 
+			&& !getCurrentTitle().empty())
 		{
 			static LLUIColor titlebar_focus_color = LLUIColorTable::instance().getColor("TitleBarFocusColor");
 			// draw highlight on title bar to indicate focus.  RDW
 			const LLFontGL* font = LLFontGL::getFontSansSerif();
 			LLRect r = getRect();
 			gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1, 
-				titlebar_focus_color, 0, TRUE);
+				titlebar_focus_color % alpha, 0, TRUE);
 		}
 	}
 
 		static LLUIColor unfocus_border_color = LLUIColorTable::instance().getColor("FloaterUnfocusBorderColor");
 		LLUI::setLineWidth(1.5f);
 		LLColor4 outlineColor = gFocusMgr.childHasKeyboardFocus(this) ? focus_border_color : unfocus_border_color;
-		gl_rect_2d_offset_local(0, getRect().getHeight() + 1, getRect().getWidth() + 1, 0, outlineColor, -LLPANEL_BORDER_WIDTH, FALSE);
+		gl_rect_2d_offset_local(0, getRect().getHeight() + 1, getRect().getWidth() + 1, 0, outlineColor % alpha, -LLPANEL_BORDER_WIDTH, FALSE);
 		LLUI::setLineWidth(1.f);
 	}
 

indra/llui/llfloater.h

 	S32				mPreviousMinimizedBottom;
 	S32				mPreviousMinimizedLeft;
 
-	LLColor4		mBgColorAlpha;
-	LLColor4		mBgColorOpaque;
-
 	LLFloaterNotificationContext* mNotificationContext;
 	LLRootHandle<LLFloater>		mHandle;	
 };

indra/llui/lliconctrl.cpp

 {
 	if( mImagep.notNull() )
 	{
-		mImagep->draw(getLocalRect(), mColor.get() );
+		mImagep->draw(getLocalRect(), mColor.get() % getDrawContext().mAlpha );
 	}
 
 	LLUICtrl::draw();
 }
 
-// virtual 
-void LLIconCtrl::setAlpha(F32 alpha)
-{
-	LLColor4 temp = mColor.get();
-	temp.setAlpha(alpha);
-	mColor.set(temp);
-}
-
 // virtual
 // value might be a string or a UUID
 void LLIconCtrl::setValue(const LLSD& value )

indra/llui/lliconctrl.h

 
 	std::string	getImageName() const;
 
-	/*virtual*/ void	setAlpha(F32 alpha);
-
 	void			setColor(const LLColor4& color) { mColor = color; }
 
 private:

indra/llui/lllayoutstack.cpp

 #include "linden_common.h"
 
 #include "lllayoutstack.h"
+#include "lllocalcliprect.h"
 #include "llresizebar.h"
 #include "llcriticaldamp.h"
 
 				FALSE, output_child);
 
 			LLPanel::Params p;
+			p.mouse_opaque(false);
 			LLPanel* panelp = LLUICtrlFactory::create<LLPanel>(p);
 			LLView* new_child = LLUICtrlFactory::getInstance()->createFromXML(child_node, panelp, LLStringUtil::null, LLPanel::child_registry_t::instance(), output_child);
 			if (new_child)

indra/llui/lllocalcliprect.cpp

+/** 
+* @file lllocalcliprect.cpp
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+* 
+* Copyright (c) 2009, Linden Research, Inc.
+* 
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab.  Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+* 
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+* 
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+* 
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#include "linden_common.h"
+
+#include "lllocalcliprect.h"
+
+#include "llfontgl.h"
+#include "llgl.h"
+#include "llui.h"
+
+#include <stack>
+
+//---------------------------------------------------------------------------
+// LLScreenClipRect
+// implementation class in screen space
+//---------------------------------------------------------------------------
+class LLScreenClipRect
+{
+public:
+	LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE);
+	virtual ~LLScreenClipRect();
+
+private:
+	static void pushClipRect(const LLRect& rect);
+	static void popClipRect();
+	static void updateScissorRegion();
+
+private:
+	LLGLState		mScissorState;
+	BOOL			mEnabled;
+
+	static std::stack<LLRect> sClipRectStack;
+};
+
+/*static*/ std::stack<LLRect> LLScreenClipRect::sClipRectStack;
+
+
+LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled)
+:	mScissorState(GL_SCISSOR_TEST),
+	mEnabled(enabled)
+{
+	if (mEnabled)
+	{
+		pushClipRect(rect);
+	}
+	mScissorState.setEnabled(!sClipRectStack.empty());
+	updateScissorRegion();
+}
+
+LLScreenClipRect::~LLScreenClipRect()
+{
+	if (mEnabled)
+	{
+		popClipRect();
+	}
+	updateScissorRegion();
+}
+
+//static 
+void LLScreenClipRect::pushClipRect(const LLRect& rect)
+{
+	LLRect combined_clip_rect = rect;
+	if (!sClipRectStack.empty())
+	{
+		LLRect top = sClipRectStack.top();
+		combined_clip_rect.intersectWith(top);
+
+		if(combined_clip_rect.isEmpty())
+		{
+			// avoid artifacts where zero area rects show up as lines
+			combined_clip_rect = LLRect::null;
+		}
+	}
+	sClipRectStack.push(combined_clip_rect);
+}
+
+//static 
+void LLScreenClipRect::popClipRect()
+{
+	sClipRectStack.pop();
+}
+
+//static
+void LLScreenClipRect::updateScissorRegion()
+{
+	if (sClipRectStack.empty()) return;
+
+	LLRect rect = sClipRectStack.top();
+	stop_glerror();
+	S32 x,y,w,h;
+	x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]);
+	y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]);
+	w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1;
+	h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1;
+	glScissor( x,y,w,h );
+	stop_glerror();
+}
+
+//---------------------------------------------------------------------------
+// LLLocalClipRect
+//---------------------------------------------------------------------------
+LLLocalClipRect::LLLocalClipRect(const LLRect& rect, BOOL enabled /* = TRUE */)
+{
+	LLRect screen(rect.mLeft + LLFontGL::sCurOrigin.mX, 
+		rect.mTop + LLFontGL::sCurOrigin.mY, 
+		rect.mRight + LLFontGL::sCurOrigin.mX, 
+		rect.mBottom + LLFontGL::sCurOrigin.mY);
+	mScreenClipRect = new LLScreenClipRect(screen, enabled);
+}
+
+LLLocalClipRect::~LLLocalClipRect()
+{
+	delete mScreenClipRect;
+	mScreenClipRect = NULL;
+}

indra/llui/lllocalcliprect.h

+/** 
+* @file lllocalcliprect.h
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+* 
+* Copyright (c) 2009, Linden Research, Inc.
+* 
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab.  Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+* 
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+* 
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+* 
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#ifndef LLLOCALCLIPRECT_H
+#define LLLOCALCLIPRECT_H
+
+#include "llrect.h"		// can't forward declare, it's templated
+
+// Clip rendering to a specific rectangle using GL scissor
+// Just create one of these on the stack:
+// {
+//     LLLocalClipRect(rect);
+//     draw();
+// }
+class LLLocalClipRect
+{
+public:
+	LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
+	~LLLocalClipRect();
+
+private:
+	// implementation class
+	class LLScreenClipRect* mScreenClipRect;
+};
+
+#endif

indra/llui/llmenugl.cpp

 	// If the mouse doesn't move, the menu will stay open ala the Mac.
 	// See also LLContextMenu::show()
 	S32 mouse_x, mouse_y;
-	LLUI::getCursorPositionLocal(menu->getParent(), &mouse_x, &mouse_y);
+	LLUI::getMousePositionLocal(menu->getParent(), &mouse_x, &mouse_y);
 	LLMenuHolderGL::sContextMenuSpawnPos.set(mouse_x,mouse_y);
 
 	const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect();

indra/llui/llpanel.cpp

 
 LLPanel::LLPanel(const LLPanel::Params& p)
 :	LLUICtrl(p),
-	mBgColorAlpha(p.bg_alpha_color().get()),
-	mBgColorOpaque(p.bg_opaque_color().get()),
+	mBgColorAlpha(p.bg_alpha_color()),
+	mBgColorOpaque(p.bg_opaque_color()),
 	mBgVisible(p.background_visible),
 	mBgOpaque(p.background_opaque),
 	mDefaultBtn(NULL),
 	mLabel(p.label),
 	mCommitCallbackRegistrar(false),
 	mEnableCallbackRegistrar(false),
-	mXMLFilename("")
+	mXMLFilename(p.filename)
 {
 	setIsChrome(FALSE);
 
 
 void LLPanel::draw()
 {
+	F32 alpha = getDrawContext().mAlpha;
+
 	// draw background
 	if( mBgVisible )
 	{
 
 		if (mBgOpaque )
 		{
-			gl_rect_2d( left, top, right, bottom, mBgColorOpaque );
+			gl_rect_2d( left, top, right, bottom, mBgColorOpaque.get() % alpha);
 		}
 		else
 		{
-			gl_rect_2d( left, top, right, bottom, mBgColorAlpha );
+			gl_rect_2d( left, top, right, bottom, mBgColorAlpha.get() % alpha);
 		}
 	}
 
 	LLView::draw();
 }
 
-/*virtual*/
-void LLPanel::setAlpha(F32 alpha)
-{
-	mBgColorOpaque.setAlpha(alpha);
-}
-
 void LLPanel::updateDefaultBtn()
 {
 	if( mDefaultBtn)
 	setVisible(p.visible);
 	setEnabled(p.enabled);
 
+	setSoundFlags(p.sound_flags);
+
 	 // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible
 	LLUICtrl::initFromParams(p);
 	
 		child->setColor(color);
 	}
 }
-void LLPanel::childSetAlpha(const std::string& id, F32 alpha)
-{
-	LLUICtrl* child = getChild<LLUICtrl>(id, true);
-	if (child)
-	{
-		child->setAlpha(alpha);
-	}
-}
 
 LLCtrlSelectionInterface* LLPanel::childGetSelectionInterface(const std::string& id) const
 {

indra/llui/llpanel.h

 
 	// From LLFocusableElement
 	/*virtual*/ void	setFocus( BOOL b );
-	virtual void setAlpha(F32 alpha);
-
 	
 	// New virtuals
 	virtual 	void	refresh();	// called in setFocus()
 	void childSetValidate(const std::string& id, boost::function<bool (const LLSD& data)> cb );
 
 	void childSetColor(const std::string& id, const LLColor4& color);
-	void childSetAlpha(const std::string& id, F32 alpha);
 
 	LLCtrlSelectionInterface* childGetSelectionInterface(const std::string& id) const;
 	LLCtrlListInterface* childGetListInterface(const std::string& id) const;
 	virtual void	onOpen(const LLSD& key) {}
 
 	void setXMLFilename(std::string filename) { mXMLFilename = filename; };
+	std::string getXMLFilename() { return mXMLFilename; };
 	
 protected:
 	// Override to set not found list
 	commit_signal_t mVisibleSignal;		// Called when visibility changes, passes new visibility as LLSD()
 	
 private:
-	// Unified error reporting for the child* functions
-	typedef std::set<std::string> expected_members_list_t;
-	mutable expected_members_list_t mExpectedMembers;
-	mutable expected_members_list_t mNewExpectedMembers;
-
-	LLColor4		mBgColorAlpha;
-	LLColor4		mBgColorOpaque;
+	LLUIColor		mBgColorAlpha;
+	LLUIColor		mBgColorOpaque;
 	BOOL			mBgVisible;
 	BOOL			mBgOpaque;
 	LLViewBorder*	mBorder;

indra/llui/llscrollbar.cpp

 
 	S32 local_mouse_x;
 	S32 local_mouse_y;
-	LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y);
+	LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y);
 	BOOL other_captor = gFocusMgr.getMouseCapture() && gFocusMgr.getMouseCapture() != this;
 	BOOL hovered = getEnabled() && !other_captor && (hasMouseCapture() || mThumbRect.pointInRect(local_mouse_x, local_mouse_y));
 	if (hovered)

indra/llui/llscrollcontainer.cpp

 
 #include "llrender.h"
 #include "llcontainerview.h"
+#include "lllocalcliprect.h"
 // #include "llfolderview.h"
 #include "llscrollingpanellist.h"
 #include "llscrollbar.h"

indra/llui/llscrolllistctrl.cpp

 #include "llcheckboxctrl.h"
 #include "llclipboard.h"
 #include "llfocusmgr.h"
+#include "llgl.h"				// LLGLSUIDefault()
+#include "lllocalcliprect.h"
 //#include "llrender.h"
 #include "llresmgr.h"
 #include "llscrollbar.h"
 #include "llcachename.h"
 #include "llmenugl.h"
 #include "llurlaction.h"
+#include "lltooltip.h"
 
 #include <boost/bind.hpp>
 
 	return handled;
 }
 
-BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
 {
 	S32 column_index = getColumnIndexFromOffset(x);
 	LLScrollListColumn* columnp = getColumn(column_index);
 			LLRect cell_rect;
 			cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->getWidth(), mLineHeight);
 			// Convert rect local to screen coordinates
-			localRectToScreen(cell_rect, sticky_rect_screen);
-			msg = hit_cell->getValue().asString();
+			LLRect sticky_rect;
+			localRectToScreen(cell_rect, &sticky_rect);
+			LLToolTipMgr::instance().show(LLToolTipParams()
+				.message(hit_cell->getValue().asString())
+				.sticky_rect(sticky_rect));		
 		}
 		handled = TRUE;
 	}
 	LLScrollColumnHeader* headerp = columnp->mHeader;
 	if (headerp && !handled)
 	{
-		headerp->handleToolTip(x, y, msg, sticky_rect_screen);
-		handled = !msg.empty();
+		handled = headerp->handleToolTip(x, y, msg, sticky_rect_screen);
 	}
 
 	return handled;

indra/llui/llscrolllistctrl.h

 	/*virtual*/ BOOL	handleKeyHere(KEY key, MASK mask);
 	/*virtual*/ BOOL	handleUnicodeCharHere(llwchar uni_char);
 	/*virtual*/ BOOL	handleScrollWheel(S32 x, S32 y, S32 clicks);
-	/*virtual*/ BOOL	handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
+	/*virtual*/ BOOL	handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
 	/*virtual*/ void	setEnabled(BOOL enabled);
 	/*virtual*/ void	setFocus( BOOL b );
 	/*virtual*/ void	onFocusReceived();

indra/llui/llsdparam.cpp

 	mNameStack.clear();
 	setParseSilently(silent);
 
-	// must have named elements at top level to submit for parsing
-	if (sd.isMap())
-	{
-		readSDValues(sd, block);
-	}
-	else
-	{
-		parserWarning("Top level map required for LLSD->Block conversion");
-	}
+	readSDValues(sd, block);
 }
 
 void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)

indra/llui/llslider.cpp

 
 void LLSlider::draw()
 {
+	F32 alpha = getDrawContext().mAlpha;
+
 	// since thumb image might still be decoding, need thumb to accomodate image size
 	updateThumbRect();
 
 						getRect().getWidth() - mThumbImage->getWidth() / 2, 
 						getLocalRect().getCenterY() - (mTrackImage->getHeight() / 2) );
 	LLRect highlight_rect(track_rect.mLeft, track_rect.mTop, mThumbRect.getCenterX(), track_rect.mBottom);
-	mTrackImage->draw(track_rect);
-	mTrackHighlightImage->draw(highlight_rect);
+	mTrackImage->draw(track_rect, LLColor4::white % alpha);
+	mTrackHighlightImage->draw(highlight_rect, LLColor4::white % alpha);
 
 	// Thumb
 	if (hasFocus())
 	{
 		// Draw focus highlighting.
-		mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
+		mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor() % alpha, gFocusMgr.getFocusFlashWidth());
 	}
 
 	if( hasMouseCapture() ) // currently clicking on slider
 		// Show ghost where thumb was before dragging began.
 		if (mThumbImage.notNull())
 		{
-			mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f);
+			mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor.get() % (0.3f * alpha));
 		}
 		if (mThumbImagePressed.notNull())
 		{
-			mThumbImagePressed->draw(mThumbRect, mThumbOutlineColor);
+			mThumbImagePressed->draw(mThumbRect, mThumbOutlineColor % alpha);
 		}
 	}
 	else if (!isInEnabledChain())
 	{
 		if (mThumbImageDisabled.notNull())
 		{
-			mThumbImageDisabled->draw(mThumbRect, mThumbCenterColor);
+			mThumbImageDisabled->draw(mThumbRect, mThumbCenterColor % alpha);
 		}
 	}
 	else
 	{
 		if (mThumbImage.notNull())
 		{
-			mThumbImage->draw(mThumbRect, mThumbCenterColor);
+			mThumbImage->draw(mThumbRect, mThumbCenterColor % alpha);
 		}
 	}
 	

indra/llui/lltabcontainer.cpp

  */
 
 #include "linden_common.h"
+
 #include "lltabcontainer.h"
+
 #include "llfocusmgr.h"
 #include "llbutton.h"
+#include "lllocalcliprect.h"
 #include "llrect.h"
 #include "llresizehandle.h"
 #include "lltextbox.h"
 }
 
 // virtual
-BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect )
+BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect& sticky_rect )
 {
 	static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
 	BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect );
 {
 	BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
 
-	if( mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
+	if( mDragAndDropDelayTimer.getStarted() && mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
 	{
 		if (has_scroll_arrows)
 		{

indra/llui/lltabcontainer.h

 	/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );
 	/*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask );
 	/*virtual*/ BOOL handleMouseUp( S32 x, S32 y, MASK mask );
-	/*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect );
+	/*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect );
 	/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
 	/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,	BOOL drop,
 									   EDragAndDropType type, void* cargo_data,

indra/llui/lltextbase.cpp

 #include "llview.h"
 #include "llwindow.h"
 #include "llmenugl.h"
+#include "lltooltip.h"
 #include "lluictrl.h"
 #include "llurlaction.h"
 #include "llurlregistry.h"
 	return FALSE;
 }
 
-BOOL LLTextBase::handleToolTipForUrl(LLView *view, S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLTextBase::handleToolTipForUrl(LLView *view, S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
 {
+	std::string tooltip_msg;
 	const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
-	if (cur_segment && cur_segment->getToolTip( msg ) && view)
+	if (cur_segment && cur_segment->getToolTip( tooltip_msg ) && view)
 	{
 		// Use a slop area around the cursor
 		const S32 SLOP = 8;
 		// Convert rect local to screen coordinates
-		view->localPointToScreen(x - SLOP, y - SLOP, &(sticky_rect_screen->mLeft),
-								 &(sticky_rect_screen->mBottom));
-		sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP;
-		sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP;
+		view->localPointToScreen(x - SLOP, y - SLOP, &(sticky_rect_screen.mLeft),
+								 &(sticky_rect_screen.mBottom));
+		sticky_rect_screen.mRight = sticky_rect_screen.mLeft + 2 * SLOP;
+		sticky_rect_screen.mTop = sticky_rect_screen.mBottom + 2 * SLOP;
+
+		LLToolTipMgr::instance().show(LLToolTipParams()
+			.message(tooltip_msg)
+			.sticky_rect(sticky_rect_screen));
 	}
 	return TRUE;
 }

indra/llui/lltextbase.h

 	BOOL                handleHoverOverUrl(S32 x, S32 y);
 	BOOL                handleMouseUpOverUrl(S32 x, S32 y);
 	BOOL                handleRightMouseDownOverUrl(LLView *view, S32 x, S32 y);
-	BOOL                handleToolTipForUrl(LLView *view, S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen);
+	BOOL                handleToolTipForUrl(LLView *view, S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
 
 	// pure virtuals that have to be implemented by any subclasses
 	virtual S32         getLineCount() const = 0;

indra/llui/lltextbox.cpp

 	drop_shadow_visible("drop_shadow_visible"),
 	disabled_color("disabled_color"),
 	background_color("background_color"),
-	border_color("border_color"),
 	v_pad("v_pad", 0),
 	h_pad("h_pad", 0),
 	line_spacing("line_spacing", 0),
 	mTextColor(p.text_color()),
 	mDisabledColor(p.disabled_color()),
 	mBackgroundColor(p.background_color()),
-	mBorderColor(p.border_color()),
 	mHAlign(p.font_halign),
 	mLineSpacing(p.line_spacing),
 	mDidWordWrap(FALSE)
 	return LLView::handleHover(x,y,mask);
 }
 
-BOOL LLTextBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLTextBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
 {
 	return handleToolTipForUrl(this, x, y, msg, sticky_rect_screen);
 }
 
 void LLTextBox::draw()
 {
+	F32 alpha = getDrawContext().mAlpha;
+
 	if (mBorderVisible)
 	{
 		gl_rect_2d_offset_local(getLocalRect(), 2, FALSE);
 		static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow");
 		static LLUICachedControl<S32> drop_shadow_tooltip ("DropShadowTooltip", 0);
 		gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
-			color_drop_shadow, drop_shadow_tooltip);
+			color_drop_shadow % alpha, drop_shadow_tooltip);
 	}
 
 	if (mBackgroundVisible)
 	{
 		LLRect r( 0, getRect().getHeight(), getRect().getWidth(), 0 );
-		gl_rect_2d( r, mBackgroundColor.get() );
+		gl_rect_2d( r, mBackgroundColor.get() % alpha );
 	}
 
 	S32 text_x = 0;
 
 void LLTextBox::drawText( S32 x, S32 y, const LLWString &text, const LLColor4& color )
 {
+	F32 alpha = getDrawContext().mAlpha;
 	if (mSegments.size() > 1)
 	{
 		// we have Urls (or other multi-styled segments)
 	else if( mLineLengthList.empty() )
 	{
 		// simple case of 1 line of text in one style
-		mDefaultFont->render(text, 0, (F32)x, (F32)y, color,
+		mDefaultFont->render(text, 0, (F32)x, (F32)y, color % alpha,
 							 mHAlign, mVAlign, 
 							 0,
 							 mShadowType,
 			iter != mLineLengthList.end(); ++iter)
 		{
 			S32 line_length = *iter;
-			mDefaultFont->render(text, cur_pos, (F32)x, (F32)y, color,
+			mDefaultFont->render(text, cur_pos, (F32)x, (F32)y, color % alpha,
 								 mHAlign, mVAlign,
 								 0,
 								 mShadowType,
 
 void LLTextBox::reshapeToFitText()
 {
+	// wrap remaining lines that did not fit on call to setWrappedText()
+	setLineLengths();
+
 	S32 width = getTextPixelWidth();
 	S32 height = getTextPixelHeight();
 	reshape( width + 2 * mHPad, height + 2 * mVPad );
 
 void LLTextBox::drawTextSegments(S32 init_x, S32 init_y, const LLWString &text)
 {
+	F32 alpha = getDrawContext().mAlpha;
+
 	const S32 text_len = text.length();
 	if (text_len <= 0)
 	{
 					{
 						color = mDisabledColor.get();
 					}
+					color = color % alpha;
 
 					// render a single line worth for this segment
 					mDefaultFont->render(text, seg_start, text_x, text_y, color,

indra/llui/lltextbox.h

 
 		Optional<LLUIColor>	text_color,
 							disabled_color,
-							background_color,
-							border_color;
+							background_color;
 
 		Optional<S32>		v_pad,
 							h_pad,
 	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleHover(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleRightMouseDown(S32 x, S32 y, MASK mask);
-	virtual BOOL	handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen);
+	virtual BOOL	handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen);
 
 	void			setColor( const LLColor4& c )			{ mTextColor = c; }
 	void			setDisabledColor( const LLColor4& c)	{ mDisabledColor = c; }
 	void			setBackgroundColor( const LLColor4& c)	{ mBackgroundColor = c; }	
-	void			setBorderColor( const LLColor4& c)		{ mBorderColor = c; }	
 
 	void			setText( const LLStringExplicit& text );
 	void			setWrappedText(const LLStringExplicit& text, F32 max_width = -1.f); // -1 means use existing control width

indra/llui/lltexteditor.cpp

 
 #include "llfontfreetype.h" // for LLFontFreetype::FIRST_CHAR
 #include "llfontgl.h"
+#include "llgl.h"			// LLGLSUIDefault()
+#include "lllocalcliprect.h"
 #include "llrender.h"
 #include "llui.h"
 #include "lluictrlfactory.h"
 #include "llscrollcontainer.h"
 #include "llpanel.h"
 #include "llurlregistry.h"
+#include "lltooltip.h"
 
 #include <queue>
 #include "llcombobox.h"
 }
 
 
-BOOL LLTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
 {
-	for ( child_list_const_iter_t child_it = getChildList()->begin();
-		  child_it != getChildList()->end(); ++child_it)
-	{
-		LLView* viewp = *child_it;
-		S32 local_x = x - viewp->getRect().mLeft;
-		S32 local_y = y - viewp->getRect().mBottom;
-		if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
-		{
-			return TRUE;
-		}
+	if (childrenHandleToolTip(x, y, msg, sticky_rect_screen))
+	{
+		return TRUE;
 	}
 
 	return handleToolTipForUrl(this, x, y, msg, sticky_rect_screen);
 
 	mDocumentPanel->setBackgroundColor(bg_color);
 
-	drawChildren();
+	LLView::draw();
 	drawBackground(); //overlays scrolling panel bg
 	drawLineNumbers();
 

indra/llui/lltexteditor.h

 	virtual BOOL	handleKeyHere(KEY key, MASK mask );
 	virtual BOOL	handleUnicodeCharHere(llwchar uni_char);
 
-	virtual BOOL	handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
+	virtual BOOL	handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect);
 	virtual BOOL	handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 									  EDragAndDropType cargo_type, void *cargo_data,
 									  EAcceptance *accept, std::string& tooltip_msg);

indra/llui/lltooltip.cpp

+/** 
+ * @file lltooltip.cpp
+ * @brief LLToolTipMgr class implementation and related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// self include
+#include "lltooltip.h"
+
+// Library includes
+#include "llpanel.h"
+#include "lltextbox.h"
+#include "lliconctrl.h"
+#include "llui.h"			// positionViewNearMouse()
+#include "llwindow.h"
+
+//
+// Constants
+//
+const F32 DELAY_BEFORE_SHOW_TIP = 0.35f;
+
+//
+// Local globals
+//
+
+LLToolTipView *gToolTipView = NULL;
+
+//
+// Member functions
+//
+
+LLToolTipView::LLToolTipView(const LLToolTipView::Params& p)
+:	LLView(p)
+{
+}
+
+void LLToolTipView::draw()
+{
+	if (LLUI::getWindow()->isCursorHidden() )
+	{
+		LLToolTipMgr::instance().hideToolTips();
+	}
+
+	// do the usual thing
+	LLView::draw();
+}
+
+BOOL LLToolTipView::handleHover(S32 x, S32 y, MASK mask)
+{
+	static S32 last_x = x;
+	static S32 last_y = y;
+
+	LLToolTipMgr& tooltip_mgr = LLToolTipMgr::instance();
+
+	// hide existing tooltips when mouse moves out of sticky rect
+	if (tooltip_mgr.toolTipVisible() 
+		&& !tooltip_mgr.getStickyRect().pointInRect(x, y))
+	{
+		tooltip_mgr.hideToolTips();
+	}
+
+	// allow new tooltips whenever mouse moves
+	if (x != last_x && y != last_y)
+	{
+		tooltip_mgr.enableToolTips();
+	}
+
+	last_x = x;
+	last_y = y;
+	return LLView::handleHover(x, y, mask);
+}
+
+BOOL LLToolTipView::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+	LLToolTipMgr::instance().hideToolTips();
+	return LLView::handleMouseDown(x, y, mask);
+}
+
+BOOL LLToolTipView::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
+{
+	LLToolTipMgr::instance().hideToolTips();
+	return LLView::handleMiddleMouseDown(x, y, mask);
+}
+
+BOOL LLToolTipView::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+	LLToolTipMgr::instance().hideToolTips();
+	return LLView::handleRightMouseDown(x, y, mask);
+}
+
+
+BOOL LLToolTipView::handleScrollWheel( S32 x, S32 y, S32 clicks )
+{
+	LLToolTipMgr::instance().hideToolTips();
+	return FALSE;
+}
+
+void LLToolTipView::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+	LLToolTipMgr::instance().hideToolTips();
+}
+
+
+void LLToolTipView::drawStickyRect()
+{
+	gl_rect_2d(LLToolTipMgr::instance().getStickyRect(), LLColor4::white, false);
+}
+//
+// LLToolTip
+//
+class LLToolTip : public LLPanel
+{
+public:
+	struct Params : public LLInitParam::Block<Params, LLPanel::Params> 
+	{
+		Mandatory<F32>				visible_time;
+	
+		Optional<LLToolTipParams::click_callback_t>	click_callback;
+		Optional<LLUIImage*>						image;
+
+		Params()
+		{
+			//use_bounding_rect = true;
+		}
+	};
+	/*virtual*/ void draw();
+	/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+
+	/*virtual*/ void setValue(const LLSD& value);
+	/*virtual*/ void setVisible(BOOL visible);
+
+	bool isFading() { return mFadeTimer.getStarted(); }
+
+	LLToolTip(const Params& p);
+
+private:
+	LLTextBox*		mTextBox;
+	LLFrameTimer	mFadeTimer;
+	F32				mVisibleTime;
+	bool			mHasClickCallback;
+};
+
+static LLDefaultChildRegistry::Register<LLToolTip> r("tool_tip");
+
+const S32 TOOLTIP_PADDING = 4;
+
+LLToolTip::LLToolTip(const LLToolTip::Params& p)
+:	LLPanel(p),
+	mVisibleTime(p.visible_time),
+	mHasClickCallback(p.click_callback.isProvided())
+{
+	LLTextBox::Params params;
+	params.text = "tip_text";
+	params.name = params.text;
+	// bake textbox padding into initial rect
+	params.rect = LLRect (TOOLTIP_PADDING, TOOLTIP_PADDING + 1, TOOLTIP_PADDING + 1, TOOLTIP_PADDING);
+	params.follows.flags = FOLLOWS_ALL;
+	params.h_pad = 4;
+	params.v_pad = 2;
+	params.mouse_opaque = false;
+	params.text_color = LLUIColorTable::instance().getColor( "ToolTipTextColor" );
+	params.bg_visible = false;
+	params.font.style = "NORMAL";
+	//params.border_drop_shadow_visible = true;
+	mTextBox = LLUICtrlFactory::create<LLTextBox> (params);
+	addChild(mTextBox);
+
+	if (p.image.isProvided())
+	{
+		LLIconCtrl::Params icon_params;
+		icon_params.name = "tooltip_icon";
+		LLRect icon_rect;
+		const S32 TOOLTIP_ICON_SIZE = 18;
+		icon_rect.setOriginAndSize(TOOLTIP_PADDING, TOOLTIP_PADDING, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
+		icon_params.rect = icon_rect;
+		icon_params.follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM;
+		icon_params.image = p.image;
+		icon_params.mouse_opaque = false;
+		addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_params));
+
+		// move text over to fit image in
+		mTextBox->translate(TOOLTIP_ICON_SIZE,0);
+	}
+
+	if (p.click_callback.isProvided())
+	{
+		setMouseUpCallback(boost::bind(p.click_callback()));
+	}
+}
+
+void LLToolTip::setValue(const LLSD& value)
+{
+	mTextBox->setWrappedText(value.asString());
+	mTextBox->reshapeToFitText();
+
+	// reshape tooltip panel to fit text box
+	LLRect tooltip_rect = calcBoundingRect();
+	tooltip_rect.mTop += TOOLTIP_PADDING;
+	tooltip_rect.mRight += TOOLTIP_PADDING;
+	tooltip_rect.mBottom = 0;
+	tooltip_rect.mLeft = 0;
+
+	setRect(tooltip_rect);
+}
+
+void LLToolTip::setVisible(BOOL visible)
+{
+	// fade out tooltip over time
+	if (!visible)
+	{
+		// don't actually change mVisible state, start fade out transition instead
+		if (!mFadeTimer.getStarted())
+		{
+			mFadeTimer.start();
+		}
+	}
+	else
+	{
+		mFadeTimer.stop();
+		LLPanel::setVisible(TRUE);
+	}
+}
+
+BOOL LLToolTip::handleHover(S32 x, S32 y, MASK mask)
+{
+	LLPanel::handleHover(x, y, mask);
+	if (mHasClickCallback)
+	{
+		getWindow()->setCursor(UI_CURSOR_HAND);
+	}
+	return TRUE;
+}
+
+void LLToolTip::draw()
+{
+	F32 alpha = 1.f;
+
+	if (LLUI::getMouseIdleTime() > mVisibleTime)
+	{
+		LLToolTipMgr::instance().hideToolTips();
+	}
+
+	if (mFadeTimer.getStarted())
+	{
+		F32 tool_tip_fade_time = LLUI::sSettingGroups["config"]->getF32("ToolTipFadeTime");
+		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time, 1.f, 0.f);
+		if (alpha == 0.f)
+		{
+			// finished fading out, so hide ourselves
+			mFadeTimer.stop();
+			LLPanel::setVisible(false);
+		}
+	}
+
+	// draw tooltip contents with appropriate alpha
+	{
+		LLViewDrawContext context(alpha);
+		LLPanel::draw();
+	}
+}
+
+
+
+//
+// LLToolTipMgr
+//
+LLToolTipParams::LLToolTipParams()
+:	pos("pos"),
+	message("message"),
+	delay_time("delay_time", LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" )),
+	visible_time("visible_time", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTime" )),
+	sticky_rect("sticky_rect"),
+	width("width", 200),
+	image("image")
+{}
+
+LLToolTipMgr::LLToolTipMgr()
+:	mToolTip(NULL)
+{
+}
+
+LLToolTip* LLToolTipMgr::createToolTip(const LLToolTipParams& params)
+{
+	S32 mouse_x;
+	S32 mouse_y;
+	LLUI::getMousePositionLocal(gToolTipView->getParent(), &mouse_x, &mouse_y);
+
+
+	LLToolTip::Params tooltip_params;
+	tooltip_params.name = "tooltip";
+	tooltip_params.mouse_opaque = true;
+	tooltip_params.rect = LLRect (0, 1, 1, 0);
+	tooltip_params.bg_opaque_color = LLUIColorTable::instance().getColor( "ToolTipBgColor" );
+	tooltip_params.background_visible = true;
+	tooltip_params.visible_time = params.visible_time;
+	if (params.image.isProvided())
+	{
+		tooltip_params.image = params.image;
+	}
+	if (params.click_callback.isProvided())
+	{
+		tooltip_params.click_callback = params.click_callback;
+	}
+
+	LLToolTip* tooltip = LLUICtrlFactory::create<LLToolTip> (tooltip_params);
+
+	// make tooltip fixed width and tall enough to fit text
+	tooltip->reshape(params.width, 2000);
+	tooltip->setValue(params.message());
+	gToolTipView->addChild(tooltip);
+
+	if (params.pos.isProvided())
+	{
+		// try to spawn at requested position
+		LLUI::positionViewNearMouse(tooltip, params.pos.x, params.pos.y);
+	}
+	else
+	{
+		// just spawn at mouse location
+		LLUI::positionViewNearMouse(tooltip);
+	}
+
+	//...update "sticky" rect and tooltip position
+	if (params.sticky_rect.isProvided())
+	{
+		mToolTipStickyRect = params.sticky_rect;
+	}
+	else
+	{
+		// otherwise just use one pixel rect around mouse cursor
+		mToolTipStickyRect.setOriginAndSize(mouse_x, mouse_y, 1, 1);
+	}
+	
+	if (params.click_callback.isProvided())
+	{
+		// keep tooltip up when we mouse over it
+		mToolTipStickyRect.unionWith(tooltip->getRect());
+	}
+
+	return tooltip;
+}
+
+
+void LLToolTipMgr::show(const std::string& msg)
+{
+	show(LLToolTipParams().message(msg));
+}
+
+void LLToolTipMgr::show(const LLToolTipParams& params)
+{
+	if (!params.validateBlock()) 
+	{
+		llwarns << "Could not display tooltip!" << llendl;
+		return;
+	}
+	
+	bool tooltip_shown =	mToolTip 
+							&& mToolTip->getVisible() 
+							&& !mToolTip->isFading();
+
+	// if tooltip contents change, hide existing tooltip
+	if (tooltip_shown && mLastToolTipMessage != params.message())
+	{
+		hideToolTips();
+	}
+
+	if (!mToolTipsBlocked									// we haven't hit a key, moved the mouse, etc.
+		&& LLUI::getMouseIdleTime() > params.delay_time		// the mouse has been still long enough
+		&& !tooltip_shown)									// tooltip not visible
+	{
+		// create new tooltip at mouse cursor position
+		delete mToolTip;
+		mToolTip = createToolTip(params);
+
+		// remember this tooltip so we know when it changes
+		mLastToolTipMessage = params.message();
+	}
+}
+
+// allow new tooltips to be created, e.g. after mouse has moved
+void LLToolTipMgr::enableToolTips()
+{
+	mToolTipsBlocked = false;
+}
+
+void LLToolTipMgr::hideToolTips() 
+{ 
+	mToolTipsBlocked = true; 
+	if (mToolTip)
+	{
+		mToolTip->setVisible(FALSE);
+	}
+}
+
+bool LLToolTipMgr::toolTipVisible()
+{
+	return mToolTip ? mToolTip->getVisible() : false;
+}
+
+LLRect LLToolTipMgr::getToolTipRect()
+{
+	if (mToolTip && mToolTip->getVisible())
+	{
+		return mToolTip->getRect();
+	}
+	return LLRect();
+}
+
+
+LLRect LLToolTipMgr::getStickyRect() 
+{ 
+	if (!mToolTip) return LLRect();
+
+	return mToolTip->isInVisibleChain() ? mToolTipStickyRect : LLRect(); 
+}
+
+// EOF

indra/llui/lltooltip.h

+/** 
+ * @file lltooltip.h
+ * @brief LLToolTipMgr class definition and related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTOOLTIP_H
+#define LL_LLTOOLTIP_H
+
+// Library includes
+#include "llsingleton.h"
+#include "llinitparam.h"
+#include "llview.h"
+
+//
+// Classes
+//
+class LLToolTipView : public LLView
+{
+public:
+	struct Params : public LLInitParam::Block<Params, LLView::Params>
+	{
+		Params()
+		{
+			mouse_opaque = false;
+		}
+	};
+	LLToolTipView(const LLToolTipView::Params&);
+	/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+	/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+	/*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
+	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+	/*virtual*/ BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
+
+	/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
+
+	void drawStickyRect();
+
+	/*virtual*/ void draw();
+};
+
+struct LLToolTipPosParams : public LLInitParam::Block<LLToolTipPosParams>
+{
+	Mandatory<S32>		x, 
+						y;
+	LLToolTipPosParams()
+	:	x("x"),
+		y("y")
+	{}
+};
+
+struct LLToolTipParams : public LLInitParam::Block<LLToolTipParams>
+{
+	typedef boost::function<void(void)> click_callback_t;
+
+	Mandatory<std::string>		message;
+	
+	Optional<LLToolTipPosParams>	pos;
+	Optional<F32>					delay_time,
+									visible_time;
+	Optional<LLRect>				sticky_rect;
+	Optional<S32>					width;
+	Optional<LLUIImage*>			image;
+
+	Optional<click_callback_t>		click_callback;
+
+	LLToolTipParams();
+	LLToolTipParams(const std::string& message);
+};
+
+class LLToolTipMgr : public LLSingleton<LLToolTipMgr>
+{
+	LOG_CLASS(LLToolTipMgr);
+public:
+	LLToolTipMgr();
+	void show(const LLToolTipParams& params);
+	void show(const std::string& message);
+
+	void enableToolTips();
+	void hideToolTips();
+	bool toolTipVisible();
+	LLRect getToolTipRect();
+
+	LLRect getStickyRect();
+
+private:
+	class LLToolTip* createToolTip(const LLToolTipParams& params);
+
+	bool				mToolTipsBlocked;
+	class LLToolTip*	mToolTip;
+	std::string			mLastToolTipMessage;
+	LLRect				mToolTipStickyRect;
+};
+
+//
+// Globals
+//
+
+extern LLToolTipView *gToolTipView;
+
+#endif

indra/llui/llui.cpp

 #include "llrect.h"
 #include "lldir.h"
 #include "llfontgl.h"
+#include "llgl.h"
 
 // Project includes
 #include "llcontrol.h"
 /*static*/ LLWindow*		LLUI::sWindow = NULL;
 /*static*/ LLHtmlHelp*		LLUI::sHtmlHelp = NULL;
 /*static*/ LLView*			LLUI::sRootView = NULL;
-/*static*/ BOOL            LLUI::sShowXUINames = FALSE;
-/*static*/ std::stack<LLRect> LLScreenClipRect::sClipRectStack;
 
 /*static*/ std::vector<std::string> LLUI::sXUIPaths;
+/*static*/ LLFrameTimer		LLUI::sMouseIdleTimer;
 
 // register filtereditor here
 static LLDefaultChildRegistry::Register<LLFilterEditor> register_filter_editor("filter_editor");
 	gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP);
 }
 
-bool handleShowXUINamesChanged(const LLSD& newvalue)
-{
-	LLUI::sShowXUINames = newvalue.asBoolean();
-	return true;
-}
-
 void LLUI::initClass(const settings_map_t& settings,
 					 LLImageProviderInterface* image_provider,
 					 LLUIAudioCallback audio_callback,
 	sWindow = NULL; // set later in startup
 	LLFontGL::sShadowColor = LLUIColorTable::instance().getColor("ColorDropShadow");
 
-	static LLUICachedControl<bool> show_xui_names ("ShowXUINames", false);
-	LLUI::sShowXUINames = show_xui_names;
-	LLUI::sSettingGroups["config"]->getControl("ShowXUINames")->getSignal()->connect(boost::bind(&handleShowXUINamesChanged, _2));
-	
 	// Callbacks for associating controls with floater visibilty:
 	LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleFloaterInstance, _2));
 	LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Show", boost::bind(&LLFloaterReg::showFloaterInstance, _2));
 }
 
 //static 
-void LLUI::setCursorPositionScreen(S32 x, S32 y)
+void LLUI::setMousePositionScreen(S32 x, S32 y)
 {
 	S32 screen_x, screen_y;
 	screen_x = llround((F32)x * sGLScaleFactor.mV[VX]);
 }
 
 //static 
-void LLUI::setCursorPositionLocal(const LLView* viewp, S32 x, S32 y)
+void LLUI::setMousePositionLocal(const LLView* viewp, S32 x, S32 y)
 {
 	S32 screen_x, screen_y;
 	viewp->localPointToScreen(x, y, &screen_x, &screen_y);
 
-	setCursorPositionScreen(screen_x, screen_y);
+	setMousePositionScreen(screen_x, screen_y);
 }
 
 //static 
-void LLUI::getCursorPositionLocal(const LLView* viewp, S32 *x, S32 *y)
+void LLUI::getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y)
 {
 	LLCoordWindow cursor_pos_window;
 	LLView::getWindow()->getCursorPosition(&cursor_pos_window);
 	return *sSettingGroups["config"]; // default group
 }
 
-LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST), mEnabled(enabled)
+//static
+// spawn_x and spawn_y are top left corner of view in screen GL coordinates
+void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y)
 {
-	if (mEnabled)
+	const S32 CURSOR_HEIGHT = 22;		// Approximate "normal" cursor size
+	const S32 CURSOR_WIDTH = 12;
+
+	LLView* parent = view->getParent();