diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index aaa5952ef7730ecb2c9e8c8d2162adadd9ab5ce7..73bb8543ee5955467149ade6936574b1bdd4c746 100755
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -294,8 +294,8 @@ bool LLGroupActions::onJoinGroup(const LLSD& notification, const LLSD& response)
 void LLGroupActions::leave(const LLUUID& group_id)
 {
 //	if (group_id.isNull())
-// [RLVa:KB] - Checked: 2011-03-28 (RLVa-1.4.1a) | Added: RLVa-1.3.0f
-	if ( (group_id.isNull()) || ((gAgent.getGroupID() == group_id) && (gRlvHandler.hasBehaviour(RLV_BHVR_SETGROUP))) )
+// [RLVa:KB] - Checked: RLVa-1.3.0
+	if ( (group_id.isNull()) || ((gAgent.getGroupID() == group_id) && (!RlvActions::canChangeActiveGroup())) )
 // [/RLVa:KB]
 	{
 		return;
@@ -348,8 +348,8 @@ void LLGroupActions::processLeaveGroupDataResponse(const LLUUID group_id)
 // static
 void LLGroupActions::activate(const LLUUID& group_id)
 {
-// [RLVa:KB] - Checked: 2011-03-28 (RLVa-1.4.1a) | Added: RLVa-1.3.0f
-	if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SETGROUP)) && (gRlvHandler.getAgentGroup() != group_id) )
+// [RLVa:KB] - Checked: RLVa-1.3.0
+	if ( (!RlvActions::canChangeActiveGroup()) && (gRlvHandler.getAgentGroup() != group_id) )
 	{
 		return;
 	}
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
index 062154f03c102ea25a7504f94ee1d8c63c149c10..339414e5cb691c604368b40399d0b2d0c0877627 100755
--- a/indra/newview/llgrouplist.cpp
+++ b/indra/newview/llgrouplist.cpp
@@ -43,8 +43,8 @@
 #include "llviewercontrol.h"	// for gSavedSettings
 #include "llviewermenu.h"		// for gMenuHolder
 #include "llvoiceclient.h"
-// [RLVa:KB] - Checked: 2011-03-28 (RLVa-1.3.0f) | Added: RLVa-1.3.0f
-#include "rlvhandler.h"
+// [RLVa:KB] - Checked: RLVa-2.0.3
+#include "rlvactions.h"
 // [/RLVa:KB]
 
 static LLDefaultChildRegistry::Register<LLGroupList> r("group_list");
@@ -284,14 +284,14 @@ bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)
 	bool real_group_selected = selected_group_id.notNull(); // a "real" (not "none") group is selected
 
 	// each group including "none" can be activated
-//	if (userdata.asString() == "activate")
-//		return gAgent.getGroupID() != selected_group_id;
-// [RLVa:KB] - Checked: 2011-03-28 (RLVa-1.4.1a) | Added: RLVa-1.3.0f
+// [RLVa:KB] - Checked: RLVa-1.3.0
 	if (userdata.asString() == "activate")
-		return (gAgent.getGroupID() != selected_group_id) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETGROUP));
+		return (gAgent.getGroupID() != selected_group_id) && (RlvActions::canChangeActiveGroup());
 	else if (userdata.asString() == "leave")
-		return (real_group_selected) && ((gAgent.getGroupID() != selected_group_id) || (!gRlvHandler.hasBehaviour(RLV_BHVR_SETGROUP)));
+		return (real_group_selected) && ((gAgent.getGroupID() != selected_group_id) || (RlvActions::canChangeActiveGroup()));
 // [/RLVa:KB]
+//	if (userdata.asString() == "activate")
+//		return gAgent.getGroupID() != selected_group_id;
 
 	if (userdata.asString() == "call")
 	  return real_group_selected && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
diff --git a/indra/newview/rlvactions.cpp b/indra/newview/rlvactions.cpp
index 1def8205fb10b139209e49e12d9f18b3b5062ab8..b98de3cbf25782a7d279bfd871265042d5a43f5b 100644
--- a/indra/newview/rlvactions.cpp
+++ b/indra/newview/rlvactions.cpp
@@ -121,6 +121,13 @@ bool RlvActions::getCameraFOVLimits(F32& nFOVMin, F32& nFOVMax)
 
 bool RlvActions::s_BlockNamesContexts[SNC_COUNT] = { 0 };
 
