From e4b63c96b83a1ed8c18946ecd64c21d6bd7c26fe Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 17 Jan 2012 14:59:18 -0800
Subject: [PATCH] EXP-1804 FIX -- Drag and drop operations can be blocked by
 modal dialogs

* Added support for marketplace notifications that don't display the dialog
  until the next frame, leaving room for the drag and drop operation to
  properly complete before the notification shows up and interferes.
---
 indra/newview/CMakeLists.txt                 |  2 +
 indra/newview/llappviewer.cpp                |  4 +-
 indra/newview/llinventoryfunctions.cpp       | 39 +--------
 indra/newview/llmarketplacenotifications.cpp | 89 ++++++++++++++++++++
 indra/newview/llmarketplacenotifications.h   | 57 +++++++++++++
 5 files changed, 155 insertions(+), 36 deletions(-)
 create mode 100644 indra/newview/llmarketplacenotifications.cpp
 create mode 100644 indra/newview/llmarketplacenotifications.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 78cd33210fb..f85b943c70d 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -316,6 +316,7 @@ set(viewer_SOURCE_FILES
     llmanipscale.cpp
     llmaniptranslate.cpp
     llmarketplacefunctions.cpp
+    llmarketplacenotifications.cpp
     llmediactrl.cpp
     llmediadataclient.cpp
     llmemoryview.cpp
@@ -871,6 +872,7 @@ set(viewer_HEADER_FILES
     llmanipscale.h
     llmaniptranslate.h
     llmarketplacefunctions.h
+    llmarketplacenotifications.h
     llmediactrl.h
     llmediadataclient.h
     llmemoryview.h
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 5c51f1b11ae..a455d359bfc 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -46,6 +46,7 @@
 #include "llviewerstats.h"
 #include "llviewerstatsrecorder.h"
 #include "llmarketplacefunctions.h"
+#include "llmarketplacenotifications.h"
 #include "llmd5.h"
 #include "llmeshrepository.h"
 #include "llpumpio.h"
@@ -4406,8 +4407,9 @@ void LLAppViewer::idle()
 	// update media focus
 	LLViewerMediaFocus::getInstance()->update();
 	
-	// Update marketplace importer
+	// Update marketplace
 	LLMarketplaceInventoryImporter::update();
+	LLMarketplaceInventoryNotifications::update();
 
 	// objects and camera should be in sync, do LOD calculations now
 	{
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 40bc3b76c93..dd92188e9d2 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -58,6 +58,7 @@
 #include "llinventorymodel.h"
 #include "llinventorypanel.h"
 #include "lllineeditor.h"
+#include "llmarketplacenotifications.h"
 #include "llmenugl.h"
 #include "llnotificationsutil.h"
 #include "llpanelmaininventory.h"
@@ -533,9 +534,6 @@ void show_item_original(const LLUUID& item_uuid)
 }
 
 
-static S32 move_to_outbox_operation_id = -1;
-static std::list<LLSD> move_to_outbox_payloads;
-
 void open_outbox()
 {
 	LLFloaterReg::showInstance("outbox");
@@ -614,24 +612,6 @@ void move_to_outbox_cb_action(const LLSD& payload)
 	}
 }
 
-void move_to_outbox_cb(const LLSD& notification, const LLSD& response)
-{
-	const S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
-	if (option == 0)
-	{
-		llassert(move_to_outbox_payloads.size() > 0);
-
-		BOOST_FOREACH(const LLSD& payload, move_to_outbox_payloads)
-		{
-			move_to_outbox_cb_action(payload);
-		}
-	}
-
-	move_to_outbox_operation_id = -1;
-	move_to_outbox_payloads.clear();
-}
-
 void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id)
 {
 	// Collapse links directly to items/folders
@@ -668,25 +648,14 @@ void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LL
 			open_outbox();
 		}
 		else
