diff --git a/indra/llplugin/slplugin/CMakeLists.txt b/indra/llplugin/slplugin/CMakeLists.txt
index c1536e85de3640350b1f9b556c3d55022f16a953..08d35f9ae7ebd6502d4fe1de832d7b07b02399a9 100644
--- a/indra/llplugin/slplugin/CMakeLists.txt
+++ b/indra/llplugin/slplugin/CMakeLists.txt
@@ -16,6 +16,7 @@ include_directories(
 if (DARWIN)
     include(CMakeFindFrameworks)
     find_library(CARBON_LIBRARY Carbon)
+    find_library(COCOA_LIBRARY Cocoa)
 endif (DARWIN)
 
 
@@ -25,6 +26,22 @@ set(SLPlugin_SOURCE_FILES
     slplugin.cpp
     )
 
+if (DARWIN)
+  list(APPEND SLPlugin_SOURCE_FILES
+    slplugin-objc.mm
+  )
+  list(APPEND SLPlugin_HEADER_FILES
+    slplugin-objc.h
+  )
+endif (DARWIN)
+
+set_source_files_properties(${SLPlugin_HEADER_FILES}
+                            PROPERTIES HEADER_FILE_ONLY TRUE)
+
+if (SLPlugin_HEADER_FILES)
+  list(APPEND SLPlugin_SOURCE_FILES ${SLPlugin_HEADER_FILES})
+endif (SLPlugin_HEADER_FILES)
+
 add_executable(SLPlugin
     WIN32
     MACOSX_BUNDLE
@@ -51,7 +68,7 @@ add_dependencies(SLPlugin
 
 if (DARWIN)
   # Mac version needs to link against Carbon
-  target_link_libraries(SLPlugin ${CARBON_LIBRARY})
+  target_link_libraries(SLPlugin ${CARBON_LIBRARY} ${COCOA_LIBRARY})
   # Make sure the app bundle has a Resources directory (it will get populated by viewer-manifest.py later)
   add_custom_command(
     TARGET SLPlugin POST_BUILD
diff --git a/indra/llplugin/slplugin/slplugin-objc.h b/indra/llplugin/slplugin/slplugin-objc.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e55cb14cf69f46331de916fe4950e311a568bc9
--- /dev/null
+++ b/indra/llplugin/slplugin/slplugin-objc.h
@@ -0,0 +1,40 @@
+/**
+ * @file slplugin-objc.h
+ * @brief Header file for slplugin-objc.mm.
+ *
+ * @cond
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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$
+ *
+ * @endcond
+ */
+
+
+/* Defined in slplugin-objc.mm: */
+void setupCocoa();
+void createAutoReleasePool();
+void deleteAutoReleasePool();
diff --git a/indra/llplugin/slplugin/slplugin-objc.mm b/indra/llplugin/slplugin/slplugin-objc.mm
new file mode 100644
index 0000000000000000000000000000000000000000..823e1ebea6f6f4839f8b07dc9c3ee073ec3c0f3e
--- /dev/null
+++ b/indra/llplugin/slplugin/slplugin-objc.mm
@@ -0,0 +1,87 @@
+/**
+ * @file slplugin-objc.mm
+ * @brief Objective-C++ file for use with the loader shell, so we can use a couple of Cocoa APIs.
+ *
+ * @cond
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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$
+ *
+ * @endcond
+ */
+
+
+#include <AppKit/AppKit.h>
+
+#include "slplugin-objc.h"
+
+
+void setupCocoa()
+{
+	static bool inited = false;
+	
+	if(!inited)
+	{
+		createAutoReleasePool();
+		
+		// The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents.
+		// ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr' 
+		// when init'ing the Cocoa App window.		
+		[[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
+		
+		// This is a bit of voodoo taken from the Apple sample code "CarbonCocoa_PictureCursor":
+		//   http://developer.apple.com/samplecode/CarbonCocoa_PictureCursor/index.html
+		
+		//	Needed for Carbon based applications which call into Cocoa
+		NSApplicationLoad();
+
+		//	Must first call [[[NSWindow alloc] init] release] to get the NSWindow machinery set up so that NSCursor can use a window to cache the cursor image
+		[[[NSWindow alloc] init] release];
+		
+		deleteAutoReleasePool();
+		
+		inited = true;
+	}
+}
+
+static NSAutoreleasePool *sPool = NULL;
+
+void createAutoReleasePool()
+{
+	if(!sPool)
+	{
+		sPool = [[NSAutoreleasePool alloc] init];
+	}
+}
+
+void deleteAutoReleasePool()
+{
+	if(sPool)
+	{
+		[sPool release];
+		sPool = NULL;
+	}
+}
diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp
index 7d6dde1a58e3dfb03e9947b133f8ce61887c063b..4c955e875a0f227f31beea8c507df39b62d5ff30 100644
--- a/indra/llplugin/slplugin/slplugin.cpp
+++ b/indra/llplugin/slplugin/slplugin.cpp
@@ -44,6 +44,7 @@
 
 #if LL_DARWIN
 	#include <Carbon/Carbon.h>
+	#include "slplugin-objc.h"
 #endif
 
 #if LL_DARWIN || LL_LINUX
@@ -229,10 +230,19 @@ int main(int argc, char **argv)
 	signal(SIGSYS, &crash_handler);		// non-existent system call invoked
 #endif
 
+#if LL_DARWIN
+	setupCocoa();
+	createAutoReleasePool();
+#endif
+
 	LLPluginProcessChild *plugin = new LLPluginProcessChild();
 
 	plugin->init(port);
 
+#if LL_DARWIN
+		deleteAutoReleasePool();
+#endif
+
 	LLTimer timer;
 	timer.start();
 
@@ -260,6 +270,9 @@ int main(int argc, char **argv)
 #endif
 	while(!plugin->isDone())
 	{
+#if LL_DARWIN
+		createAutoReleasePool();
+#endif
 		timer.reset();
 		plugin->idle();
 #if LL_DARWIN
@@ -377,6 +390,10 @@ int main(int argc, char **argv)
 	// exception handler such as QuickTime.
 	//checkExceptionHandler();
 #endif
+
+#if LL_DARWIN
+		deleteAutoReleasePool();
+#endif
 	}
 
 	delete plugin;
diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm
index 3a822a93a668690ff016e0d3dbeebcdb3a8f50d2..01e04dbb07eba07efc163649f3bd58514d0688ed 100644
--- a/indra/llwindow/llwindowmacosx-objc.mm
+++ b/indra/llwindow/llwindowmacosx-objc.mm
@@ -64,6 +64,8 @@ void setupCocoa()
 		[[[NSWindow alloc] init] release];
 
 		[pool release];
+		
+		inited = true;
 	}
 }
 
diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp
index 51364594e4b3257d85963a1205a315cdd7847a6b..ba7526ccd51bf8d56e5b443ea312bcf6f58d8e74 100644
--- a/indra/newview/llfloaterpay.cpp
+++ b/indra/newview/llfloaterpay.cpp
@@ -145,6 +145,9 @@ LLFloaterPay::~LLFloaterPay()
 {
 	std::for_each(mCallbackData.begin(), mCallbackData.end(), DeletePointer());
 	// Name callbacks will be automatically disconnected since LLFloater is trackable
+	
+	// In case this floater is currently waiting for a reply.
+	gMessageSystem->setHandlerFuncFast(_PREHASH_PayPriceReply, 0, 0);
 }
 
 BOOL LLFloaterPay::postBuild()
diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp
index 3ca8fa2f56e14c6eaf3ec50fe10db827f73c8f9d..9a10a7ede8796f393ab82567f3063204b0fdd814 100644
--- a/indra/newview/llinspecttoast.cpp
+++ b/indra/newview/llinspecttoast.cpp
@@ -55,7 +55,7 @@ class LLInspectToast: public LLInspect
 private:
 	void onToastDestroy(LLToast * toast);
 
-private:
+	boost::signals2::scoped_connection mConnection;
 	LLPanel* mPanel;
 	LLScreenChannel* mScreenChannel;
 };
@@ -88,7 +88,7 @@ void LLInspectToast::onOpen(const LLSD& notification_id)
 		llwarns << "Could not get requested toast  from screen channel." << llendl;
 		return;
 	}
-	toast->setOnToastDestroyedCallback(boost::bind(&LLInspectToast::onToastDestroy, this, _1));
+	mConnection = toast->setOnToastDestroyedCallback(boost::bind(&LLInspectToast::onToastDestroy, this, _1));
 
 	LLPanel * panel = toast->getPanel();
 	panel->setVisible(TRUE);
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 37088064c6d2cb463c8996c189f7583669ccc360..7e9a2cb71666b66de984e4dcd7333924a40fca5b 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -245,6 +245,47 @@ BOOL get_is_item_worn(const LLUUID& id)
 	return FALSE;
 }
 
+BOOL get_can_item_be_worn(const LLUUID& id)
+{
+	const LLViewerInventoryItem* item = gInventory.getItem(id);
+	if (!item)
+		return FALSE;
+	
+	switch(item->getType())
+	{
+		case LLAssetType::AT_OBJECT:
+		{
+			if (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item->getLinkedUUID()))
+			{
+				// Already being worn
+				return FALSE;
+			}
+			else
+			{
+				// Not being worn yet.
+				return TRUE;
+			}
+			break;
+		}
+		case LLAssetType::AT_BODYPART:
+		case LLAssetType::AT_CLOTHING:
+			if(gAgentWearables.isWearingItem(item->getLinkedUUID()))
+			{
+				// Already being worn
+				return FALSE;
+			}
+			else
+			{
+				// Not being worn yet.
+				return TRUE;
+			}
+			break;
+		default:
+			break;
+	}
+	return FALSE;
+}
+
 BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id)
 {
 	if (!model)
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 6619a50d28e83ad3c35d515bf064f755b2a49073..1c3f82c531374ef18c6975776f9adaf4600ec32d 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -46,6 +46,9 @@
 // Is this item or its baseitem is worn, attached, etc...
 BOOL get_is_item_worn(const LLUUID& id);
 
+// Could this item be worn (correct type + not already being worn)
+BOOL get_can_item_be_worn(const LLUUID& id);
+
 BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id);
 
 BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id);
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 154471787358aa9a12ae5dd5432bf3f13bb62b34..ffd879dfd75000d0b5882869f6dbe53d76a63484 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -661,10 +661,13 @@ void LLPanelOutfitEdit::onInventorySelectionChange()
 	getSelectedItemsUUID(selected_items);
 	if (selected_items.empty())
 	{
+		mPlusBtn->setEnabled(false);
 		return;
 	}
-	uuid_vec_t::iterator worn_item = std::find_if(selected_items.begin(), selected_items.end(), boost::bind(&get_is_item_worn, _1));
-	bool can_add = ( worn_item == selected_items.end() );
+
+	// If any of the selected items are not wearable (due to already being worn OR being of the wrong type), disable the add button.
+	uuid_vec_t::iterator unwearable_item = std::find_if(selected_items.begin(), selected_items.end(), !boost::bind(& get_can_item_be_worn, _1));
+	bool can_add = ( unwearable_item == selected_items.end() );
 
 	mPlusBtn->setEnabled(can_add);