diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index ab9db303b5b3ddc48c29528f44a150b5446ede5e..d6fe9a20ed27842297ae54203786759214728180 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -5975,7 +5975,7 @@ bool LLAgent::teleportCore(bool is_local)
 	LLFloaterReg::hideInstance("about_land");
 
 	LLViewerParcelMgr::getInstance()->deselectLand();
-	LLViewerMediaFocus::getInstance()->setFocusFace(false, NULL, 0, NULL);
+	LLViewerMediaFocus::getInstance()->clearFocus();
 
 	// Close all pie menus, deselect land, etc.
 	// Don't change the camera until we know teleport succeeded. JC
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index a631314d5bf92d83de4f5d88e46cedc9f032044e..8544d6fb29af266d7861518c03b69f21f63200a7 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1518,7 +1518,6 @@ bool LLAppViewer::cleanup()
 	//Note:
 	//LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()
 	//because some new image might be generated during cleaning up media. --bao
-	LLViewerMediaFocus::cleanupClass();
 	LLViewerMedia::cleanupClass();
 	LLViewerParcelMedia::cleanupClass();
 	gTextureList.shutdown(); // shutdown again in case a callback added something
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index d163ceb30e263024cef1e8b1bf7232a39074a909..61a203f442cf5e057df701e85689f71804be5337 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -4903,7 +4903,6 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
 		{
 			inspect_item_id = inspect_instance->getSelectedUUID();
 		}
-		LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getSelectedUUID();
 		for (S32 pass = 0; pass < 2; pass++)
 		{
 			for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
@@ -4917,11 +4916,7 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
 				{
 					continue;
 				}
-				if (objectp->getID() == focus_item_id)
-				{
-					node->renderOneSilhouette(gFocusMgr.getFocusColor());
-				}
-				else if(objectp->getID() == inspect_item_id)
+				if(objectp->getID() == inspect_item_id)
 				{
 					node->renderOneSilhouette(sHighlightInspectColor);
 				}
@@ -4975,6 +4970,19 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
 		}
 	}
 
+#if 0	
+	// Hilight focused media object
+	{
+		LLViewerObject* objectp = LLViewerMediaFocus::getInstance()->getFocusedObject();
+		if(objectp)
+		{
+			// FIXME: how do I construct a silhouette for an object that's not selected?
+			// Would we need to add another LLObjectSelectionHandle for this purpose?
+			node->renderOneSilhouette(gFocusMgr.getFocusColor());
+		}
+	}
+#endif
+
 	if (for_hud && avatar)
 	{
 		glMatrixMode(GL_PROJECTION);
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index beb16c267ebc4eb86d07c6f912d64b8fda0c8bd5..d472626fabc6dc3c33c0fea5e07fbe752f0bb0b0 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -518,11 +518,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
 
 		if(!object)
 		{
-			// We need to clear media hover flag
-			if (LLViewerMediaFocus::getInstance()->getMouseOverFlag())
-			{
-				LLViewerMediaFocus::getInstance()->setMouseOverFlag(false);
-			}
+			LLViewerMediaFocus::getInstance()->clearHover();
 		}
 	}
 
@@ -1027,7 +1023,6 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
 		pick.mObjectFace < 0 || 
 		pick.mObjectFace >= objectp->getNumTEs()) 
 	{
-		LLSelectMgr::getInstance()->deselect();
 		LLViewerMediaFocus::getInstance()->clearFocus();
 
 		return false;
@@ -1035,11 +1030,7 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
 
 
 
-	// HACK: This is directly referencing an impl name.  BAD!
-	// This can be removed when we have a truly generic media browser that only 
-	// builds an impl based on the type of url it is passed.
-
-	// is media playing on this face?
+	// Does this face have media?
 	const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
 	LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL;
 	viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL;
@@ -1049,11 +1040,9 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
 		&& gSavedSettings.getBOOL("MediaOnAPrimUI")
 		&& media_impl.notNull())
 	{
-		// LLObjectSelectionHandle selection = /*LLViewerMediaFocus::getInstance()->getSelection()*/ LLSelectMgr::getInstance()->getSelection();
-		if (/*! selection->contains(pick.getObject(), pick.mObjectFace)*/
-			! LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) )
+		if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) )
 		{
-			LLViewerMediaFocus::getInstance()->setFocusFace(TRUE, pick.getObject(), pick.mObjectFace, media_impl);
+			LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);
 		}
 		else
 		{
@@ -1065,7 +1054,6 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
 		return true;
 	}
 