-		{	
-			LLSD args;
-			args["ITEM_NAME"] = inv_item->getName();
-
+		{
 			LLSD payload;
 			payload["item_id"] = inv_item->getUUID();
 			payload["dest_folder_id"] = dest_folder;
 			payload["top_level_folder"] = top_level_folder;
 			payload["operation_id"] = operation_id;
-
-			if (move_to_outbox_operation_id != operation_id)
-			{
-				LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&move_to_outbox_cb, _1, _2));
-				
-				move_to_outbox_operation_id = operation_id;
-				move_to_outbox_payloads.clear();
-			}
-
-			move_to_outbox_payloads.push_back(payload);
+			
+			LLMarketplaceInventoryNotifications::addNoCopyNotification(payload, move_to_outbox_cb_action);
 		}
 	}
 }
diff --git a/indra/newview/llmarketplacenotifications.cpp b/indra/newview/llmarketplacenotifications.cpp
new file mode 100644
index 00000000000..25faafb8ea6
--- /dev/null
+++ b/indra/newview/llmarketplacenotifications.cpp
@@ -0,0 +1,89 @@
+/** 
+ * @file llmarketplacenotifications.cpp
+ * @brief Handler for notifications related to marketplace file I/O
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llmarketplacenotifications.h"
+#include "llnotificationsutil.h"
+
+#include "llerror.h"
+
+#include <boost/foreach.hpp>
+#include <boost/signals2.hpp>
+
+
+namespace LLMarketplaceInventoryNotifications
+{
+	typedef boost::signals2::signal<void (const LLSD& param)>	no_copy_payload_cb_signal_t;
+
+	static no_copy_payload_cb_signal_t*	no_copy_cb_action = NULL;
+	static bool							no_copy_notify_active = false;
+	static std::list<LLSD>				no_copy_payloads;
+
+	void notifyNoCopyCallback(const LLSD& notification, const LLSD& response)
+	{
+		const S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+		
+		if (option == 0)
+		{
+			llassert(!no_copy_payloads.empty());
+			llassert(no_copy_cb_action != NULL);
+			
+			BOOST_FOREACH(const LLSD& payload, no_copy_payloads)
+			{
+				(*no_copy_cb_action)(payload);
+			}
+		}
+		
+		delete no_copy_cb_action;
+		no_copy_cb_action = NULL;
+		
+		no_copy_notify_active = false;
+		no_copy_payloads.clear();
+	}
+
+	void update()
+	{
+		if (!no_copy_notify_active && !no_copy_payloads.empty())
+		{
+			no_copy_notify_active = true;
+			
+			LLNotificationsUtil::add("ConfirmNoCopyToOutbox", LLSD(), LLSD(), boost::bind(&notifyNoCopyCallback, _1, _2));
+		}
+	}
+		
+	void addNoCopyNotification(const LLSD& payload, const NoCopyCallbackFunction& cb)
+	{
+		if (no_copy_cb_action == NULL)
+		{
+			no_copy_cb_action = new no_copy_payload_cb_signal_t;
+			no_copy_cb_action->connect(boost::bind(cb, _1));
+		}
+
+		no_copy_payloads.push_back(payload);
+	}
+}
diff --git a/indra/newview/llmarketplacenotifications.h b/indra/newview/llmarketplacenotifications.h
new file mode 100644
index 00000000000..83a4e163c7c
--- /dev/null
+++ b/indra/newview/llmarketplacenotifications.h
@@ -0,0 +1,57 @@
+/** 
+ * @file llmarketplacenotifications.h
+ * @brief Handler for notifications related to marketplace file I/O
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMARKETPLACENOTIFICATIONS_H
+#define LL_LLMARKETPLACENOTIFICATIONS_H
+
+
+#include <llsd.h>
+#include <boost/function.hpp>
+
+
+//
+// This is a set of helper functions to handle a unique notification with multiple
+// payloads, helpful when dragging and dropping items to the merchant outbox that
+// trigger notifications that can potentially interfere with the current drag and
+// drop operation.
+//
+// Notification payloads are cached locally when initiated, the notification itself
+// is triggered on the following frame during the call to "update" and then the
+// response is triggered once per payload.
+//
+
+namespace LLMarketplaceInventoryNotifications
+{
+	void update();
+
+	typedef boost::function<void (const LLSD&)> NoCopyCallbackFunction;
+	
+	void addNoCopyNotification(const LLSD& payload, const NoCopyCallbackFunction& cb);
+};
+
+
+#endif // LL_LLMARKETPLACENOTIFICATIONS_H
-- 
GitLab