From 74429f2ed926362a2ec47d590fc862b55b26f0f8 Mon Sep 17 00:00:00 2001
From: Alexei Arabadji <aarabadji@productengine.com>
Date: Fri, 22 Jan 2010 13:42:52 +0200
Subject: [PATCH] =?UTF-8?q?fixed=20EXT-3670=20=E2=80=9CClicking=20on=20IM?=
 =?UTF-8?q?=20session=20in=20IM=20session=20well=20closes=20IM=20floater?=
 =?UTF-8?q?=E2=80=9D,=20implemented=20exclude=20sets=20for=20groups=20of?=
 =?UTF-8?q?=20transient=20floaters,=20now=20transient=20floaters=20not=20c?=
 =?UTF-8?q?loses=20if=20user=20click=20on=20view=20from=20global=20exclude?=
 =?UTF-8?q?=20set=20or=20from=20floater=20group=20set;=20made=20IM=20float?=
 =?UTF-8?q?er=20goes=20foreground=20if=20it=20visible=20but=20not=20focuse?=
 =?UTF-8?q?d=20instead=20hide=20floater;?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

--HG--
branch : product-engine
---
 indra/newview/llchiclet.cpp                  |  2 +
 indra/newview/llimfloater.cpp                |  7 +-
 indra/newview/llimfloater.h                  |  2 +
 indra/newview/lltransientdockablefloater.cpp |  2 +-
 indra/newview/lltransientdockablefloater.h   |  4 +-
 indra/newview/lltransientfloatermgr.cpp      | 69 +++++++++++++-------
 indra/newview/lltransientfloatermgr.h        | 37 +++++++++--
 7 files changed, 90 insertions(+), 33 deletions(-)

diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 8da207f887f..f1de4e29824 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -1272,6 +1272,7 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)
 		chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index));
 
 		arrange();
+		LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, chiclet);
 
 		return true;
 	}
@@ -1299,6 +1300,7 @@ void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it)
 	mChicletList.erase(it);
 	
 	arrange();
+	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, chiclet);
 	chiclet->die();
 }
 
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index e06e0c94ec9..73597e7de33 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -110,6 +110,8 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
 		}
 	}
 	setOverlapsScreenChannel(true);
+
+	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
 }
 
 void LLIMFloater::onFocusLost()
@@ -228,6 +230,7 @@ void LLIMFloater::sendMsg()
 
 LLIMFloater::~LLIMFloater()
 {
+	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);
 }
 
 //virtual
@@ -513,14 +516,14 @@ bool LLIMFloater::toggle(const LLUUID& session_id)
 	if(!isChatMultiTab())
 	{
 		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
-		if (floater && floater->getVisible())
+		if (floater && floater->getVisible() && floater->hasFocus())
 		{
 			// clicking on chiclet to close floater just hides it to maintain existing
 			// scroll/text entry state
 			floater->setVisible(false);
 			return false;
 		}
-		else if(floater && !floater->isDocked())
+		else if(floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus()))
 		{
 			floater->setVisible(TRUE);
 			floater->setFocus(TRUE);
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index d9db385d06a..0ca0325451b 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -116,6 +116,8 @@ class LLIMFloater : public LLTransientDockableFloater
 
 	static void onIMChicletCreated(const LLUUID& session_id);
 
+	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; }
+
 private:
 	// process focus events to set a currently active session
 	/* virtual */ void onFocusLost();
diff --git a/indra/newview/lltransientdockablefloater.cpp b/indra/newview/lltransientdockablefloater.cpp
index 7e4d4988d12..b830498cb0b 100644
--- a/indra/newview/lltransientdockablefloater.cpp
+++ b/indra/newview/lltransientdockablefloater.cpp
@@ -39,7 +39,7 @@
 
 LLTransientDockableFloater::LLTransientDockableFloater(LLDockControl* dockControl, bool uniqueDocking,
 		const LLSD& key, const Params& params) :