-	LLSelectMgr::getInstance()->deselect();
 	LLViewerMediaFocus::getInstance()->clearFocus();
 
 	return false;
@@ -1079,50 +1067,50 @@ bool LLToolPie::handleMediaHover(const LLPickInfo& pick)
 
 	LLPointer<LLViewerObject> objectp = pick.getObject();
 
-	// Early out cases.  Must clear mouse over media focus flag
+	// Early out cases.  Must clear media hover. 
 	// did not hit an object or did not hit a valid face
 	if ( objectp.isNull() ||
 		pick.mObjectFace < 0 || 
 		pick.mObjectFace >= objectp->getNumTEs() )
 	{
-		LLViewerMediaFocus::getInstance()->setMouseOverFlag(false);
+		LLViewerMediaFocus::getInstance()->clearHover();
 		return false;
 	}
 
-
-	// HACK: This is directly referencing an impl name.  BAD!
-	// This can be removed when we have a truly generic media browser that only 
-	// builds an impl based on the type of url it is passed.
-
-	// is media playing on this face?
+	// Does this face have media?
 	const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
 	const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
 	if (mep
 		&& gSavedSettings.getBOOL("MediaOnAPrimUI"))
 	{		
 		viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
-		if(LLViewerMediaFocus::getInstance()->getFocus() && media_impl.notNull())
-		{
-			media_impl->mouseMove(pick.mUVCoords);
-
-			gViewerWindow->setCursor(media_impl->getLastSetCursor());
-		}
-		else
+		
+		if(media_impl.notNull())
 		{
-			gViewerWindow->setCursor(UI_CURSOR_ARROW);
-		}
+			// Update media hover object
+			if (!LLViewerMediaFocus::getInstance()->isHoveringOverFace(objectp, pick.mObjectFace))
+			{
+				LLViewerMediaFocus::getInstance()->setHoverFace(objectp, pick.mObjectFace, media_impl, pick.mNormal);
+			}
+			
+			// If this is the focused media face, send mouse move events.
+			if (LLViewerMediaFocus::getInstance()->isFocusedOnFace(objectp, pick.mObjectFace))
+			{
+				media_impl->mouseMove(pick.mUVCoords);
+				gViewerWindow->setCursor(media_impl->getLastSetCursor());
+			}
+			else
+			{
+				// This is not the focused face -- set the default cursor.
+				gViewerWindow->setCursor(UI_CURSOR_ARROW);
+			}
 
-		// Set mouse over flag if unset
-		if (! LLViewerMediaFocus::getInstance()->getMouseOverFlag())
-		{
-			LLSelectMgr::getInstance()->setHoverObject(objectp, pick.mObjectFace);
-			LLViewerMediaFocus::getInstance()->setMouseOverFlag(true, media_impl);
-			LLViewerMediaFocus::getInstance()->setPickInfo(pick);
+			return true;
 		}
-
-		return true;
 	}
-	LLViewerMediaFocus::getInstance()->setMouseOverFlag(false);
+	
+	// In all other cases, clear media hover.
+	LLViewerMediaFocus::getInstance()->clearHover();
 
 	return false;
 }
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 6a40c767578ed361dd7a62df3731bfd555832607..b8cf3e667ef6ff372b14516bbd2ae51a88a00b88 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -836,7 +836,15 @@ void LLViewerMediaImpl::stop()
 {
 	if(mMediaSource)
 	{
-		mMediaSource->stop();
+		if(mMediaSource->pluginSupportsMediaBrowser())
+		{
+			mMediaSource->browse_stop();
+		}
+		else
+		{
+			mMediaSource->stop();
+		}
+
 		// destroyMediaSource();
 	}
 }
