From 2d855a9fd7ea0ef32f8d9de81b2532b3771142e4 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 16 Jul 2021 22:45:41 +0300
Subject: SL-15594 Reimplement previous voice keybind behavior

Also fixed dupplicate checks
---
 indra/newview/llviewerinput.cpp | 159 ++++++++++++++++++++++++++++++++--------
 1 file changed, 128 insertions(+), 31 deletions(-)

(limited to 'indra/newview/llviewerinput.cpp')

diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index f269be035e..77b0c8e37b 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -60,8 +60,21 @@ const F32 ORBIT_NUDGE_RATE = 0.05f;  // fraction of normal speed
 
 const LLKeyData agent_control_lbutton(CLICK_LEFT, KEY_NONE, MASK_NONE, true);
 
+struct LLKeybindFunctionData
+{
+    LLKeybindFunctionData(boost::function<bool(EKeystate keystate)> function, bool global)
+        :
+        mFunction(function),
+        mIsGlobal(global)
+    {
+    }
+    boost::function<bool(EKeystate keystate)> mFunction;
+    // todo: might be good idea to make this into enum, like: global/inworld/menu
+    bool mIsGlobal;
+};
+
 struct LLKeyboardActionRegistry 
-:	public LLRegistrySingleton<std::string, boost::function<bool (EKeystate keystate)>, LLKeyboardActionRegistry>
+:	public LLRegistrySingleton<const std::string, LLKeybindFunctionData, LLKeyboardActionRegistry>
 {
 	LLSINGLETON_EMPTY_CTOR(LLKeyboardActionRegistry);
 };
@@ -852,7 +865,10 @@ bool agen_control_lbutton_handle(EKeystate s)
     return true;
 }
 
-#define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, ACTION);
+// In-world keybindings, like walking or camera
+#define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, LLKeybindFunctionData(ACTION, false));
+// Global keybindings that should work even with floaters focused, like voice
+#define REGISTER_KEYBOARD_GLOBAL_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, LLKeybindFunctionData(ACTION, true));
 REGISTER_KEYBOARD_ACTION("jump", agent_jump);
 REGISTER_KEYBOARD_ACTION("push_down", agent_push_down);
 REGISTER_KEYBOARD_ACTION("push_forward", agent_push_forward);
@@ -903,8 +919,8 @@ REGISTER_KEYBOARD_ACTION("toggle_pause_media", toggle_pause_media);
 REGISTER_KEYBOARD_ACTION("toggle_enable_media", toggle_enable_media);
 REGISTER_KEYBOARD_ACTION("teleport_to", teleport_to);
 REGISTER_KEYBOARD_ACTION("walk_to", walk_to);
-REGISTER_KEYBOARD_ACTION("toggle_voice", toggle_voice);
-REGISTER_KEYBOARD_ACTION("voice_follow_key", voice_follow_key);
+REGISTER_KEYBOARD_GLOBAL_ACTION("toggle_voice", toggle_voice);
+REGISTER_KEYBOARD_GLOBAL_ACTION("voice_follow_key", voice_follow_key);
 #undef REGISTER_KEYBOARD_ACTION
 
 LLViewerInput::LLViewerInput()
@@ -1034,6 +1050,29 @@ BOOL LLViewerInput::handleKeyUp(KEY translated_key, MASK translated_mask)
 	return gViewerWindow->handleKeyUp(translated_key, translated_mask);
 }
 
+bool LLViewerInput::handleGlobalBindsKeyDown(KEY key, MASK mask)
+{
+    S32 mode = getMode();
+    return scanKey(mGlobalKeyBindings[mode], mGlobalKeyBindings[mode].size(), key, mask, TRUE, FALSE, FALSE, FALSE);
+}
+
+bool LLViewerInput::handleGlobalBindsKeyUp(KEY key, MASK mask)
+{
+    S32 mode = getMode();
+    return scanKey(mGlobalKeyBindings[mode], mGlobalKeyBindings[mode].size(), key, mask, FALSE, TRUE, FALSE, FALSE);
+}
+
+bool LLViewerInput::handleGlobalBindsMouse(EMouseClickType clicktype, MASK mask, bool down)
+{
+    bool res = false;
+    if (down)
+    {
+        S32 mode = getMode();
+        res = scanMouse(mGlobalMouseBindings[mode], mGlobalMouseBindings[mode].size(), clicktype, mask, MOUSE_STATE_DOWN);
+    }
+    return res;
+}
+
 BOOL LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name)
 {
 	S32 index;
@@ -1061,39 +1100,64 @@ BOOL LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, cons
 	}
 
 	// Not remapped, look for a function
-	
-	function_t* result = LLKeyboardActionRegistry::getValue(function_name);
+
+    LLKeybindFunctionData* result = LLKeyboardActionRegistry::getValue(function_name);
 	if (result)
 	{
-		function = *result;
+		function = result->mFunction;
 	}
 
 	if (!function)
 	{
-		LL_WARNS() << "Can't bind key to function " << function_name << ", no function with this name found" << LL_ENDL;
+		LL_WARNS_ONCE() << "Can't bind key to function " << function_name << ", no function with this name found" << LL_ENDL;
 		return FALSE;
 	}
 