-		LLDockableFloater(dockControl, uniqueDocking, key, params)
+		LLDockableFloater(dockControl, uniqueDocking, key, params), LLTransientFloater(this)
 {
 	LLTransientFloaterMgr::getInstance()->registerTransientFloater(this);
 }
diff --git a/indra/newview/lltransientdockablefloater.h b/indra/newview/lltransientdockablefloater.h
index 6e8a3afd221..e0541d65979 100644
--- a/indra/newview/lltransientdockablefloater.h
+++ b/indra/newview/lltransientdockablefloater.h
@@ -37,12 +37,13 @@
 #include "llfloater.h"
 #include "lldockcontrol.h"
 #include "lldockablefloater.h"
+#include "lltransientfloatermgr.h"
 
 /**
  * Represents floater that can dock and managed by transient floater manager.
  * Transient floaters should be hidden if user click anywhere except defined view list.
  */
-class LLTransientDockableFloater : public LLDockableFloater
+class LLTransientDockableFloater : public LLDockableFloater, LLTransientFloater
 {
 public:
 	LOG_CLASS(LLTransientDockableFloater);
@@ -52,6 +53,7 @@ class LLTransientDockableFloater : public LLDockableFloater
 
 	/*virtual*/ void setVisible(BOOL visible);
 	/* virtual */void setDocked(bool docked, bool pop_on_undock = true);
+	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; }
 };
 
 #endif /* LL_TRANSIENTDOCKABLEFLOATER_H */
diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp
index 347399f2391..f474f47eb79 100644
--- a/indra/newview/lltransientfloatermgr.cpp
+++ b/indra/newview/lltransientfloatermgr.cpp
@@ -44,57 +44,68 @@ LLTransientFloaterMgr::LLTransientFloaterMgr()
 {
 	gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(
 			&LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3));
+
+	mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(GLOBAL, std::set<LLView*>()));
+	mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(IM, std::set<LLView*>()));
 }
 
-void LLTransientFloaterMgr::registerTransientFloater(LLFloater* floater)
+void LLTransientFloaterMgr::registerTransientFloater(LLTransientFloater* floater)
 {
 	mTransSet.insert(floater);
 }
 
-void LLTransientFloaterMgr::unregisterTransientFloater(LLFloater* floater)
+void LLTransientFloaterMgr::unregisterTransientFloater(LLTransientFloater* floater)
 {
 	mTransSet.erase(floater);
 }
 
+void LLTransientFloaterMgr::addControlView(ETransientGroup group, LLView* view)
+{
+	mGroupControls.find(group)->second.insert(view);
+}
+
+void LLTransientFloaterMgr::removeControlView(ETransientGroup group, LLView* view)
+{
+	mGroupControls.find(group)->second.erase(view);
+}
+
 void LLTransientFloaterMgr::addControlView(LLView* view)
 {
-	mControlsSet.insert(view);
+	addControlView(GLOBAL, view);
 }
 
 void LLTransientFloaterMgr::removeControlView(LLView* view)
 {
 	// we will still get focus lost callbacks on this view, but that's ok
 	// since we run sanity checking logic every time
-	mControlsSet.erase(view);
+	removeControlView(GLOBAL, view);
 }
 