@@ -1008,6 +1016,45 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask)
 
 	return TRUE; 
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateBack()
+{
+	if (mMediaSource)
+	{
+		if(mMediaSource->pluginSupportsMediaTime())
+		{
+			mMediaSource->start(-2.0);
+		}
+		else
+		{
+			mMediaSource->browse_back();
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateForward()
+{
+	if (mMediaSource)
+	{
+		if(mMediaSource->pluginSupportsMediaTime())
+		{
+			mMediaSource->start(2.0);
+		}
+		else
+		{
+			mMediaSource->browse_forward();
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateReload()
+{
+	navigateTo(mMediaURL, "", true, false);
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::navigateHome()
 {
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 37aabcf2d668566a3fccae75c4198b0ba717c106..05c67eda4714a408fe06d3dc56cb7acd71e8afb1 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -141,7 +141,10 @@ class LLViewerMediaImpl
 	void mouseMove(const LLVector2& texture_coords);
 	void mouseLeftDoubleClick(S32 x,S32 y );
 	void mouseCapture();
-
+	
+	void navigateBack();
+	void navigateForward();
+	void navigateReload();
 	void navigateHome();
 	void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false);
 	void navigateStop();
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index d81c332d546bdf54f00d4ebe109688870e56ea32..cad8b5f0ceca7d61f609d01cfda91752936784a1 100644
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -53,7 +53,8 @@
 //
 
 LLViewerMediaFocus::LLViewerMediaFocus()
-: mMouseOverFlag(false)
+:	mFocusedObjectFace(0),
+	mHoverObjectFace(0)
 {
 }
 
@@ -63,110 +64,100 @@ LLViewerMediaFocus::~LLViewerMediaFocus()
 	// Clean up in cleanupClass() instead.
 }
 
-void LLViewerMediaFocus::cleanupClass()
-{
-	LLViewerMediaFocus *self = LLViewerMediaFocus::getInstance();
-	
-	if(self)
-	{
-		// mMediaHUD will have been deleted by this point -- don't try to delete it.
-
-		/* Richard says:
-			all widgets are supposed to be destroyed at the same time
-			you shouldn't hold on to pointer to them outside of ui code		
-			you can use the LLHandle approach
-			if you want to be type safe, you'll need to add a LLRootHandle to whatever derived class you are pointing to
-			look at llview::gethandle
-			its our version of a weak pointer			
-		*/
-		if(self->mMediaHUD.get())
-		{
-			self->mMediaHUD.get()->setMediaImpl(NULL);
-		}
-		self->mMediaImpl = NULL;
-	}
-	
-}
-
-
-void LLViewerMediaFocus::setFocusFace( BOOL b, LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl )
-{
+void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal)
+{	
 	LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-
-	if(mMediaImpl.notNull())
+	
+	LLViewerMediaImpl *old_media_impl = getFocusedMediaImpl();
+	if(old_media_impl)
 	{
-		mMediaImpl->focus(false);
+		old_media_impl->focus(false);
 	}
 
-	if (b && media_impl.notNull())
+	if (media_impl.notNull() && objectp.notNull())
 	{
 		bool face_auto_zoom = false;
-		mMediaImpl = media_impl;
-		mMediaImpl->focus(true);
+		media_impl->focus(true);
 
-		LLSelectMgr::getInstance()->deselectAll();
-		LLSelectMgr::getInstance()->selectObjectOnly(objectp, face);
+		mFocusedImplID = media_impl->getMediaTextureID();
+		mFocusedObjectID = objectp->getID();
+		mFocusedObjectFace = face;
+		mFocusedObjectNormal = pick_normal;
 
-		if(objectp.notNull())
+		LLTextureEntry* tep = objectp->getTE(face);
+		if(tep->hasMedia())
 		{
-			LLTextureEntry* tep = objectp->getTE(face);
-			if(! tep->hasMedia())
-			{
-				// Error condition
-			}
 			LLMediaEntry* mep = tep->getMediaData();
 			face_auto_zoom = mep->getAutoZoom();
-			if(! mep->getAutoPlay())
+			if(!media_impl->hasMedia())
 			{
 				std::string url = mep->getCurrentURL().empty() ? mep->getHomeURL() : mep->getCurrentURL();
 				media_impl->navigateTo(url, "", true);
 			}
 		}
-		mFocus = LLSelectMgr::getInstance()->getSelection();
+		else
+		{
+			// This should never happen.
+			llwarns << "Can't find media entry for focused face" << llendl;
+		}
+
+		gFocusMgr.setKeyboardFocus(this);
+		
+		// We must do this before  processing the media HUD zoom, or it may zoom to the wrong face. 
+		update();
+
 		if(mMediaHUD.get() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom())
 		{
 			mMediaHUD.get()->resetZoomLevel();
 			mMediaHUD.get()->nextZoomLevel();
 		}
-		if (!mFocus->isEmpty())
-		{
-			gFocusMgr.setKeyboardFocus(this);
-		}
-		mObjectID = objectp->getID();
-		mObjectFace = face;
-		// LLViewerMedia::addObserver(this, mObjectID);
-
-
 	}
 	else
 	{
-		gFocusMgr.setKeyboardFocus(NULL);
-		if(! parcel->getMediaPreventCameraZoom())
+		if(hasFocus())
 		{
-			if (!mFocus->isEmpty())
+			if(mMediaHUD.get())
 			{
-				gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+				mMediaHUD.get()->resetZoomLevel();
 			}
+
+			gFocusMgr.setKeyboardFocus(NULL);
 		}
-		mFocus = NULL;
-		// LLViewerMedia::remObserver(this, mObjectID);
 		
-		// Null out the media hud media pointer
-		if(mMediaHUD.get())
-		{
-			mMediaHUD.get()->setMediaImpl(NULL);
-		}
+		mFocusedImplID = LLUUID::null;
+		mFocusedObjectID = LLUUID::null;
+		mFocusedObjectFace = 0;
+	}
+}
 
-		// and null out the media impl
-		mMediaImpl = NULL;
-		mObjectID = LLUUID::null;
-		mObjectFace = 0;
+void LLViewerMediaFocus::clearFocus()
+{
+	setFocusFace(NULL, 0, NULL);
+}
+
+void LLViewerMediaFocus::setHoverFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal)
+{
+	if (media_impl.notNull())
+	{
+		mHoverImplID = media_impl->getMediaTextureID();
+		mHoverObjectID = objectp->getID();
+		mHoverObjectFace = face;
+		mHoverObjectNormal = pick_normal;
 	}
-	if(mMediaHUD.get())
+	else
 	{
-		mMediaHUD.get()->setMediaFocus(b);
+		mHoverObjectID = LLUUID::null;
+		mHoverObjectFace = 0;
+		mHoverImplID = LLUUID::null;
 	}
 }
+
+void LLViewerMediaFocus::clearHover()
+{
+	setHoverFace(NULL, 0, NULL);
+}
+
+
 bool LLViewerMediaFocus::getFocus()
 {
 	if (gFocusMgr.getKeyboardFocus() == this)
@@ -176,22 +167,15 @@ bool LLViewerMediaFocus::getFocus()
 	return false;
 }
 
-// This function selects an ideal viewing distance given a selection bounding box, normal, and padding value
-void LLViewerMediaFocus::setCameraZoom(F32 padding_factor)
+// This function selects an ideal viewing distance based on the focused object, pick normal, and padding value
+void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor)
 {
-	LLPickInfo& pick = LLToolPie::getInstance()->getPick();
-
-	if(LLSelectMgr::getInstance()->getSelection()->isEmpty())
-	{
-		pick = mPickInfo;
-		setFocusFace(true, pick.getObject(), pick.mObjectFace, mMediaImpl);
-	}
-
-	if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
+	if (object)
 	{
 		gAgent.setFocusOnAvatar(FALSE, ANIMATE);
 
-		LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
+		LLBBox bbox = object->getBoundingBoxAgent();
+		LLVector3d center = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
 		F32 height;
 		F32 width;
 		F32 depth;
@@ -199,7 +183,7 @@ void LLViewerMediaFocus::setCameraZoom(F32 padding_factor)
 		F32 distance;
 
 		// We need the aspect ratio, and the 3 components of the bbox as height, width, and depth.
-		F32 aspect_ratio = getBBoxAspectRatio(selection_bbox, pick.mNormal, &height, &width, &depth);
+		F32 aspect_ratio = getBBoxAspectRatio(bbox, normal, &height, &width, &depth);
 		F32 camera_aspect = LLViewerCamera::getInstance()->getAspect();
 
 		// We will normally use the side of the volume aligned with the short side of the screen (i.e. the height for 
@@ -229,9 +213,9 @@ void LLViewerMediaFocus::setCameraZoom(F32 padding_factor)
 		// Finally animate the camera to this new position and focal point
 		LLVector3d camera_pos, target_pos;
 		// The target lookat position is the center of the selection (in global coords)
-		target_pos = LLSelectMgr::getInstance()->getSelectionCenterGlobal();
+		target_pos = center;
 		// Target look-from (camera) position is "distance" away from the target along the normal 
-		LLVector3d pickNormal = LLVector3d(pick.mNormal);
+		LLVector3d pickNormal = LLVector3d(normal);
 		pickNormal.normalize();
         camera_pos = target_pos + pickNormal * distance;
         if (pickNormal == LLVector3d::z_axis || pickNormal == LLVector3d::z_axis_neg)
@@ -255,92 +239,69 @@ void LLViewerMediaFocus::setCameraZoom(F32 padding_factor)
             camera_pos += 0.01 * len * delta;
         }
 
-		gAgent.setCameraPosAndFocusGlobal(camera_pos, target_pos, LLSelectMgr::getInstance()->getSelection()->getFirstObject()->mID );
+		gAgent.setCameraPosAndFocusGlobal(camera_pos, target_pos, object->getID() );
+	}
+	else
+	{
+		// If we have no object, focus back on the avatar.
+		gAgent.setFocusOnAvatar(TRUE, ANIMATE);
 	}
 }
 void LLViewerMediaFocus::onFocusReceived()
 {
-	if(mMediaImpl.notNull())
-		mMediaImpl->focus(true);
+	// Don't do this here -- this doesn't change "inworld media focus", it just changes whether the viewer's input is focused on the media.
+//	LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+//	if(media_impl.notNull())
+//		media_impl->focus(true);
 
 	LLFocusableElement::onFocusReceived();
 }
 
 void LLViewerMediaFocus::onFocusLost()
 {
-	if(mMediaImpl.notNull())
-		mMediaImpl->focus(false);
+	// Don't do this here -- this doesn't change "inworld media focus", it just changes whether the viewer's input is focused on the media.
+//	LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+//	if(media_impl.notNull())
+//		media_impl->focus(false);
+
 	gViewerWindow->focusClient();
-	mFocus = NULL;
 	LLFocusableElement::onFocusLost();
 }
-void LLViewerMediaFocus::setMouseOverFlag(bool b, viewer_media_t media_impl)
+
+BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent)
 {
-	if (b && media_impl.notNull())
+	LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+	if(media_impl)
 	{
-		if(! mMediaHUD.get())
-		{
-			LLPanelMediaHUD* media_hud = new LLPanelMediaHUD(mMediaImpl);
-			mMediaHUD = media_hud->getHandle();
-			gHUDView->addChild(media_hud);	
-		}
-		mMediaHUD.get()->setMediaImpl(media_impl);
+		media_impl->handleKeyHere(key, mask);
 
-		if(mMediaImpl.notNull() && (mMediaImpl != media_impl))
+		if (key == KEY_ESCAPE)
 		{
-			mMediaImpl->focus(false);
+			clearFocus();
 		}
-
-		mMediaImpl = media_impl;
-	}
-	mMouseOverFlag = b;
-}
-LLUUID LLViewerMediaFocus::getSelectedUUID() 
-{ 
-	LLViewerObject* object = mFocus->getFirstObject();
-	return object ? object->getID() : LLUUID::null; 
-}
-#if 0 // Must re-implement when the new media api event system is ready
-void LLViewerMediaFocus::onNavigateComplete( const EventType& event_in )
-{
-	if (hasFocus() && mLastURL != event_in.getStringValue())
-	{
-		LLViewerMedia::focus(true, mObjectID);
-		// spoof mouse event to reassert focus
-		LLViewerMedia::mouseDown(1,1, mObjectID);
-		LLViewerMedia::mouseUp(1,1, mObjectID);
-	}
-	mLastURL = event_in.getStringValue();
-}
-#endif
-BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent)
-{
-	if(mMediaImpl.notNull())
-		mMediaImpl->handleKeyHere(key, mask);
-
-	if (key == KEY_ESCAPE && mMediaHUD.get())
-	{
-		mMediaHUD.get()->close();
 	}
+	
 	return true;
 }
 
 BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
 {
-	if(mMediaImpl.notNull())
-		mMediaImpl->handleUnicodeCharHere(uni_char);
+	LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+	if(media_impl)
+		media_impl->handleUnicodeCharHere(uni_char);
 	return true;
 }
 BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)
 {
 	BOOL retval = FALSE;
-	if(mFocus.notNull() && mMediaImpl.notNull() && mMediaImpl->hasMedia())
+	LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+	if(media_impl && media_impl->hasMedia())
 	{
         // the scrollEvent() API's x and y are not the same as handleScrollWheel's x and y.
         // The latter is the position of the mouse at the time of the event
         // The former is the 'scroll amount' in x and y, respectively.
         // All we have for 'scroll amount' here is 'clicks', and no mask.
-		mMediaImpl->getMediaPlugin()->scrollEvent(0, clicks, /*mask*/0);
+		media_impl->getMediaPlugin()->scrollEvent(0, clicks, /*mask*/0);
 		retval = TRUE;
 	}
 	return retval;
@@ -348,19 +309,45 @@ BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)
 
 void LLViewerMediaFocus::update()
 {
-	if (mMediaHUD.get())
+	LLViewerMediaImpl *media_impl = getFocusedMediaImpl();
+	LLViewerObject *viewer_object = getFocusedObject();
+	S32 face = mFocusedObjectFace;
+	LLVector3 normal = mFocusedObjectNormal;
+	bool focus = true;
+	
+	if(!media_impl || !viewer_object)
+	{
+		focus = false;
+		media_impl = getHoverMediaImpl();
+		viewer_object = getHoverObject();
+		face = mHoverObjectFace;
+		normal = mHoverObjectNormal;
+	}
+	
+	if(media_impl && viewer_object)
 	{
-		if(mFocus.notNull() || mMouseOverFlag || mMediaHUD.get()->isMouseOver())
+		// We have an object and impl to point at.
+		
+		// Make sure the media HUD object exists.
+		if(! mMediaHUD.get())
 		{
-			// mMediaHUD.get()->setVisible(true);
-			mMediaHUD.get()->updateShape();
+			LLPanelMediaHUD* media_hud = new LLPanelMediaHUD();
+			mMediaHUD = media_hud->getHandle();
+			gHUDView->addChild(media_hud);	
 		}
-		else
+		mMediaHUD.get()->setMediaFace(viewer_object, face, media_impl, normal);
+	}
+	else
+	{
+		// The media HUD is no longer needed.
+		if(mMediaHUD.get())
 		{
-			mMediaHUD.get()->setVisible(false);
+			mMediaHUD.get()->setMediaFace(NULL, 0, NULL);
 		}
 	}
 }
