diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 4ef4bf996cd11e0b2c57cad7e2e51da3c7222bd0..ade88d27148f6b58b1c20b9773f0c24eea80ae46 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -3250,6 +3250,19 @@ BOOL LLMenuHolderGL::handleRightMouseDown( S32 x, S32 y, MASK mask )
 	return handled;
 }
 
+// This occurs when you mouse-down to spawn a context menu, hold the button 
+// down, move off the menu, then mouse-up.  We want this to close the menu.
+BOOL LLMenuHolderGL::handleRightMouseUp( S32 x, S32 y, MASK mask )
+{
+	BOOL handled = LLView::childrenHandleRightMouseUp(x, y, mask) != NULL;
+	if (!handled)
+	{
+		// clicked off of menu, hide them all
+		hideMenus();
+	}
+	return handled;
+}
+
 void LLMenuHolderGL::reshape(S32 width, S32 height, BOOL called_from_parent)
 {
 	if (width != getRect().getWidth() || height != getRect().getHeight())
@@ -3568,8 +3581,9 @@ static MenuRegistry::Register<LLContextMenu> context_menu_register2("context_men
 LLContextMenu::LLContextMenu(const Params& p)
 :	LLMenuGL(p),
 	mHoveredAnyItem(FALSE),
-	mHoverItem(NULL)
-
+	mHoverItem(NULL),
+	mSpawnMouseX(S32_MAX),  // definitely not inside the window frame
+	mSpawnMouseY(S32_MAX)
 {
 	//setBackgroundVisible(TRUE);
 }
@@ -3580,6 +3594,7 @@ void LLContextMenu::setVisible(BOOL visible)
 		hide();
 }
 
+// Takes cursor position in screen space?
 void LLContextMenu::show(S32 x, S32 y)
 {
 	arrangeAndClear();
@@ -3622,8 +3637,12 @@ void LLContextMenu::show(S32 x, S32 y)
 	const_cast<LLRect&>(getRect()).setCenterAndSize(local_x + width/2, local_y - height/2, width, height);
 	arrange();
 
-	LLView::setVisible(TRUE);
+	// Save click point for detecting cursor moves before mouse-up.
+	// Must be in local coords to compare with mouseUp events.
+	// If the mouse doesn't move, the menu will stay open ala the Mac.
+	screenPointToLocal(x, y, &mSpawnMouseX, &mSpawnMouseY);
 
+	LLView::setVisible(TRUE);
 }
 
 void LLContextMenu::hide()
@@ -3683,58 +3702,8 @@ BOOL LLContextMenu::handleHover( S32 x, S32 y, MASK mask )
 	return handled;
 }
 
-BOOL LLContextMenu::handleMouseDown( S32 x, S32 y, MASK mask )
-{
-	BOOL handled = FALSE;
-	// The click was somewhere within our rectangle
-	LLMenuItemGL *item = getHighlightedItem();
+// handleMouseDown and handleMouseUp are handled by LLMenuGL
 
-	if (item)
-	{
-		// lie to the item about where the click happened
-		// to make sure it's within the item's rectangle
-		handled = item->handleMouseDown( 0, 0, mask );
-	}
-	else 
-	{
-		// call hidemenus to make sure transient selections get cleared
-		((LLMenuHolderGL*)getParent())->hideMenus();
-	}
-
-	// always handle mouse down as mouse up will close open menus
-	return handled;
-}
-BOOL LLContextMenu::handleMouseUp( S32 x, S32 y, MASK mask )
-{
-	BOOL handled = FALSE;
-
-	// The click was somewhere within our rectangle
-	LLMenuItemGL *item = getHighlightedItem();
-
-	if (item)
-	{
-		// lie to the item about where the click happened
-		// to make sure it's within the item's rectangle
-		if (item->getEnabled())
-		{
-			handled = item->handleMouseUp( 0, 0, mask );
-			hide();
-		}
-	}
-	else 
-	{
-		// call hidemenus to make sure transient selections get cleared
-		((LLMenuHolderGL*)getParent())->hideMenus();
-	}
-
-	if (!handled)
-	{
-		// call hidemenus to make sure transient selections get cleared
-		sMenuContainer->hideMenus();
-	}
-
-	return handled;
-}
 
 BOOL LLContextMenu::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
