From b9294516fc65f7a172ae119e20865b70c43c19c0 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Thu, 19 Sep 2019 16:55:28 +0300
Subject: SL-6109 Implement keybindings

---
 indra/llcommon/CMakeLists.txt    |   2 +
 indra/llcommon/indra_constants.h |  10 +++
 indra/llcommon/llkeybind.cpp     | 147 +++++++++++++++++++++++++++++++++++++++
 indra/llcommon/llkeybind.h       |  70 +++++++++++++++++++
 4 files changed, 229 insertions(+)
 create mode 100644 indra/llcommon/llkeybind.cpp
 create mode 100644 indra/llcommon/llkeybind.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index af41b9e460..7e52a620db 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -73,6 +73,7 @@ set(llcommon_SOURCE_FILES
     llinitparam.cpp
     llinitdestroyclass.cpp
     llinstancetracker.cpp
+    llkeybind.cpp
     llleap.cpp
     llleaplistener.cpp
     llliveappconfig.cpp
@@ -183,6 +184,7 @@ set(llcommon_HEADER_FILES
     llinitdestroyclass.h
     llinitparam.h
     llinstancetracker.h
+    llkeybind.h
     llkeythrottle.h
     llleap.h
     llleaplistener.h
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index e7b0e0ef8e..f8c0232660 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -54,6 +54,16 @@ enum ETerrainBrushType
 	E_LANDBRUSH_INVALID = 6
 };
 
+enum EMouseClickType{
+    CLICK_NONE = -1,
+    CLICK_LEFT = 0,
+    CLICK_MIDDLE,
+    CLICK_RIGHT,
+    CLICK_BUTTON4,
+    CLICK_BUTTON5,
+    CLICK_DOUBLELEFT
+};
+
 // keys
 // Bit masks for various keyboard modifier keys.
 const MASK MASK_NONE =			0x0000;
diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp
new file mode 100644
index 0000000000..f227c0a1a5
--- /dev/null
+++ b/indra/llcommon/llkeybind.cpp
@@ -0,0 +1,147 @@
+/** 
+ * @file llkeybind.cpp
+ * @brief Information about key combinations.
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, 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 "llkeybind.h"
+
+#include "llsd.h"
+#include "llsdutil.h"
+
+LLKeyData::LLKeyData()
+    : mMouse(CLICK_NONE), mKey(KEY_NONE), mMask(MASK_NONE)
+{
+}
+
+LLKeyData::LLKeyData(const LLSD &key_data)
+{
+    mMouse = (EMouseClickType)key_data["mouse"].asInteger();
+    mKey = key_data["key"].asInteger();
+    mMask = key_data["mask"].asInteger();
+}
+
+LLSD LLKeyData::asLLSD() const
+{
+    LLSD data;
+    data["mouse"] = (LLSD::Integer)mMouse;
+    data["key"] = (LLSD::Integer)mKey;
+    data["mask"] = (LLSD::Integer)mMask;
+    return data;
+}
+
+bool LLKeyData::isEmpty() const
+{
+    return mMouse == CLICK_NONE && mKey == KEY_NONE &&  mMask == MASK_NONE;
+}
+
+void LLKeyData::reset()
+{
+    mMouse = CLICK_NONE;
+    mKey = KEY_NONE;
+    mMask = MASK_NONE;
+}
+
+LLKeyData& LLKeyData::operator=(const LLKeyData& rhs)
+{
+    mMouse = rhs.mMouse;
+    mKey = rhs.mKey;
+    mMask = rhs.mMask;
+    return *this;
+}
+
+// LLKeyBind
+
+LLKeyBind::LLKeyBind(const LLSD &key_bind)
+{
+    if (key_bind.has("DataPrimary"))
+    {
+        mDataPrimary = LLKeyData(key_bind["DataPrimary"]);
+    }
+    if (key_bind.has("DataSecondary"))
+    {
+        mDataSecondary = LLKeyData(key_bind["DataSecondary"]);
+    }
+}
+
+bool LLKeyBind::operator==(const LLKeyBind& rhs)
+{
+    if (mDataPrimary.mMouse != rhs.mDataPrimary.mMouse) return false;
+    if (mDataPrimary.mKey != rhs.mDataPrimary.mKey) return false;
+    if (mDataPrimary.mMask != rhs.mDataPrimary.mMask) return false;
+    if (mDataSecondary.mMouse != rhs.mDataSecondary.mMouse) return false;
+    if (mDataSecondary.mKey != rhs.mDataSecondary.mKey) return false;
+    if (mDataSecondary.mMask != rhs.mDataSecondary.mMask) return false;
+    return true;
+}
+
+bool LLKeyBind::empty()
+{
+    if (mDataPrimary.mMouse != CLICK_NONE) return false;
+    if (mDataPrimary.mKey != KEY_NONE) return false;
+    if (mDataPrimary.mMask != MASK_NONE) return false;
+    if (mDataSecondary.mMouse != CLICK_NONE) return false;
+    if (mDataSecondary.mKey != KEY_NONE) return false;
+    if (mDataSecondary.mMask != MASK_NONE) return false;
+    return false;
+}
+
+LLSD LLKeyBind::asLLSD() const
+{
+    LLSD data;
+    if (!mDataPrimary.isEmpty())
+    {
+        data["DataPrimary"] = mDataPrimary.asLLSD();
+    }
+    if (!mDataSecondary.isEmpty())
+    {
+        data["DataSecondary"] = mDataSecondary.asLLSD();
+    }
+    return data;
+}
+
+bool LLKeyBind::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
+{
+    if (mDataPrimary.mKey == key && mDataPrimary.mMask == mask && mDataPrimary.mMouse == mouse)
+    {
+        return true;
+    }
+    if (mDataSecondary.mKey == key && mDataSecondary.mMask == mask && mDataSecondary.mMouse == mouse)
+    {
+        return true;
+    }
+    return false;
+}
+
+bool LLKeyBind::canHandleKey(KEY key, MASK mask) const
+{
+    return canHandle(CLICK_NONE, key, mask);
+}
+
+bool LLKeyBind::canHandleMouse(EMouseClickType mouse, MASK mask) const
+{
+    return canHandle(mouse, KEY_NONE, mask);
+}
+
diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h
new file mode 100644
index 0000000000..4fe622fb79
--- /dev/null
+++ b/indra/llcommon/llkeybind.h
@@ -0,0 +1,70 @@
+/** 
+ * @file llkeybind.h
+ * @brief Information about key combinations.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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_KEYBIND_H
+#define LL_KEYBIND_H
+
+#include "indra_constants.h"
+
+// KeyData - single key combination (mouse/mask/keyboard)
+class LL_COMMON_API LLKeyData
+{
+public:
+    LLKeyData();
+    LLKeyData(const LLSD &key_data);
+
+    LLSD asLLSD() const;
+    bool isEmpty() const;
+    void reset();
+    LLKeyData& operator=(const LLKeyData& rhs);
+
+    EMouseClickType mMouse;
+    KEY mKey;
+    MASK mMask;
+};
+
+// One function can bind to multiple Key options
+class LLKeyBind
+{
+public:
+    LLKeyBind() {}
+    LLKeyBind(const LLSD &key_bind);
+
+    bool operator==(const LLKeyBind& rhs);
+    bool empty();
+
+    LLSD asLLSD() const;
+
+    bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const;
+    bool canHandleKey(KEY key, MASK mask) const;
+    bool canHandleMouse(EMouseClickType mouse, MASK mask) const;
+
+    LLKeyData mDataPrimary;
+    LLKeyData mDataSecondary;
+};
+
+
+#endif // LL_KEYBIND_H
-- 
cgit v1.2.3


From 4df05c5a8995158922c7b7aacfef442ac8ae6fdd Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Tue, 17 Sep 2019 21:36:59 +0300
Subject: SL-6109 Keyaboard support ready

---
 indra/llcommon/llkeybind.cpp | 180 ++++++++++++++++++++++++++++++++++++-------
 indra/llcommon/llkeybind.h   |  23 +++++-
 2 files changed, 171 insertions(+), 32 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp
index f227c0a1a5..765084bbf6 100644
--- a/indra/llcommon/llkeybind.cpp
+++ b/indra/llcommon/llkeybind.cpp
@@ -36,6 +36,11 @@ LLKeyData::LLKeyData()
 {
 }
 
+LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, MASK mask)
+: mMouse(mouse), mKey(key), mMask(mask)
+{
+}
+
 LLKeyData::LLKeyData(const LLSD &key_data)
 {
     mMouse = (EMouseClickType)key_data["mouse"].asInteger();
@@ -72,65 +77,100 @@ LLKeyData& LLKeyData::operator=(const LLKeyData& rhs)
     return *this;
 }
 
+bool LLKeyData::operator==(const LLKeyData& rhs)
+{
+    if (mMouse != rhs.mMouse) return false;
+    if (mKey != rhs.mKey) return false;
+    if (mMask != rhs.mMask) return false;
+    return true;
+}
+
+bool LLKeyData::operator!=(const LLKeyData& rhs)
+{
+    if (mMouse != rhs.mMouse) return true;
+    if (mKey != rhs.mKey) return true;
+    if (mMask != rhs.mMask) return true;
+    return false;
+}
+
 // LLKeyBind
 
 LLKeyBind::LLKeyBind(const LLSD &key_bind)
 {
-    if (key_bind.has("DataPrimary"))
-    {
-        mDataPrimary = LLKeyData(key_bind["DataPrimary"]);
-    }
-    if (key_bind.has("DataSecondary"))
+    if (key_bind.isArray())
     {
-        mDataSecondary = LLKeyData(key_bind["DataSecondary"]);
+        for (LLSD::array_const_iterator data = key_bind.beginArray(), endLists = key_bind.endArray();
+            data != endLists;
+            data++
+            )
+        {
+            mData.push_back(LLKeyData(*data));
+        }
     }
 }
 
 bool LLKeyBind::operator==(const LLKeyBind& rhs)
 {
-    if (mDataPrimary.mMouse != rhs.mDataPrimary.mMouse) return false;
-    if (mDataPrimary.mKey != rhs.mDataPrimary.mKey) return false;
-    if (mDataPrimary.mMask != rhs.mDataPrimary.mMask) return false;
-    if (mDataSecondary.mMouse != rhs.mDataSecondary.mMouse) return false;
-    if (mDataSecondary.mKey != rhs.mDataSecondary.mKey) return false;
-    if (mDataSecondary.mMask != rhs.mDataSecondary.mMask) return false;
+    U32 size = mData.size();
+    if (size != rhs.mData.size()) return false;
+
+    for (U32 i = 0; i < size; i++)
+    {
+        if (mData[i] != rhs.mData[i]) return false;
+    }
+
     return true;
 }
 
-bool LLKeyBind::empty()
+bool LLKeyBind::operator!=(const LLKeyBind& rhs)
 {
-    if (mDataPrimary.mMouse != CLICK_NONE) return false;
-    if (mDataPrimary.mKey != KEY_NONE) return false;
-    if (mDataPrimary.mMask != MASK_NONE) return false;
-    if (mDataSecondary.mMouse != CLICK_NONE) return false;
-    if (mDataSecondary.mKey != KEY_NONE) return false;
-    if (mDataSecondary.mMask != MASK_NONE) return false;
+    U32 size = mData.size();
+    if (size != rhs.mData.size()) return true;
+
+    for (U32 i = 0; i < size; i++)
+    {
+        if (mData[i] != rhs.mData[i]) return true;
+    }
+
     return false;
 }
 
-LLSD LLKeyBind::asLLSD() const
+bool LLKeyBind::isEmpty() const
 {
-    LLSD data;
-    if (!mDataPrimary.isEmpty())
+    for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
     {
-        data["DataPrimary"] = mDataPrimary.asLLSD();
+        if (!iter->isEmpty()) return false;
     }
-    if (!mDataSecondary.isEmpty())
+    return true;
+}
+
+LLSD LLKeyBind::asLLSD() const
+{
+    LLSD data;
+    for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
     {
-        data["DataSecondary"] = mDataSecondary.asLLSD();
+        if (!iter->isEmpty())
+        {
+            data.append(iter->asLLSD());
+        }
     }
     return data;
 }
 
 bool LLKeyBind::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
 {
-    if (mDataPrimary.mKey == key && mDataPrimary.mMask == mask && mDataPrimary.mMouse == mouse)
+    if (mouse == CLICK_NONE && key == KEY_NONE)
     {
-        return true;
+        // assume placeholder
+        return false;
     }
-    if (mDataSecondary.mKey == key && mDataSecondary.mMask == mask && mDataSecondary.mMouse == mouse)
+
+    for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
     {
-        return true;
+        if (iter->mKey == key && iter->mMask == mask && iter->mMouse == mouse)
+        {
+            return true;
+        }
     }
     return false;
 }
@@ -145,3 +185,85 @@ bool LLKeyBind::canHandleMouse(EMouseClickType mouse, MASK mask) const
     return canHandle(mouse, KEY_NONE, mask);
 }
 
+bool LLKeyBind::addKeyData(EMouseClickType mouse, KEY key, MASK mask)
+{
+    if (!canHandle(mouse, key, mask))
+    {
+        mData.push_back(LLKeyData(mouse, key, mask));
+        return true;
+    }
+    return false;
+}
+
+bool LLKeyBind::addKeyData(const LLKeyData& data)
+{
+    if (!canHandle(data.mMouse, data.mKey, data.mMask))
+    {
+        mData.push_back(data);
+        return true;
+    }
+    return false;
+}
+
+void LLKeyBind::replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, U32 index)
+{
+    if (mouse != CLICK_NONE && key != KEY_NONE && mask != MASK_NONE)
+    {
+        for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
+        {
+            if (iter->mKey == key && iter->mMask == mask && iter->mMouse == mouse)
+            {
+                mData.erase(iter);
+                break;
+            }
+        }
+    }
+    if (mData.size() > index)
+    {
+        mData[index] = LLKeyData(mouse, key, mask);
+    }
+    else
+    {
+        mData.push_back(LLKeyData(mouse, key, mask));
+    }
+}
+
+void LLKeyBind::replaceKeyData(const LLKeyData& data, U32 index)
+{
+    for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
+    {
+        if (iter->mKey == data.mKey && iter->mMask == data.mMask && iter->mMouse == data.mMouse)
+        {
+            mData.erase(iter);
+            break;
+        }
+    }
+    if (mData.size() > index)
+    {
+        mData[index] = data;
+    }
+    else
+    {
+        mData.push_back(data);
+    }
+}
+
+bool LLKeyBind::hasKeyData(U32 index) const
+{
+    return mData.size() > index;
+}
+
+LLKeyData LLKeyBind::getKeyData(U32 index) const
+{
+    if (mData.size() > index)
+    {
+        return mData[index];
+    }
+    return LLKeyData();
+}
+
+U32 LLKeyBind::getDataCount()
+{
+    return mData.size();
+}
+
diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h
index 4fe622fb79..481949f275 100644
--- a/indra/llcommon/llkeybind.h
+++ b/indra/llcommon/llkeybind.h
@@ -34,12 +34,16 @@ class LL_COMMON_API LLKeyData
 {
 public:
     LLKeyData();
+    LLKeyData(EMouseClickType mouse, KEY key, MASK mask);
     LLKeyData(const LLSD &key_data);
 
     LLSD asLLSD() const;
     bool isEmpty() const;
+    bool empty() const { return isEmpty(); };
     void reset();
     LLKeyData& operator=(const LLKeyData& rhs);
+    bool operator==(const LLKeyData& rhs);
+    bool operator!=(const LLKeyData& rhs);
 
     EMouseClickType mMouse;
     KEY mKey;
@@ -54,7 +58,9 @@ public:
     LLKeyBind(const LLSD &key_bind);
 
     bool operator==(const LLKeyBind& rhs);
-    bool empty();
+    bool operator!=(const LLKeyBind& rhs);
+    bool isEmpty() const;
+    bool empty() const { return isEmpty(); };
 
     LLSD asLLSD() const;
 
@@ -62,8 +68,19 @@ public:
     bool canHandleKey(KEY key, MASK mask) const;
     bool canHandleMouse(EMouseClickType mouse, MASK mask) const;
 
-    LLKeyData mDataPrimary;
-    LLKeyData mDataSecondary;
+    // these methods enshure there will be no repeats
+    bool addKeyData(EMouseClickType mouse, KEY key, MASK mask);
+    bool addKeyData(const LLKeyData& data);
+    void replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, U32 index);
+    void replaceKeyData(const LLKeyData& data, U32 index);
+    bool hasKeyData(U32 index) const;
+    void clear() { mData.clear(); };
+    LLKeyData getKeyData(U32 index) const;
+    U32 getDataCount();
+
+private:
+    typedef std::vector<LLKeyData> data_vector_t;
+    data_vector_t mData;
 };
 
 
-- 
cgit v1.2.3


From c60b929fbb615f8d73f7bf42849b5628bf0f8f7a Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Wed, 25 Sep 2019 17:54:36 +0300
Subject: SL-6109 Mouse support ready

---
 indra/llcommon/indra_constants.h |   3 +-
 indra/llcommon/llkeybind.cpp     | 152 +++++++++++++++++++++++++++++++++------
 indra/llcommon/llkeybind.h       |  13 +++-
 3 files changed, 142 insertions(+), 26 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index f8c0232660..10b98f49aa 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -61,7 +61,8 @@ enum EMouseClickType{
     CLICK_RIGHT,
     CLICK_BUTTON4,
     CLICK_BUTTON5,
-    CLICK_DOUBLELEFT
+    CLICK_DOUBLELEFT,
+    CLICK_COUNT // 'size', CLICK_NONE does not counts
 };
 
 // keys
diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp
index 765084bbf6..0eca289d4b 100644
--- a/indra/llcommon/llkeybind.cpp
+++ b/indra/llcommon/llkeybind.cpp
@@ -32,20 +32,59 @@
 #include "llsdutil.h"
 
 LLKeyData::LLKeyData()
-    : mMouse(CLICK_NONE), mKey(KEY_NONE), mMask(MASK_NONE)
+    :
+    mMouse(CLICK_NONE),
+    mKey(KEY_NONE),
+    mMask(MASK_NONE),
+    mIgnoreMasks(false)
 {
 }
 
 LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, MASK mask)
-: mMouse(mouse), mKey(key), mMask(mask)
+    :
+    mMouse(mouse),
+    mKey(key),
+    mMask(mask),
+    mIgnoreMasks(false)
+{
+}
+
+LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, bool ignore_mask)
+    :
+    mMouse(mouse),
+    mKey(key),
+    mMask(MASK_NONE),
+    mIgnoreMasks(ignore_mask)
+{
+}
+
+LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask)
+    :
+    mMouse(mouse),
+    mKey(key),
+    mMask(mask),
+    mIgnoreMasks(ignore_mask)
 {
 }
 
 LLKeyData::LLKeyData(const LLSD &key_data)
 {
-    mMouse = (EMouseClickType)key_data["mouse"].asInteger();
-    mKey = key_data["key"].asInteger();
-    mMask = key_data["mask"].asInteger();
+    if (key_data.has("mouse"))
+    {
+        mMouse = (EMouseClickType)key_data["mouse"].asInteger();
+    }
+    if (key_data.has("key"))
+    {
+        mKey = key_data["key"].asInteger();
+    }
+    if (key_data.has("ignore_accelerators"))
+    {
+        mIgnoreMasks = key_data["ignore_accelerators"];
+    }
+    if (key_data.has("mask"))
+    {
+        mMask = key_data["mask"].asInteger();
+    }
 }
 
 LLSD LLKeyData::asLLSD() const
@@ -53,13 +92,20 @@ LLSD LLKeyData::asLLSD() const
     LLSD data;
     data["mouse"] = (LLSD::Integer)mMouse;
     data["key"] = (LLSD::Integer)mKey;
-    data["mask"] = (LLSD::Integer)mMask;
+    if (mIgnoreMasks)
+    {
+        data["ignore_accelerators"] = (LLSD::Boolean)mIgnoreMasks;
+    }
+    else
+    {
+        data["mask"] = (LLSD::Integer)mMask;
+    }
     return data;
 }
 
 bool LLKeyData::isEmpty() const
 {
-    return mMouse == CLICK_NONE && mKey == KEY_NONE &&  mMask == MASK_NONE;
+    return mMouse == CLICK_NONE && mKey == KEY_NONE;
 }
 
 void LLKeyData::reset()
@@ -67,6 +113,7 @@ void LLKeyData::reset()
     mMouse = CLICK_NONE;
     mKey = KEY_NONE;
     mMask = MASK_NONE;
+    mIgnoreMasks = false;
 }
 
 LLKeyData& LLKeyData::operator=(const LLKeyData& rhs)
@@ -74,6 +121,7 @@ LLKeyData& LLKeyData::operator=(const LLKeyData& rhs)
     mMouse = rhs.mMouse;
     mKey = rhs.mKey;
     mMask = rhs.mMask;
+    mIgnoreMasks = rhs.mIgnoreMasks;
     return *this;
 }
 
@@ -82,6 +130,7 @@ bool LLKeyData::operator==(const LLKeyData& rhs)
     if (mMouse != rhs.mMouse) return false;
     if (mKey != rhs.mKey) return false;
     if (mMask != rhs.mMask) return false;
+    if (mIgnoreMasks != rhs.mIgnoreMasks) return false;
     return true;
 }
 
@@ -90,6 +139,29 @@ bool LLKeyData::operator!=(const LLKeyData& rhs)
     if (mMouse != rhs.mMouse) return true;
     if (mKey != rhs.mKey) return true;
     if (mMask != rhs.mMask) return true;
+    if (mIgnoreMasks != rhs.mIgnoreMasks) return true;
+    return false;
+}
+
+bool LLKeyData::canHandle(const LLKeyData& data) const
+{
+    if (data.mKey == mKey
+        && data.mMouse == mMouse
+        && (mIgnoreMasks || data.mMask == mMask))
+    {
+        return true;
+    }
+    return false;
+}
+
+bool LLKeyData::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
+{
+    if (mouse == mMouse
+        && key == mKey
+        && (mIgnoreMasks || mask == mMask))
+    {
+        return true;
+    }
     return false;
 }
 
@@ -167,7 +239,7 @@ bool LLKeyBind::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
 
     for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
     {
-        if (iter->mKey == key && iter->mMask == mask && iter->mMouse == mouse)
+        if (iter->canHandle(mouse, key, mask))
         {
             return true;
         }
@@ -185,11 +257,34 @@ bool LLKeyBind::canHandleMouse(EMouseClickType mouse, MASK mask) const
     return canHandle(mouse, KEY_NONE, mask);
 }
 
-bool LLKeyBind::addKeyData(EMouseClickType mouse, KEY key, MASK mask)
+bool LLKeyBind::hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const
+{
+    if (mouse != CLICK_NONE || key != KEY_NONE)
+    {
+        for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
+        {
+            if (iter->mKey == key
+                && iter->mMask == mask
+                && iter->mMouse == mouse
+                && iter->mIgnoreMasks == ignore)
+            {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool LLKeyBind::hasKeyData(const LLKeyData& data) const
 {
-    if (!canHandle(mouse, key, mask))
+    return hasKeyData(data.mMouse, data.mKey, data.mMask, data.mIgnoreMasks);
+}
+
+bool LLKeyBind::addKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore)
+{
+    if (!hasKeyData(mouse, key, mask, ignore))
     {
-        mData.push_back(LLKeyData(mouse, key, mask));
+        mData.push_back(LLKeyData(mouse, key, mask, ignore));
         return true;
     }
     return false;
@@ -197,7 +292,7 @@ bool LLKeyBind::addKeyData(EMouseClickType mouse, KEY key, MASK mask)
 
 bool LLKeyBind::addKeyData(const LLKeyData& data)
 {
-    if (!canHandle(data.mMouse, data.mKey, data.mMask))
+    if (!hasKeyData(data))
     {
         mData.push_back(data);
         return true;
@@ -205,37 +300,48 @@ bool LLKeyBind::addKeyData(const LLKeyData& data)
     return false;
 }
 
-void LLKeyBind::replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, U32 index)
+void LLKeyBind::replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index)
 {
-    if (mouse != CLICK_NONE && key != KEY_NONE && mask != MASK_NONE)
+    if (mouse != CLICK_NONE || key != KEY_NONE )
     {
-        for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
+        // if both click and key are none, we are inserting a placeholder, we don't want to reset anything
+        // otherwise reset identical key
+        for (data_vector_t::iterator iter = mData.begin(); iter != mData.end(); iter++)
         {
-            if (iter->mKey == key && iter->mMask == mask && iter->mMouse == mouse)
+            if (iter->mKey == key
+                && iter->mMouse == mouse
+                && iter->mIgnoreMasks == ignore
+                && (iter->mIgnoreMasks || iter->mMask == mask))
             {
-                mData.erase(iter);
+                iter->reset();
                 break;
             }
         }
     }
     if (mData.size() > index)
     {
-        mData[index] = LLKeyData(mouse, key, mask);
+        mData[index] = LLKeyData(mouse, key, mask, ignore);
     }
     else
     {
-        mData.push_back(LLKeyData(mouse, key, mask));
+        mData.push_back(LLKeyData(mouse, key, mask, ignore));
     }
 }
 
 void LLKeyBind::replaceKeyData(const LLKeyData& data, U32 index)
 {
-    for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
+    if (!data.isEmpty())
     {
-        if (iter->mKey == data.mKey && iter->mMask == data.mMask && iter->mMouse == data.mMouse)
+        for (data_vector_t::iterator iter = mData.begin(); iter != mData.end(); iter++)
         {
-            mData.erase(iter);
-            break;
+            if (iter->mKey == data.mKey
+                && iter->mMouse == data.mMouse
+                && iter->mIgnoreMasks == data.mIgnoreMasks
+                && (iter->mIgnoreMasks || iter->mMask == data.mMask))
+            {
+                iter->reset();
+                break;
+            }
         }
     }
     if (mData.size() > index)
diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h
index 481949f275..25179a57f3 100644
--- a/indra/llcommon/llkeybind.h
+++ b/indra/llcommon/llkeybind.h
@@ -35,6 +35,8 @@ class LL_COMMON_API LLKeyData
 public:
     LLKeyData();
     LLKeyData(EMouseClickType mouse, KEY key, MASK mask);
+    LLKeyData(EMouseClickType mouse, KEY key, bool ignore_mask);
+    LLKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask);
     LLKeyData(const LLSD &key_data);
 
     LLSD asLLSD() const;
@@ -45,9 +47,13 @@ public:
     bool operator==(const LLKeyData& rhs);
     bool operator!=(const LLKeyData& rhs);
 
+    bool canHandle(const LLKeyData& data) const;
+    bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const;
+
     EMouseClickType mMouse;
     KEY mKey;
     MASK mMask;
+    bool mIgnoreMasks;
 };
 
 // One function can bind to multiple Key options
@@ -68,10 +74,13 @@ public:
     bool canHandleKey(KEY key, MASK mask) const;
     bool canHandleMouse(EMouseClickType mouse, MASK mask) const;
 
+    bool LLKeyBind::hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const;
+    bool LLKeyBind::hasKeyData(const LLKeyData& data) const;
+
     // these methods enshure there will be no repeats
-    bool addKeyData(EMouseClickType mouse, KEY key, MASK mask);
+    bool addKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore);
     bool addKeyData(const LLKeyData& data);
-    void replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, U32 index);
+    void replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index);
     void replaceKeyData(const LLKeyData& data, U32 index);
     bool hasKeyData(U32 index) const;
     void clear() { mData.clear(); };
-- 
cgit v1.2.3


From 2532a2ee9ee9003e2c6b72f8da19979a9e3dd2f6 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Thu, 26 Sep 2019 22:28:18 +0300
Subject: SL-6109 Conflict resolution

---
 indra/llcommon/llkeybind.cpp | 76 ++++++++++++++++++++++++++++++++++----------
 indra/llcommon/llkeybind.h   | 19 ++++++++---
 2 files changed, 73 insertions(+), 22 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp
index 0eca289d4b..ff88a9c9aa 100644
--- a/indra/llcommon/llkeybind.cpp
+++ b/indra/llcommon/llkeybind.cpp
@@ -218,13 +218,17 @@ bool LLKeyBind::isEmpty() const
 
 LLSD LLKeyBind::asLLSD() const
 {
+    S32 last = mData.size() - 1;
+    while (mData[last].empty())
+    {
+        last--;
+    }
+
     LLSD data;
-    for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
+    for (S32 i = 0; i <= last; ++i)
     {
-        if (!iter->isEmpty())
-        {
-            data.append(iter->asLLSD());
-        }
+        // append even if empty to not affect visual representation
+        data.append(mData[i].asLLSD());
     }
     return data;
 }
@@ -280,6 +284,43 @@ bool LLKeyBind::hasKeyData(const LLKeyData& data) const
     return hasKeyData(data.mMouse, data.mKey, data.mMask, data.mIgnoreMasks);
 }
 
+bool LLKeyBind::hasKeyData(U32 index) const
+{
+    return mData.size() > index;
+}
+
+S32 LLKeyBind::findKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const
+{
+    if (mouse != CLICK_NONE || key != KEY_NONE)
+    {
+        for (S32 i = 0; i < mData.size(); ++i)
+        {
+            if (mData[i].mKey == key
+                && mData[i].mMask == mask
+                && mData[i].mMouse == mouse
+                && mData[i].mIgnoreMasks == ignore)
+            {
+                return i;
+            }
+        }
+    }
+    return -1;
+}
+
+S32 LLKeyBind::findKeyData(const LLKeyData& data) const
+{
+    return findKeyData(data.mMouse, data.mKey, data.mMask, data.mIgnoreMasks);
+}
+
+LLKeyData LLKeyBind::getKeyData(U32 index) const
+{
+    if (mData.size() > index)
+    {
+        return mData[index];
+    }
+    return LLKeyData();
+}
+
 bool LLKeyBind::addKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore)
 {
     if (!hasKeyData(mouse, key, mask, ignore))
@@ -344,28 +385,29 @@ void LLKeyBind::replaceKeyData(const LLKeyData& data, U32 index)
             }
         }
     }
-    if (mData.size() > index)
+    if (mData.size() <= index)
     {
-        mData[index] = data;
-    }
-    else
-    {
-        mData.push_back(data);
+        mData.resize(index + 1);
     }
+    mData[index] = data;
 }
 
-bool LLKeyBind::hasKeyData(U32 index) const
+void LLKeyBind::resetKeyData(S32 index)
 {
-    return mData.size() > index;
+    if (mData.size() > index)
+    {
+        mData[index].reset();
+    }
 }
 
-LLKeyData LLKeyBind::getKeyData(U32 index) const
+void LLKeyBind::trimEmpty()
 {
-    if (mData.size() > index)
+    S32 last = mData.size() - 1;
+    while (last >= 0 && mData[last].empty())
     {
-        return mData[index];
+        mData.erase(mData.begin() + last);
+        last--;
     }
-    return LLKeyData();
 }
 
 U32 LLKeyBind::getDataCount()
diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h
index 25179a57f3..39cb668aac 100644
--- a/indra/llcommon/llkeybind.h
+++ b/indra/llcommon/llkeybind.h
@@ -74,17 +74,26 @@ public:
     bool canHandleKey(KEY key, MASK mask) const;
     bool canHandleMouse(EMouseClickType mouse, MASK mask) const;
 
-    bool LLKeyBind::hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const;
-    bool LLKeyBind::hasKeyData(const LLKeyData& data) const;
+    // contains specified combination
+    bool hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const;
+    bool hasKeyData(const LLKeyData& data) const;
+    bool hasKeyData(U32 index) const;
+
+    // index of contained LLKeyData
+    S32 findKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const;
+    S32 findKeyData(const LLKeyData& data) const;
+
+    LLKeyData getKeyData(U32 index) const;
 
     // these methods enshure there will be no repeats
     bool addKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore);
     bool addKeyData(const LLKeyData& data);
     void replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index);
     void replaceKeyData(const LLKeyData& data, U32 index);
-    bool hasKeyData(U32 index) const;
-    void clear() { mData.clear(); };
-    LLKeyData getKeyData(U32 index) const;
+    void resetKeyData(S32 index);
+    void clear() { mData.clear(); }
+    // if there any empty LLKeyData in the end of the array, remove them
+    void trimEmpty();
     U32 getDataCount();
 
 private:
-- 
cgit v1.2.3


From e211372923bed31e632bc9825913d3d57cdc2d52 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Thu, 3 Oct 2019 22:45:29 +0300
Subject: SL-6109 Remade 'ignore' list processing, renamed and reformed
 keybindings

---
 indra/llcommon/llkeybind.cpp | 9 +++------
 indra/llcommon/llkeybind.h   | 3 ++-
 2 files changed, 5 insertions(+), 7 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp
index ff88a9c9aa..46a3230240 100644
--- a/indra/llcommon/llkeybind.cpp
+++ b/indra/llcommon/llkeybind.cpp
@@ -92,14 +92,11 @@ LLSD LLKeyData::asLLSD() const
     LLSD data;
     data["mouse"] = (LLSD::Integer)mMouse;
     data["key"] = (LLSD::Integer)mKey;
+    data["mask"] = (LLSD::Integer)mMask;
     if (mIgnoreMasks)
     {
         data["ignore_accelerators"] = (LLSD::Boolean)mIgnoreMasks;
     }
-    else
-    {
-        data["mask"] = (LLSD::Integer)mMask;
-    }
     return data;
 }
 
@@ -147,7 +144,7 @@ bool LLKeyData::canHandle(const LLKeyData& data) const
 {
     if (data.mKey == mKey
         && data.mMouse == mMouse
-        && (mIgnoreMasks || data.mMask == mMask))
+        && ((mIgnoreMasks && (data.mMask & mMask) == data.mMask) || data.mMask == mMask))
     {
         return true;
     }
@@ -158,7 +155,7 @@ bool LLKeyData::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
 {
     if (mouse == mMouse
         && key == mKey
-        && (mIgnoreMasks || mask == mMask))
+        && ((mIgnoreMasks && (mask & mMask) == mask) || mask == mMask))
     {
         return true;
     }
diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h
index 39cb668aac..ad0ebec67c 100644
--- a/indra/llcommon/llkeybind.h
+++ b/indra/llcommon/llkeybind.h
@@ -53,7 +53,8 @@ public:
     EMouseClickType mMouse;
     KEY mKey;
     MASK mMask;
-    bool mIgnoreMasks;
+    // Either to expect exact match or ignore not expected masks
+    bool mIgnoreMasks; 
 };
 
 // One function can bind to multiple Key options
-- 
cgit v1.2.3


From 5568018bd20a43c30caca0c6288e63bfae29a2e3 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Sun, 10 Nov 2019 19:06:03 +0200
Subject: SL-6109 Better key and table localization support and fix for
 key-replacing

---
 indra/llcommon/llkeybind.cpp | 31 ++++++-------------------------
 1 file changed, 6 insertions(+), 25 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp
index 46a3230240..ecfc289cb3 100644
--- a/indra/llcommon/llkeybind.cpp
+++ b/indra/llcommon/llkeybind.cpp
@@ -340,43 +340,24 @@ bool LLKeyBind::addKeyData(const LLKeyData& data)
 
 void LLKeyBind::replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index)
 {
-    if (mouse != CLICK_NONE || key != KEY_NONE )
-    {
-        // if both click and key are none, we are inserting a placeholder, we don't want to reset anything
-        // otherwise reset identical key
-        for (data_vector_t::iterator iter = mData.begin(); iter != mData.end(); iter++)
-        {
-            if (iter->mKey == key
-                && iter->mMouse == mouse
-                && iter->mIgnoreMasks == ignore
-                && (iter->mIgnoreMasks || iter->mMask == mask))
-            {
-                iter->reset();
-                break;
-            }
-        }
-    }
-    if (mData.size() > index)
-    {
-        mData[index] = LLKeyData(mouse, key, mask, ignore);
-    }
-    else
-    {
-        mData.push_back(LLKeyData(mouse, key, mask, ignore));
-    }
+    replaceKeyData(LLKeyData(mouse, key, mask, ignore), index);
 }
 
 void LLKeyBind::replaceKeyData(const LLKeyData& data, U32 index)
 {
     if (!data.isEmpty())
     {
+        // if both click and key are none (isEmpty()), we are inserting a placeholder, we don't want to reset anything
+        // otherwise reset identical key
         for (data_vector_t::iterator iter = mData.begin(); iter != mData.end(); iter++)
         {
             if (iter->mKey == data.mKey
                 && iter->mMouse == data.mMouse
                 && iter->mIgnoreMasks == data.mIgnoreMasks
-                && (iter->mIgnoreMasks || iter->mMask == data.mMask))
+                && iter->mMask == data.mMask)
             {
+                // Replacing only fully equal combinations even in case 'ignore' is set
+                // Reason: Simplicity and user might decide to do a 'move' command as W and Shift+Ctrl+W, and 'run' as Shift+W
                 iter->reset();
                 break;
             }
-- 
cgit v1.2.3


From 6092e2ffab9ec76bdd8821e188db9cb785456eee Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 15 Jun 2020 18:13:46 +0300
Subject: SL-13418 Added converter from old mouse binding settings to new ones

---
 indra/llcommon/llkeybind.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h
index ad0ebec67c..c6b4bd970f 100644
--- a/indra/llcommon/llkeybind.h
+++ b/indra/llcommon/llkeybind.h
@@ -53,7 +53,7 @@ public:
     EMouseClickType mMouse;
     KEY mKey;
     MASK mMask;
-    // Either to expect exact match or ignore not expected masks
+    // Either to expect exact match or ignore not expected masks as long as expected mask-bit is present
     bool mIgnoreMasks; 
 };
 
-- 
cgit v1.2.3


From 7e0254ecd5923a488e69036c256a05890193524c Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Thu, 28 Nov 2019 17:09:34 +0200
Subject: SL-6109 Fixed issue with llcontrols ignoring left mouse button with
 masks

---
 indra/llcommon/llkeybind.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp
index ecfc289cb3..38696c2258 100644
--- a/indra/llcommon/llkeybind.cpp
+++ b/indra/llcommon/llkeybind.cpp
@@ -144,7 +144,7 @@ bool LLKeyData::canHandle(const LLKeyData& data) const
 {
     if (data.mKey == mKey
         && data.mMouse == mMouse
-        && ((mIgnoreMasks && (data.mMask & mMask) == data.mMask) || data.mMask == mMask))
+        && ((mIgnoreMasks && (data.mMask & mMask) == mMask) || data.mMask == mMask))
     {
         return true;
     }
@@ -155,7 +155,7 @@ bool LLKeyData::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
 {
     if (mouse == mMouse
         && key == mKey
-        && ((mIgnoreMasks && (mask & mMask) == mask) || mask == mMask))
+        && ((mIgnoreMasks && (mask & mMask) == mMask) || mask == mMask))
     {
         return true;
     }
-- 
cgit v1.2.3