+bool RlvActions::canChangeActiveGroup(const LLUUID& idRlvObject)
+{
+	// User can change their active group if:
+	//   - not specifically restricted (by another object that the one specified) from changing their active group
+	return (idRlvObject.isNull()) ? !gRlvHandler.hasBehaviour(RLV_BHVR_SETGROUP) : !gRlvHandler.hasBehaviourExcept(RLV_BHVR_SETGROUP, idRlvObject);
+}
+
 // Little helper function to check the IM exclusion range for @recvim, @sendim and @startim (returns: min_dist <= (pos user - pos target) <= max_dist)
 static bool rlvCheckAvatarIMDistance(const LLUUID& idAvatar, ERlvBehaviourModifier eModDistMin, ERlvBehaviourModifier eModDistMax)
 {
diff --git a/indra/newview/rlvactions.h b/indra/newview/rlvactions.h
index e11066e25aab92b68ff24acd18ac7bb8a4edc8f5..14f0c3b85bcb47594ca0ba6fecf4116db1130fa6 100644
--- a/indra/newview/rlvactions.h
+++ b/indra/newview/rlvactions.h
@@ -74,6 +74,11 @@ public:
 	// Communication/Avatar interaction
 	// ================================
 public:
+	/*
+	 * Returns true if the user is allowed to change their currently active group
+	 */
+	static bool canChangeActiveGroup(const LLUUID& idRlvObject = LLUUID::null);
+
 	/*
 	 * Returns true if the user is allowed to receive IMs from the specified sender (can be an avatar or a group)
 	 */
diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h
index 84a921b3fb6d000a0820df4d55988fac351ca1c0..3011a41325d0a6896a5a2851999b362ea6d64d4f 100644
--- a/indra/newview/rlvdefines.h
+++ b/indra/newview/rlvdefines.h
@@ -370,6 +370,7 @@ enum ERlvAttachGroupType
 
 #define RLV_STRING_BLOCKED_AUTOPILOT		"blocked_autopilot"
 #define RLV_STRING_BLOCKED_GENERIC			"blocked_generic"
+#define RLV_STRING_BLOCKED_GROUPCHANGE		"blocked_groupchange"
 #define RLV_STRING_BLOCKED_PERMATTACH		"blocked_permattach"
 #define RLV_STRING_BLOCKED_PERMTELEPORT		"blocked_permteleport"
 #define RLV_STRING_BLOCKED_RECVIM			"blocked_recvim"
diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp
index f4033a2380186cfebccec585e69d5395953472a8..6ad9e4c848b1dd293f4428936683294fd71214e2 100644
--- a/indra/newview/rlvhandler.cpp
+++ b/indra/newview/rlvhandler.cpp
@@ -472,21 +472,43 @@ ERlvCmdRet RlvHandler::processClearCommand(const RlvCommand& rlvCmd)
 // Externally invoked event handlers
 //
 
-// Checked: 2011-05-22 (RLVa-1.4.1a) | Added: RLVa-1.3.1b
 bool RlvHandler::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& sdUserdata)
 {
+	// NOTE: we'll fire once for every group the user belongs to so we need to manually keep track of pending changes
+	static LLUUID s_idLastAgentGroup = LLUUID::null;
+	static bool s_fGroupChanging = false;
+
+	if (s_idLastAgentGroup != gAgent.getGroupID())
+	{
+		s_idLastAgentGroup = gAgent.getGroupID();
+		s_fGroupChanging = false;
+	}
+
 	// If the user managed to change their active group (= newly joined or created group) we need to reactivate the previous one
-	if ( (hasBehaviour(RLV_BHVR_SETGROUP)) && ("new group" == event->desc()) && (m_idAgentGroup != gAgent.getGroupID()) )
-	{
-		// [Copy/paste from LLGroupActions::activate()]
-		LLMessageSystem* msg = gMessageSystem;
-		msg->newMessageFast(_PREHASH_ActivateGroup);
-		msg->nextBlockFast(_PREHASH_AgentData);
-		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-		msg->addUUIDFast(_PREHASH_GroupID, m_idAgentGroup);
-		gAgent.sendReliableMessage();
-		return true;
+	if ( (!RlvActions::canChangeActiveGroup()) && ("new group" == event->desc()) && (m_idAgentGroup != gAgent.getGroupID()) )
+	{
+		// Make sure they still belong to the group
+		if ( (m_idAgentGroup.notNull()) && (!gAgent.isInGroup(m_idAgentGroup)) )
+		{
+			m_idAgentGroup.setNull();
+			s_fGroupChanging = false;
+		}
+
+		if (!s_fGroupChanging)
+		{
+			RlvUtil::notifyBlocked(RLV_STRING_BLOCKED_GROUPCHANGE, LLSD().with("GROUP_SLURL", (m_idAgentGroup.notNull()) ? llformat("secondlife:///app/group/%s/about", m_idAgentGroup.asString()) : "(none)"));
+
+			// [Copy/paste from LLGroupActions::activate()]
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessageFast(_PREHASH_ActivateGroup);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			msg->addUUIDFast(_PREHASH_GroupID, m_idAgentGroup);
+			gAgent.sendReliableMessage();
+			s_fGroupChanging = true;
+			return true;
+		}
 	}
 	else
 	{
@@ -2384,7 +2406,7 @@ void RlvHandler::onForceWearCallback(const uuid_vec_t& idItems, U32 nFlags) cons
 template<> template<>
 ERlvCmdRet RlvForceHandler<RLV_BHVR_SETGROUP>::onCommand(const RlvCommand& rlvCmd)
 {
-	if (gRlvHandler.hasBehaviourExcept(RLV_BHVR_SETGROUP, rlvCmd.getObjectID()))
+	if (!RlvActions::canChangeActiveGroup(rlvCmd.getObjectID()))
 	{
 		return RLV_RET_FAILED_LOCK;
 	}
diff --git a/indra/newview/skins/default/xui/en/rlva_strings.xml b/indra/newview/skins/default/xui/en/rlva_strings.xml
index 6861f9c4657bf7caee12ba1c0e0b35150435ff1e..62651c9a09cc573909a01bccb0062681495b4ece 100644
--- a/indra/newview/skins/default/xui/en/rlva_strings.xml
+++ b/indra/newview/skins/default/xui/en/rlva_strings.xml
@@ -56,6 +56,11 @@
 			<key>value</key>
 			<string>Unable to perform action due to RLV restrictions</string>
 		</map>
+		<key>blocked_groupchange</key>
+		<map>
+			<key>value</key>
+			<string>Unable to change your active group due to an RLV restriction; switching back to [GROUP_SLURL]</string>
+		</map>
 		<key>blocked_permattach</key>
 		<map>
 			<key>value</key>