+
+
 // This function calculates the aspect ratio and the world aligned components of a selection bounding box.
 F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth)
 {
@@ -429,5 +416,31 @@ F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3&
 
 bool LLViewerMediaFocus::isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face)
 {
-	return objectp->getID() == mObjectID && face == mObjectFace;
+	return objectp->getID() == mFocusedObjectID && face == mFocusedObjectFace;
+}
+
+bool LLViewerMediaFocus::isHoveringOverFace(LLPointer<LLViewerObject> objectp, S32 face)
+{
+	return objectp->getID() == mHoverObjectID && face == mHoverObjectFace;
+}
+
+
+LLViewerMediaImpl* LLViewerMediaFocus::getFocusedMediaImpl()
+{
+	return LLViewerMedia::getMediaImplFromTextureID(mFocusedImplID);
+}
+
+LLViewerObject* LLViewerMediaFocus::getFocusedObject()
+{
+	return gObjectList.findObject(mFocusedObjectID);
+}
+
+LLViewerMediaImpl* LLViewerMediaFocus::getHoverMediaImpl()
+{
+	return LLViewerMedia::getMediaImplFromTextureID(mHoverImplID);
+}
+
+LLViewerObject* LLViewerMediaFocus::getHoverObject()
+{
+	return gObjectList.findObject(mHoverObjectID);
 }
diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
index 2688a8b7087d6827fa70283b0ab1591ca18feaab..d5e3e6019cfe4e4b44e13d1438c4d330c1a32428 100644
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -50,44 +50,55 @@ class LLViewerMediaFocus :
 	LLViewerMediaFocus();
 	~LLViewerMediaFocus();
 	
-	static void cleanupClass();
-
-	void setFocusFace(BOOL b, LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl);
-	void clearFocus() { setFocusFace(false, NULL, 0, NULL); }
+	// Set/clear the face that has media focus (takes keyboard input and has the full set of controls)
+	void setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3d::zero);
+	void clearFocus();
+	
+	// Set/clear the face that has "media hover" (has the mimimal set of controls to zoom in or pop out into a media browser).
+	// If a media face has focus, the media hover will be ignored.
+	void setHoverFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3d::zero);
+	void clearHover();
+	
 	/*virtual*/ bool	getFocus();
-	/*virtual*/ // void onNavigateComplete( const EventType& event_in );
-
 	/*virtual*/ BOOL	handleKey(KEY key, MASK mask, BOOL called_from_parent);
 	/*virtual*/ BOOL	handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
 	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
 
-	LLUUID getSelectedUUID();
-	LLObjectSelectionHandle getSelection() { return mFocus; }
-
 	void update();