-	// check for duplicate first and overwrite
-    S32 size = mKeyBindings[mode].size();
-    for (index = 0; index < size; index++)
+    if (mode >= MODE_COUNT)
     {
-        if (key == mKeyBindings[mode][index].mKey && mask == mKeyBindings[mode][index].mMask)
-            break;
+        LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL;
+        return FALSE;
     }
 
-	if (mode >= MODE_COUNT)
-	{
-		LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL;
-		return FALSE;
-	}
+	// check for duplicate first and overwrite
+    if (result->mIsGlobal)
+    {
+        S32 size = mGlobalKeyBindings[mode].size();
+        for (index = 0; index < size; index++)
+        {
+            if (key == mGlobalKeyBindings[mode][index].mKey && mask == mGlobalKeyBindings[mode][index].mMask)
+            {
+                mGlobalKeyBindings[mode][index].mFunction = function;
+                return TRUE;
+            }
+        }
+    }
+    else
+    {
+        S32 size = mKeyBindings[mode].size();
+        for (index = 0; index < size; index++)
+        {
+            if (key == mKeyBindings[mode][index].mKey && mask == mKeyBindings[mode][index].mMask)
+            {
+                mKeyBindings[mode][index].mFunction = function;
+                return TRUE;
+            }
+        }
+    }
 
     LLKeyboardBinding bind;
     bind.mKey = key;
     bind.mMask = mask;
     bind.mFunction = function;
 
-    mKeyBindings[mode].push_back(bind);
+    if (result->mIsGlobal)
+    {
+        mGlobalKeyBindings[mode].push_back(bind);
+    }
+    else
+    {
+        mKeyBindings[mode].push_back(bind);
+    }
 
 	return TRUE;
 }
@@ -1104,38 +1168,63 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const
     typedef boost::function<bool(EKeystate)> function_t;
     function_t function = NULL;
 
-    function_t* result = LLKeyboardActionRegistry::getValue(function_name);
+    LLKeybindFunctionData* result = LLKeyboardActionRegistry::getValue(function_name);
     if (result)
     {
-        function = *result;
+        function = result->mFunction;
     }
 
     if (!function)
     {
-        LL_WARNS() << "Can't bind mouse key to function " << function_name << ", no function with this name found" << LL_ENDL;
+        LL_WARNS_ONCE() << "Can't bind mouse key to function " << function_name << ", no function with this name found" << LL_ENDL;
         return FALSE;
     }
 
-    // check for duplicate first and overwrite
-    S32 size = mMouseBindings[mode].size();
-    for (index = 0; index < size; index++)
-    {
-        if (mouse == mMouseBindings[mode][index].mMouse && mask == mMouseBindings[mode][index].mMask)
-            break;
-    }
-
     if (mode >= MODE_COUNT)
     {
         LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL;
         return FALSE;
     }
 
+    // check for duplicate first and overwrite
+    if (result->mIsGlobal)
+    {
+        S32 size = mGlobalMouseBindings[mode].size();
+        for (index = 0; index < size; index++)
+        {
+            if (mouse == mGlobalMouseBindings[mode][index].mMouse && mask == mGlobalMouseBindings[mode][index].mMask)
+            {
+                mGlobalMouseBindings[mode][index].mFunction = function;
+                return true;
+            }
+        }
+    }
+    else
+    {
+        S32 size = mMouseBindings[mode].size();
+        for (index = 0; index < size; index++)
+        {
+            if (mouse == mMouseBindings[mode][index].mMouse && mask == mMouseBindings[mode][index].mMask)
+            {
+                mMouseBindings[mode][index].mFunction = function;
+                return true;
+            }
+        }
+    }
+
     LLMouseBinding bind;
     bind.mMouse = mouse;
     bind.mMask = mask;
     bind.mFunction = function;
 
-    mMouseBindings[mode].push_back(bind);
+    if (result->mIsGlobal)
+    {
+        mGlobalMouseBindings[mode].push_back(bind);
+    }
+    else
+    {
+        mMouseBindings[mode].push_back(bind);
+    }
 
     return TRUE;
 }
@@ -1162,6 +1251,8 @@ void LLViewerInput::resetBindings()
 {
     for (S32 i = 0; i < MODE_COUNT; i++)
     {
+        mGlobalKeyBindings[i].clear();
+        mGlobalMouseBindings[i].clear();
         mKeyBindings[i].clear();
         mMouseBindings[i].clear();
     }
@@ -1536,5 +1627,11 @@ bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask
         if (mouse == mMouseBindings[mode][index].mMouse && mask == mMouseBindings[mode][index].mMask)
             return true;
     }
+    size = mGlobalMouseBindings[mode].size();
+    for (S32 index = 0; index < size; index++)
+    {
+        if (mouse == mGlobalMouseBindings[mode][index].mMouse && mask == mGlobalMouseBindings[mode][index].mMask)
+            return true;
+    }
     return false;
 }
-- 
cgit v1.2.3