-void LLTransientFloaterMgr::hideTransientFloaters()
+void LLTransientFloaterMgr::hideTransientFloaters(S32 x, S32 y)
 {
-	for (std::set<LLFloater*>::iterator it = mTransSet.begin(); it
+	for (std::set<LLTransientFloater*>::iterator it = mTransSet.begin(); it
 			!= mTransSet.end(); it++)
 	{
-		LLFloater* floater = *it;
-		if (floater->isDocked())
+		LLTransientFloater* floater = *it;
+		if (floater->isTransientDocked())
 		{
-			floater->setVisible(FALSE);
+			ETransientGroup group = floater->getGroup();
+
+			bool hide = isControlClicked(mGroupControls.find(group)->second, x, y);
+			if (hide)
+			{
+				floater->setTransientVisible(FALSE);
+			}
 		}
 	}
 }
 
-void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
-		MASK mask)
+bool LLTransientFloaterMgr::isControlClicked(std::set<LLView*>& set, S32 x, S32 y)
 {
-	bool hide = true;
-	for (controls_set_t::iterator it = mControlsSet.begin(); it
-			!= mControlsSet.end(); it++)
+	bool res = true;
+	for (controls_set_t::iterator it = set.begin(); it
+			!= set.end(); it++)
 	{
-		// don't hide transient floater if any context menu opened
-		if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL)
-		{
-			hide = false;
-			break;
-		}
-
 		LLView* control_view = *it;
 		if (!control_view->getVisible())
 		{
@@ -105,14 +116,26 @@ void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
 		// if click inside view rect
 		if (rect.pointInRect(x, y))
 		{
-			hide = false;
+			res = false;
 			break;
 		}
 	}
+	return res;
+}
+
+void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
+		MASK mask)
+{
+	// don't hide transient floater if any context menu opened
+	if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL)
+	{
+		return;
+	}
 
+	bool hide = isControlClicked(mGroupControls.find(GLOBAL)->second, x, y);
 	if (hide)
 	{
-		hideTransientFloaters();
+		hideTransientFloaters(x, y);
 	}
 }
 
diff --git a/indra/newview/lltransientfloatermgr.h b/indra/newview/lltransientfloatermgr.h
index cef6e1fe456..95eba666a03 100644
--- a/indra/newview/lltransientfloatermgr.h
+++ b/indra/newview/lltransientfloatermgr.h
@@ -37,6 +37,7 @@
 #include "llsingleton.h"
 #include "llfloater.h"
 
+class LLTransientFloater;
 
 /**
  * Provides functionality to hide transient floaters.
@@ -44,20 +45,44 @@
 class LLTransientFloaterMgr: public LLSingleton<LLTransientFloaterMgr>
 {
 public:
+	enum ETransientGroup
+	{
+		GLOBAL, IM
+	};
+
 	LLTransientFloaterMgr();
-	void registerTransientFloater(LLFloater* floater);
-	void unregisterTransientFloater(LLFloater* floater);
+	void registerTransientFloater(LLTransientFloater* floater);
+	void unregisterTransientFloater(LLTransientFloater* floater);
+	void addControlView(ETransientGroup group, LLView* view);
+	void removeControlView(ETransientGroup group, LLView* view);
 	void addControlView(LLView* view);
 	void removeControlView(LLView* view);
 
 private:
-	void hideTransientFloaters();
+	void hideTransientFloaters(S32 x, S32 y);
 	void leftMouseClickCallback(S32 x, S32 y, MASK mask);
-
+	bool isControlClicked(std::set<LLView*>& set, S32 x, S32 y);
 private:
-	std::set<LLFloater*> mTransSet;
+	std::set<LLTransientFloater*> mTransSet;
+
 	typedef std::set<LLView*> controls_set_t;
-	controls_set_t mControlsSet;
+	typedef std::map<ETransientGroup, std::set<LLView*> > group_controls_t;
+	group_controls_t mGroupControls;
+};
+
+/**
+ * An abstract class declares transient floater interfaces.
+ */
+class LLTransientFloater
+{
+public:
+	LLTransientFloater(LLFloater* floater) : mFloater(floater) {}
+	virtual LLTransientFloaterMgr::ETransientGroup getGroup() = 0;
+	bool isTransientDocked() { return mFloater->isDocked(); };
+	void setTransientVisible(BOOL visible) {mFloater->setVisible(visible); }
+
+private:
+	LLFloater* mFloater;
 };
 
 #endif  // LL_LLTRANSIENTFLOATERMGR_H
-- 
GitLab