@@ -3770,7 +3739,19 @@ BOOL LLContextMenu::handleRightMouseDown(S32 x, S32 y, MASK mask)
 
 BOOL LLContextMenu::handleRightMouseUp( S32 x, S32 y, MASK mask )
 {
-	// release mouse capture when right mouse button released, and we're past the shrink time
+	const S32 SLOP = 2;
+	S32 spawn_dx = (x - mSpawnMouseX);
+	S32 spawn_dy = (y - mSpawnMouseY);
+	if (-SLOP <= spawn_dx && spawn_dx <= SLOP
+		&& -SLOP <= spawn_dy && spawn_dy <= SLOP)
+	{
+		// we're still inside the slop region from spawning this menu
+		// so interpret the mouse-up as a single-click to show and leave on
+		// screen
+		mSpawnMouseX = S32_MAX;
+		mSpawnMouseY = S32_MAX;
+		return TRUE;
+	}
 
 	S32 local_x = x - getRect().mLeft;
 	S32 local_y = y - getRect().mBottom;
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 897b43a614e5d7c33a7da386657db57dbdab8e1e..7d5cc25e1e88068b234eef6f8190750b07a02cbc 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -662,13 +662,9 @@ class LLContextMenu
 	virtual void	show				(S32 x, S32 y);
 	virtual void	hide				();
 
-	
-
 	virtual BOOL	handleHover			( S32 x, S32 y, MASK mask );
-	virtual BOOL	handleMouseDown		( S32 x, S32 y, MASK mask );
 	virtual BOOL	handleRightMouseDown( S32 x, S32 y, MASK mask );
 	virtual BOOL	handleRightMouseUp	( S32 x, S32 y, MASK mask );
-	virtual BOOL	handleMouseUp		( S32 x, S32 y, MASK mask );
 
 	virtual bool	addChild			(LLView* view, S32 tab_group = 0);
 
@@ -677,6 +673,11 @@ class LLContextMenu
 protected:
 	BOOL			mHoveredAnyItem;
 	LLMenuItemGL*	mHoverItem;
+
+	// Cursor position when the menu was spawned, in menu-local coords
+	// Used to allow single right-click within a slop region to spawn the menu
+	S32				mSpawnMouseX;
+	S32				mSpawnMouseY;
 };
 
 
@@ -756,6 +757,7 @@ class LLMenuHolderGL : public LLPanel
 	virtual void draw();
 	virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
 	virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
+	/*virtual*/ BOOL handleRightMouseUp( S32 x, S32 y, MASK mask );
 
 	virtual const LLRect getMenuRect() const { return getLocalRect(); }
 	virtual BOOL hasVisibleMenu() const;
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index c71ed5ae47f4f1a91ebe8d7ff8e0d553cd124c22..a937f156e86efcb931102dacd28826b1cc284667 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -102,15 +102,19 @@ void LLToolPie::leftMouseCallback(const LLPickInfo& pick_info)
 	LLToolPie::getInstance()->pickLeftMouseDownCallback();
 }
 
+// Spawn context menus on right mouse down so you can drag over and select
+// an item.
 BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
+	// don't pick transparent so users can't "pay" transparent objects
+	gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE, TRUE);
+	// claim not handled so UI focus stays same
 	return FALSE;
 }
 
 BOOL LLToolPie::handleRightMouseUp(S32 x, S32 y, MASK mask)
 {
 	LLToolMgr::getInstance()->clearTransientTool();
-	gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE, TRUE);
 	return LLTool::handleRightMouseUp(x, y, mask);
 }
 
@@ -118,7 +122,7 @@ BOOL LLToolPie::handleRightMouseUp(S32 x, S32 y, MASK mask)
 void LLToolPie::rightMouseCallback(const LLPickInfo& pick_info)
 {
 	LLToolPie::getInstance()->mPick = pick_info;
-	LLToolPie::getInstance()->pickRightMouseUpCallback();
+	LLToolPie::getInstance()->pickRightMouseDownCallback();
 }
 
 // True if you selected an object.
@@ -729,8 +733,8 @@ static ECursorType cursor_from_parcel_media(U8 click_action)
 }
 
 
-// True if you selected an object.
-BOOL LLToolPie::pickRightMouseUpCallback()
+// True if we handled the event.
+BOOL LLToolPie::pickRightMouseDownCallback()
 {
 	S32 x = mPick.mMousePt.mX;
 	S32 y = mPick.mMousePt.mY;
@@ -826,7 +830,7 @@ BOOL LLToolPie::pickRightMouseUpCallback()
 		}
 	}
 
-	LLTool::handleRightMouseUp(x, y, mask);
+	LLTool::handleRightMouseDown(x, y, mask);
 	// We handled the event.
 	return TRUE;
 }
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index 82de2b363e122ed85fdc48cd08b56d3e10da488e..d2437e813d05a4047e6ec0398a8bf43ffc06e4ae 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -75,7 +75,7 @@ class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
 private:
 	BOOL outsideSlop		(S32 x, S32 y, S32 start_x, S32 start_y);
 	BOOL pickLeftMouseDownCallback();
-	BOOL pickRightMouseUpCallback();
+	BOOL pickRightMouseDownCallback();
 	BOOL useClickAction		(MASK mask, LLViewerObject* object,LLViewerObject* parent);
 
 	void showVisualContextMenuEffect();