+	
+	static void setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor);
+	static F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth);
 
-	void setCameraZoom(F32 padding_factor);
-	void setMouseOverFlag(bool b, viewer_media_t media_impl = NULL);
-	bool getMouseOverFlag() { return mMouseOverFlag; }
-	void setPickInfo(LLPickInfo pick_info) { mPickInfo = pick_info; }
-	F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth);
-
-	// TODO: figure out why selection mgr hates me
 	bool isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face);
+	bool isHoveringOverFace(LLPointer<LLViewerObject> objectp, S32 face);
+	
+	// These look up (by uuid) and return the values that were set with setFocusFace.  They will return null if the objects have been destroyed.
+	LLViewerMediaImpl* getFocusedMediaImpl();
+	LLViewerObject* getFocusedObject();
+	S32 getFocusedFace() { return mFocusedObjectFace; }
+	
+	// These look up (by uuid) and return the values that were set with setHoverFace.  They will return null if the objects have been destroyed.
+	LLViewerMediaImpl* getHoverMediaImpl();
+	LLViewerObject* getHoverObject();
+	S32 getHoverFace() { return mHoverObjectFace; }
 
 protected:
 	/*virtual*/ void	onFocusReceived();
 	/*virtual*/ void	onFocusLost();
 
 private:
-	LLObjectSelectionHandle mFocus;
-	std::string mLastURL;
-	bool mMouseOverFlag;
-	LLPickInfo mPickInfo;
+	
 	LLHandle<LLPanelMediaHUD> mMediaHUD;
-	LLUUID mObjectID;
-	S32 mObjectFace;
-	viewer_media_t mMediaImpl;
+	
+	LLUUID mFocusedObjectID;
+	S32 mFocusedObjectFace;
+	LLUUID mFocusedImplID;
+	LLVector3 mFocusedObjectNormal;
+	
+	LLUUID mHoverObjectID;
+	S32 mHoverObjectFace;
+	LLUUID mHoverImplID;
+	LLVector3 mHoverObjectNormal;
 };