summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/CMakeLists.txt2
-rw-r--r--indra/llcommon/indra_constants.h11
-rw-r--r--indra/llcommon/llapr.cpp151
-rw-r--r--indra/llcommon/llapr.h7
-rw-r--r--indra/llcommon/llkeybind.cpp395
-rw-r--r--indra/llcommon/llkeybind.h106
6 files changed, 607 insertions, 65 deletions
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..10b98f49aa 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -54,6 +54,17 @@ enum ETerrainBrushType
E_LANDBRUSH_INVALID = 6
};
+enum EMouseClickType{
+ CLICK_NONE = -1,
+ CLICK_LEFT = 0,
+ CLICK_MIDDLE,
+ CLICK_RIGHT,
+ CLICK_BUTTON4,
+ CLICK_BUTTON5,
+ CLICK_DOUBLELEFT,
+ CLICK_COUNT // 'size', CLICK_NONE does not counts
+};
+
// keys
// Bit masks for various keyboard modifier keys.
const MASK MASK_NONE = 0x0000;
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 29f0c7da9a..984e90f376 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -242,6 +242,64 @@ void _ll_apr_assert_status(apr_status_t status, const char* file, int line)
//---------------------------------------------------------------------
//
+// Scope based pool access
+//
+//---------------------------------------------------------------------
+
+class LLAPRFilePoolScope
+{
+public:
+ LLAPRFilePoolScope() : pPool(NULL), mInitialized(false) {}
+ LLAPRFilePoolScope(LLVolatileAPRPool* poolp) : mInitialized(false)
+ {
+ setFilePool(poolp);
+ }
+ ~LLAPRFilePoolScope()
+ {
+ reset();
+ }
+ apr_pool_t* getVolatileAPRPool(LLVolatileAPRPool* poolp = NULL)
+ {
+ if (!pPool)
+ {
+ setFilePool(poolp);
+ }
+ if (mInitialized)
+ {
+ // We need one clear per one get
+ // At the moment no need to support multiple calls
+ LL_ERRS() << "LLAPRFilePoolScope is not supposed to be initialized twice" << LL_ENDL;
+ }
+ mInitialized = true;
+ return pPool->getVolatileAPRPool();
+ }
+ void reset()
+ {
+ if (mInitialized)
+ {
+ pPool->clearVolatileAPRPool();
+ }
+ }
+
+private:
+ void setFilePool(LLVolatileAPRPool* poolp = NULL)
+ {
+ if (poolp)
+ {
+ pPool = poolp;
+ }
+ else
+ {
+ pPool = LLAPRFile::sAPRFilePoolp;
+ }
+ }
+
+ LLVolatileAPRPool *pPool;
+ bool mInitialized;
+};
+
+//---------------------------------------------------------------------
+//
// LLAPRFile functions
//
LLAPRFile::LLAPRFile()
@@ -287,9 +345,10 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLV
//check if already open some file
llassert_always(!mFile) ;
llassert_always(!mCurrentFilePoolp) ;
-
- apr_pool_t* apr_pool = pool ? pool->getVolatileAPRPool() : NULL ;
- s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(apr_pool));
+
+ mCurrentFilePoolp = pool ? pool : sAPRFilePoolp;
+ apr_pool_t* apr_pool = mCurrentFilePoolp->getVolatileAPRPool(); //paired with clear in close()
+ s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool);
if (s != APR_SUCCESS || !mFile)
{
@@ -314,14 +373,10 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLV
*sizep = file_size;
}
- if(!mCurrentFilePoolp)
+ if (!mFile)
{
- mCurrentFilePoolp = pool ;
-
- if(!mFile)
- {
- close() ;
- }
+ // It will clean pool
+ close() ;
}
return s ;
@@ -348,17 +403,6 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOO
return s;
}
-apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool)
-{
- if(!pool)
- {
- mCurrentFilePoolp = sAPRFilePoolp ;
- return mCurrentFilePoolp->getVolatileAPRPool() ;
- }
-
- return pool ;
-}
-
// File I/O
S32 LLAPRFile::read(void *buf, S32 nbytes)
{
@@ -415,7 +459,7 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
//
//static
-apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool)
+apr_status_t LLAPRFile::close(apr_file_t* file_handle)
{
apr_status_t ret = APR_SUCCESS ;
if(file_handle)
@@ -424,29 +468,23 @@ apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool)
file_handle = NULL ;
}
- if(pool)
- {
- pool->clearVolatileAPRPool() ;
- }
-
return ret ;
}
//static
-apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
+apr_file_t* LLAPRFile::open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags)
{
apr_status_t s;
apr_file_t* file_handle ;
- pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
- s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());
+ s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool);
if (s != APR_SUCCESS || !file_handle)
{
ll_apr_warn_status(s);
LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL;
file_handle = NULL ;
- close(file_handle, pool) ;
+ close(file_handle) ;
return NULL;
}
@@ -489,8 +527,9 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
{
//*****************************************
- apr_file_t* file_handle = open(filename, pool, APR_READ|APR_BINARY);
- //*****************************************
+ LLAPRFilePoolScope scope(pool);
+ apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), APR_READ|APR_BINARY);
+ //*****************************************
if (!file_handle)
{
return 0;
@@ -523,7 +562,7 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb
}
//*****************************************
- close(file_handle, pool) ;
+ close(file_handle) ;
//*****************************************
return (S32)bytes_read;
}
@@ -537,9 +576,10 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
flags |= APR_APPEND;
offset = 0;
}
-
+
//*****************************************
- apr_file_t* file_handle = open(filename, pool, flags);
+ LLAPRFilePoolScope scope(pool);
+ apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), flags);
//*****************************************
if (!file_handle)
{
@@ -573,7 +613,7 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
}
//*****************************************
- LLAPRFile::close(file_handle, pool);
+ LLAPRFile::close(file_handle);
//*****************************************
return (S32)bytes_written;
@@ -584,9 +624,8 @@ bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)
{
apr_status_t s;
- pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
- s = apr_file_remove(filename.c_str(), pool->getVolatileAPRPool());
- pool->clearVolatileAPRPool() ;
+ LLAPRFilePoolScope scope(pool);
+ s = apr_file_remove(filename.c_str(), scope.getVolatileAPRPool());
if (s != APR_SUCCESS)
{
@@ -602,9 +641,8 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname,
{
apr_status_t s;
- pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
- s = apr_file_rename(filename.c_str(), newname.c_str(), pool->getVolatileAPRPool());
- pool->clearVolatileAPRPool() ;
+ LLAPRFilePoolScope scope(pool);
+ s = apr_file_rename(filename.c_str(), newname.c_str(), scope.getVolatileAPRPool());
if (s != APR_SUCCESS)
{
@@ -621,18 +659,16 @@ bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, ap
apr_file_t* apr_file;
apr_status_t s;
- pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
- s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());
+ LLAPRFilePoolScope scope(pool);
+ s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, scope.getVolatileAPRPool());
if (s != APR_SUCCESS || !apr_file)
{
- pool->clearVolatileAPRPool() ;
return false;
}
else
{
apr_file_close(apr_file) ;
- pool->clearVolatileAPRPool() ;
return true;
}
}
@@ -643,14 +679,12 @@ S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
apr_file_t* apr_file;
apr_finfo_t info;
apr_status_t s;
-
- pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
- s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool->getVolatileAPRPool());
+
+ LLAPRFilePoolScope scope(pool);
+ s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, scope.getVolatileAPRPool());
if (s != APR_SUCCESS || !apr_file)
- {
- pool->clearVolatileAPRPool() ;
-
+ {
return 0;
}
else
@@ -658,7 +692,6 @@ S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file);
apr_file_close(apr_file) ;
- pool->clearVolatileAPRPool() ;
if (s == APR_SUCCESS)
{
@@ -676,9 +709,8 @@ bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool)
{
apr_status_t s;
- pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
- s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool->getVolatileAPRPool());
- pool->clearVolatileAPRPool() ;
+ LLAPRFilePoolScope scope(pool);
+ s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, scope.getVolatileAPRPool());
if (s != APR_SUCCESS)
{
@@ -694,9 +726,8 @@ bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool)
{
apr_status_t s;
- pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
- s = apr_file_remove(dirname.c_str(), pool->getVolatileAPRPool());
- pool->clearVolatileAPRPool() ;
+ LLAPRFilePoolScope scope(pool);
+ s = apr_file_remove(dirname.c_str(), scope.getVolatileAPRPool());
if (s != APR_SUCCESS)
{
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index da50dda103..0d6637f999 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -180,9 +180,6 @@ public:
S32 write(const void* buf, S32 nbytes);
apr_file_t* getFileHandle() {return mFile;}
-
-private:
- apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;
//
//*******************************************************************************************************************************
@@ -192,8 +189,8 @@ public:
static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist.
private:
- static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags);
- static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ;
+ static apr_file_t* open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags);
+ static apr_status_t close(apr_file_t* file) ;
static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);
public:
// returns false if failure:
diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp
new file mode 100644
index 0000000000..ecfc289cb3
--- /dev/null
+++ b/indra/llcommon/llkeybind.cpp
@@ -0,0 +1,395 @@
+/**
+ * @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),
+ mIgnoreMasks(false)
+{
+}
+
+LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, MASK 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)
+{
+ 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
+{
+ 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;
+ }
+ return data;
+}
+
+bool LLKeyData::isEmpty() const
+{
+ return mMouse == CLICK_NONE && mKey == KEY_NONE;
+}
+
+void LLKeyData::reset()
+{
+ mMouse = CLICK_NONE;
+ mKey = KEY_NONE;
+ mMask = MASK_NONE;
+ mIgnoreMasks = false;
+}
+
+LLKeyData& LLKeyData::operator=(const LLKeyData& rhs)
+{
+ mMouse = rhs.mMouse;
+ mKey = rhs.mKey;
+ mMask = rhs.mMask;
+ mIgnoreMasks = rhs.mIgnoreMasks;
+ 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;
+ if (mIgnoreMasks != rhs.mIgnoreMasks) 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;
+ 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) == data.mMask) || 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) == mask) || mask == mMask))
+ {
+ return true;
+ }
+ return false;
+}
+
+// LLKeyBind
+
+LLKeyBind::LLKeyBind(const LLSD &key_bind)
+{
+ if (key_bind.isArray())
+ {
+ 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)
+{
+ 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::operator!=(const LLKeyBind& rhs)
+{
+ 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;
+}
+
+bool LLKeyBind::isEmpty() const
+{
+ for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
+ {
+ if (!iter->isEmpty()) return false;
+ }
+ return true;
+}
+
+LLSD LLKeyBind::asLLSD() const
+{
+ S32 last = mData.size() - 1;
+ while (mData[last].empty())
+ {
+ last--;
+ }
+
+ LLSD data;
+ for (S32 i = 0; i <= last; ++i)
+ {
+ // append even if empty to not affect visual representation
+ data.append(mData[i].asLLSD());
+ }
+ return data;
+}
+
+bool LLKeyBind::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
+{
+ if (mouse == CLICK_NONE && key == KEY_NONE)
+ {
+ // assume placeholder
+ return false;
+ }
+
+ for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
+ {
+ if (iter->canHandle(mouse, key, mask))
+ {
+ 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);
+}
+
+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
+{
+ 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))
+ {
+ mData.push_back(LLKeyData(mouse, key, mask, ignore));
+ return true;
+ }
+ return false;
+}
+
+bool LLKeyBind::addKeyData(const LLKeyData& data)
+{
+ if (!hasKeyData(data))
+ {
+ mData.push_back(data);
+ return true;
+ }
+ return false;
+}
+
+void LLKeyBind::replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index)
+{
+ 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->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;
+ }
+ }
+ }
+ if (mData.size() <= index)
+ {
+ mData.resize(index + 1);
+ }
+ mData[index] = data;
+}
+
+void LLKeyBind::resetKeyData(S32 index)
+{
+ if (mData.size() > index)
+ {
+ mData[index].reset();
+ }
+}
+
+void LLKeyBind::trimEmpty()
+{
+ S32 last = mData.size() - 1;
+ while (last >= 0 && mData[last].empty())
+ {
+ mData.erase(mData.begin() + last);
+ last--;
+ }
+}
+
+U32 LLKeyBind::getDataCount()
+{
+ return mData.size();
+}
+
diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h
new file mode 100644
index 0000000000..ad0ebec67c
--- /dev/null
+++ b/indra/llcommon/llkeybind.h
@@ -0,0 +1,106 @@
+/**
+ * @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(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;
+ 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);
+
+ bool canHandle(const LLKeyData& data) const;
+ bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const;
+
+ EMouseClickType mMouse;
+ KEY mKey;
+ MASK mMask;
+ // Either to expect exact match or ignore not expected masks
+ bool mIgnoreMasks;
+};
+
+// One function can bind to multiple Key options
+class LLKeyBind
+{
+public:
+ LLKeyBind() {}
+ LLKeyBind(const LLSD &key_bind);
+
+ bool operator==(const LLKeyBind& rhs);
+ bool operator!=(const LLKeyBind& rhs);
+ bool isEmpty() const;
+ bool empty() const { return isEmpty(); };
+
+ 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;
+
+ // 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);
+ 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:
+ typedef std::vector<LLKeyData> data_vector_t;
+ data_vector_t mData;
+};
+
+
+#endif // LL_KEYBIND_H