summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandreykproductengine <andreykproductengine@lindenlab.com>2019-09-25 17:54:36 +0300
committerAndrey Kleshchev <andreykproductengine@lindenlab.com>2020-06-23 14:48:03 +0300
commitc60b929fbb615f8d73f7bf42849b5628bf0f8f7a (patch)
tree87c7bc9df86f49183df5176f8376ad8711383fdd
parent4df05c5a8995158922c7b7aacfef442ac8ae6fdd (diff)
SL-6109 Mouse support ready
-rw-r--r--indra/llcommon/indra_constants.h3
-rw-r--r--indra/llcommon/llkeybind.cpp152
-rw-r--r--indra/llcommon/llkeybind.h13
-rw-r--r--indra/llui/llscrolllistcell.cpp5
-rw-r--r--indra/newview/llagent.cpp11
-rw-r--r--indra/newview/llagent.h1
-rw-r--r--indra/newview/llappviewer.cpp1
-rw-r--r--indra/newview/llfloaterpreference.cpp92
-rw-r--r--indra/newview/llfloaterpreference.h2
-rw-r--r--indra/newview/llkeyconflict.cpp131
-rw-r--r--indra/newview/llkeyconflict.h10
-rw-r--r--indra/newview/llviewerkeyboard.cpp424
-rw-r--r--indra/newview/llviewerkeyboard.h82
-rw-r--r--indra/newview/llviewerwindow.cpp68
-rw-r--r--indra/newview/llviewerwindow.h3
-rw-r--r--indra/newview/skins/default/xui/en/floater_select_key.xml16
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_controls.xml10
17 files changed, 813 insertions, 211 deletions
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(); };
diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp
index 63762ab8b8..0a33ee8878 100644
--- a/indra/llui/llscrolllistcell.cpp
+++ b/indra/llui/llscrolllistcell.cpp
@@ -314,6 +314,11 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
left + mFont->getWidth(mText.getString(), mHighlightOffset, mHighlightCount) + 1,
1);
mRoundedRectImage->draw(highlight_rect, highlight_color);
+ /*LLRect highlight_rect(left - 2,
+ mFont->getLineHeight() + 2,
+ left + getWidth() + 2,
+ 1);
+ mRoundedRectImage->draw(highlight_rect, LLColor4::black);*/
}
// Try to draw the entire string
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index f6d6f7c897..f3df79fb6b 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -830,6 +830,17 @@ bool LLAgent::enableFlying()
return !sitting;
}
+// static
+bool LLAgent::isSitting()
+{
+ BOOL sitting = FALSE;
+ if (isAgentAvatarValid())
+ {
+ sitting = gAgentAvatarp->isSitting();
+ }
+ return sitting;
+}
+
void LLAgent::standUp()
{
setControlFlags(AGENT_CONTROL_STAND_UP);
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 1a352d3397..88cce0b911 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -351,6 +351,7 @@ public:
static void toggleFlying();
static bool enableFlying();
BOOL canFly(); // Does this parcel allow you to fly?
+ static bool isSitting();
//--------------------------------------------------------------------
// Voice
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index ff921dcfdb..1cb3c1af31 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1447,6 +1447,7 @@ bool LLAppViewer::doFrame()
{
joystick->scanJoystick();
gKeyboard->scanKeyboard();
+ gViewerKeyboard.scanMouse();
}
// Update state based on messages, user input, object idle.
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 34cfe6ebb4..d7a8f9fd4f 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -166,7 +166,7 @@ static const U32 ALLOW_MASK_MOUSE = 2;
static const U32 ALLOW_KEYS = 4; //keyboard
static const U32 ALLOW_MASK_KEYS = 8;
static const U32 ALLOW_MASKS = 16;
-static const U32 IGNORE_MASKS = 32; // For example W (aka Forward) should work regardless of SHIFT being pressed
+static const U32 CAN_IGNORE_MASKS = 32; // For example W (aka Forward) should work regardless of SHIFT being pressed
static const U32 DEFAULT_KEY_FILTER = ALLOW_MOUSE | ALLOW_MASK_MOUSE | ALLOW_KEYS | ALLOW_MASK_KEYS;
class LLSetKeyBindDialog : public LLModalDialog
@@ -176,6 +176,7 @@ public:
~LLSetKeyBindDialog();
/*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quiting);
void setParent(LLPanelPreferenceControls* parent, U32 key_mask = DEFAULT_KEY_FILTER);
@@ -186,18 +187,23 @@ public:
static void onDefault(void* user_data);
private:
- LLPanelPreferenceControls* mParent;
+ LLPanelPreferenceControls* pParent;
+ LLCheckBoxCtrl* pCheckBox;
U32 mKeyMask;
};
LLSetKeyBindDialog::LLSetKeyBindDialog(const LLSD& key)
: LLModalDialog(key),
- mParent(NULL),
+ pParent(NULL),
mKeyMask(DEFAULT_KEY_FILTER)
{
}
+LLSetKeyBindDialog::~LLSetKeyBindDialog()
+{
+}
+
//virtual
BOOL LLSetKeyBindDialog::postBuild()
{
@@ -205,15 +211,24 @@ BOOL LLSetKeyBindDialog::postBuild()
childSetAction("Default", onDefault, this);
childSetAction("Cancel", onCancel, this);
getChild<LLUICtrl>("Cancel")->setFocus(TRUE);
-
+
+ pCheckBox = getChild<LLCheckBoxCtrl>("ignore_masks");
+
gFocusMgr.setKeystrokesOnly(TRUE);
return TRUE;
}
+//virtual
+void LLSetKeyBindDialog::onClose(bool app_quiting)
+{
+ pParent = NULL;
+ LLModalDialog::onClose(app_quiting);
+}
+
void LLSetKeyBindDialog::setParent(LLPanelPreferenceControls* parent, U32 key_mask)
{
- mParent = parent;
+ pParent = parent;
mKeyMask = key_mask;
LLTextBase *text_ctrl = getChild<LLTextBase>("descritption");
@@ -232,10 +247,10 @@ void LLSetKeyBindDialog::setParent(LLPanelPreferenceControls* parent, U32 key_ma
input += getString("keyboard");
}
text_ctrl->setTextArg("[INPUT]", input);
-}
-LLSetKeyBindDialog::~LLSetKeyBindDialog()
-{
+ bool can_ignore_masks = (key_mask & CAN_IGNORE_MASKS) != 0;
+ pCheckBox->setVisible(can_ignore_masks);
+ pCheckBox->setValue(false);
}
BOOL LLSetKeyBindDialog::handleKeyHere(KEY key, MASK mask)
@@ -249,10 +264,19 @@ BOOL LLSetKeyBindDialog::handleKeyHere(KEY key, MASK mask)
return true;
}
+ if (key == KEY_DELETE)
+ {
+ if (pParent)
+ {
+ pParent->onSetKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false);
+ }
+ closeFloater();
+ return true;
+ }
+
// forbidden keys
if (key == KEY_NONE
|| key == KEY_RETURN
- || key == KEY_DELETE
|| key == KEY_BACKSPACE)
{
return false;
@@ -275,9 +299,9 @@ BOOL LLSetKeyBindDialog::handleKeyHere(KEY key, MASK mask)
return false;
}
- else if (mParent)
+ if (pParent)
{
- mParent->onSetKeyBind(CLICK_NONE, key, mask);
+ pParent->onSetKeyBind(CLICK_NONE, key, mask, pCheckBox->getValue().asBoolean());
}
closeFloater();
return result;
@@ -305,9 +329,9 @@ BOOL LLSetKeyBindDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClic
&& (clicktype != CLICK_RIGHT || mask != 0) // reassigning menu button is not supported
&& ((mKeyMask & ALLOW_MASK_MOUSE) != 0 || mask == 0))
{
- if (mParent)
+ if (pParent)
{
- mParent->onSetKeyBind(clicktype, KEY_NONE, mask);
+ pParent->onSetKeyBind(clicktype, KEY_NONE, mask, pCheckBox->getValue().asBoolean());
}
result = TRUE;
closeFloater();
@@ -333,9 +357,9 @@ void LLSetKeyBindDialog::onBlank(void* user_data)
{
LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
// tmp needs 'no key' button
- if (self->mParent)
+ if (self->pParent)
{
- self->mParent->onSetKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE);
+ self->pParent->onSetKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false);
}
self->closeFloater();
}
@@ -345,9 +369,9 @@ void LLSetKeyBindDialog::onDefault(void* user_data)
{
LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
// tmp needs 'no key' button
- if (self->mParent)
+ if (self->pParent)
{
- self->mParent->onDefaultKeyBind();
+ self->pParent->onDefaultKeyBind();
}
self->closeFloater();
}
@@ -2921,6 +2945,23 @@ BOOL LLPanelPreferenceControls::postBuild()
// Something of a workaround: cells don't handle clicks, so we catch a click, then process it on hover.
BOOL LLPanelPreferenceControls::handleHover(S32 x, S32 y, MASK mask)
{
+ /*S32 column = pControlsTable->getColumnIndexFromOffset(x);
+ LLScrollListItem* item = pControlsTable->hitItem(x, y);
+ static LLScrollListCell* last_cell = NULL;
+ if (item && column > 0)
+ {
+ LLScrollListCell* cell = item->getColumn(column);
+ if (cell)
+ {
+ cell->highlightText(0, CHAR_MAX);
+ if (last_cell != NULL && last_cell !=cell)
+ {
+ last_cell->highlightText(0, 0);
+ }
+ last_cell = cell;
+ }
+ }*/
+
if (mShowKeyDialog)
{
if (mEditingIndex > 0 && mConflictHandler[mEditingMode].canAssignControl((LLKeyConflictHandler::EControlTypes)mEditingIndex))
@@ -2932,14 +2973,14 @@ BOOL LLPanelPreferenceControls::handleHover(S32 x, S32 y, MASK mask)
LLSetKeyBindDialog* dialog = LLFloaterReg::showTypedInstance<LLSetKeyBindDialog>("keybind_dialog", LLSD(), TRUE);
if (dialog)
{
- if (mConflictHandler[mEditingMode].getLoadedMode() == LLKeyConflictHandler::MODE_GENERAL)
- {
+ /*if (mConflictHandler[mEditingMode].getLoadedMode() == LLKeyConflictHandler::MODE_GENERAL)
+ {*/
dialog->setParent(this, DEFAULT_KEY_FILTER);
- }
+ /*}
else
{
dialog->setParent(this, ALLOW_KEYS | ALLOW_MASK_KEYS);
- }
+ }*/
}
}
}
@@ -3082,10 +3123,6 @@ void LLPanelPreferenceControls::populateControlTable()
}
}
}
-
- //temp
- if (mEditingMode == LLKeyConflictHandler::MODE_GENERAL)
- pControlsTable->setEnabled(false);
}
// Just a workaround to not care about first separator before headers (we can start from random header)
@@ -3175,7 +3212,8 @@ void LLPanelPreferenceControls::onModeCommit()
regenerateControls();
}
-void LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MASK mask)
+// todo: copy onSetKeyBind to interface and inherit from interface
+void LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore_mask)
{
LLKeyConflictHandler::EControlTypes control = (LLKeyConflictHandler::EControlTypes)mEditingIndex;
@@ -3190,7 +3228,7 @@ void LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MAS
if (item && mEditingColumn > 0)
{
- mConflictHandler[mEditingMode].registerControl(control, mEditingColumn - 1, click, key, mask);
+ mConflictHandler[mEditingMode].registerControl(control, mEditingColumn - 1, click, key, mask, ignore_mask);
LLScrollListCell *cell = item->getColumn(1);
cell->setValue(mConflictHandler[mEditingMode].getControlString(control, 0));
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index c36dee114c..dbf493b60d 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -311,7 +311,7 @@ public:
void onListCommit();
void onModeCommit();
- void onSetKeyBind(EMouseClickType click, KEY key, MASK mask);
+ void onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore_mask);
void onRestoreDefaults();
void onDefaultKeyBind();
diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp
index 0f0129bf68..be0b8fd4ca 100644
--- a/indra/newview/llkeyconflict.cpp
+++ b/indra/newview/llkeyconflict.cpp
@@ -58,7 +58,6 @@ static const std::string typetostring[LLKeyConflictHandler::CONTROL_NUM_INDICES]
"control_wear",
"control_movements",
"control_moveto",
- "control_sit",
"control_teleportto",
"push_forward",
"push_backward",
@@ -69,8 +68,9 @@ static const std::string typetostring[LLKeyConflictHandler::CONTROL_NUM_INDICES]
"jump",
"push_down",
//"control_run",
- "control_toggle_run",
+ "toggle_run",
"toggle_fly",
+ "toggle_sit",
"stop_moving",
"control_camera",
"look_up",
@@ -103,8 +103,8 @@ static const std::string typetostring[LLKeyConflictHandler::CONTROL_NUM_INDICES]
"edit_avatar_move_forward",
"edit_avatar_move_backward",
"control_mediacontent",
- "control_parcel",
- "control_media",
+ "toggle_pause_media",
+ "toggle_enable_media",
"control_voice",
"control_toggle_voice",
"start_chat",
@@ -161,6 +161,10 @@ static const control_enum_t command_to_key =
{ "stop_moving", LLKeyConflictHandler::CONTROL_STOP },
{ "start_chat", LLKeyConflictHandler::CONTROL_START_CHAT },
{ "start_gesture", LLKeyConflictHandler::CONTROL_START_GESTURE },
+ { "toggle_run", LLKeyConflictHandler::CONTROL_TOGGLE_RUN },
+ { "toggle_sit", LLKeyConflictHandler::CONTROL_SIT },
+ { "toggle_parcel_media", LLKeyConflictHandler::CONTROL_PAUSE_MEDIA },
+ { "toggle_enable_media", LLKeyConflictHandler::CONTROL_ENABLE_MEDIA },
};
@@ -191,6 +195,60 @@ std::string string_from_mask(MASK mask)
return res;
}
+std::string string_from_mouse(EMouseClickType click)
+{
+ std::string res;
+ switch (click)
+ {
+ case CLICK_LEFT:
+ res = "LMB";
+ break;
+ case CLICK_MIDDLE:
+ res = "MMB";
+ break;
+ case CLICK_RIGHT:
+ res = "RMB";
+ break;
+ case CLICK_BUTTON4:
+ res = "MB4";
+ break;
+ case CLICK_BUTTON5:
+ res = "MB5";
+ break;
+ case CLICK_DOUBLELEFT:
+ res = "Double LMB";
+ break;
+ default:
+ break;
+ }
+ return res;
+}
+
+EMouseClickType mouse_from_string(const std::string& input)
+{
+ if (input == "LMB")
+ {
+ return CLICK_LEFT;
+ }
+ if (input == "MMB")
+ {
+ return CLICK_MIDDLE;
+ }
+ if (input == "RMB")
+ {
+ return CLICK_RIGHT;
+ }
+ if (input == "MB4")
+ {
+ return CLICK_BUTTON4;
+ }
+ if (input == "MB5")
+ {
+ return CLICK_BUTTON5;
+ }
+ return CLICK_NONE;
+}
+
// LLKeyConflictHandler
LLKeyConflictHandler::LLKeyConflictHandler()
@@ -245,14 +303,14 @@ bool LLKeyConflictHandler::canAssignControl(EControlTypes control_type)
return false;
}
-void LLKeyConflictHandler::registerControl(EControlTypes control_type, U32 index, EMouseClickType mouse, KEY key, MASK mask)
+void LLKeyConflictHandler::registerControl(EControlTypes control_type, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask)
{
LLKeyConflict &type_data = mControlsMap[control_type];
if (!type_data.mAssignable)
{
LL_ERRS() << "Error in code, user or system should not be able to change certain controls" << LL_ENDL;
}
- type_data.mKeyBind.replaceKeyData(mouse, key, mask, index);
+ type_data.mKeyBind.replaceKeyData(mouse, key, mask, ignore_mask, index);
mHasUnsavedChanges = true;
}
@@ -277,45 +335,11 @@ std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata)
}
else if (keydata.mMask != MASK_NONE)
{
- LL_ERRS() << "Masks binding without keys is not supported yet" << LL_ENDL;
+ result = LLKeyboard::stringFromAccelerator(keydata.mMask);
}
- #ifdef LL_DARWIN
- // darwin uses special symbols and doesn't need '+' for masks
- if (mMouse != CLICK_NONE && mKey != KEY_NONE)
- {
- result += " + ";
- }
- #else
- if (keydata.mMouse != CLICK_NONE && !result.empty())
- {
- result += " + ";
- }
- #endif
+ result += string_from_mouse(keydata.mMouse);
- switch (keydata.mMouse)
- {
- case CLICK_LEFT:
- result += "LMB";
- break;
- case CLICK_MIDDLE:
- result += "MMB";
- break;
- case CLICK_RIGHT:
- result += "RMB";
- break;
- case CLICK_BUTTON4:
- result += "MB4";
- break;
- case CLICK_BUTTON5:
- result += "MB5";
- break;
- case CLICK_DOUBLELEFT:
- result += "Double LMB";
- break;
- default:
- break;
- }
return result;
}
@@ -339,6 +363,8 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerKeyboard::KeyMode& ke
{
KEY key;
MASK mask;
+ EMouseClickType mouse = it->mouse.isProvided() ? mouse_from_string(it->mouse) : CLICK_NONE;
+ bool ignore = it->ignore.isProvided() ? it->ignore.getValue() : false;
if (it->key.getValue().empty())
{
key = KEY_NONE;
@@ -358,7 +384,7 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerKeyboard::KeyMode& ke
LLKeyConflict &type_data = (*destination)[iter->second];
type_data.mAssignable = true;
// Don't care about conflict level, all movement and view commands already account for it
- type_data.mKeyBind.addKeyData(CLICK_NONE, key, mask);
+ type_data.mKeyBind.addKeyData(mouse, key, mask, ignore);
}
}
}
@@ -418,6 +444,10 @@ void LLKeyConflictHandler::loadFromSettings(EModes load_mode)
{
mControlsMap.clear();
mDefaultsMap.clear();
+
+ // E.X. In case we need placeholder keys for conflict resolution.
+ generatePlaceholders(load_mode);
+
if (load_mode == MODE_GENERAL)
{
for (U32 i = 0; i < CONTROL_NUM_INDICES; i++)
@@ -463,12 +493,11 @@ void LLKeyConflictHandler::loadFromSettings(EModes load_mode)
}
else
{
- mControlsMap = mDefaultsMap;
+ // mind placeholders
+ mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end());
}
}
mLoadedMode = load_mode;
-
- generatePlaceholders();
}
void LLKeyConflictHandler::saveToSettings()
@@ -555,6 +584,8 @@ void LLKeyConflictHandler::saveToSettings()
binding.key = LLKeyboard::stringFromKey(data.mKey);
}
binding.mask = string_from_mask(data.mMask);
+ binding.mouse.set(string_from_mouse(data.mMouse), true); //set() because 'optional', for compatibility purposes
+ binding.ignore.set(data.mIgnoreMasks, true);
binding.command = getControlName(iter->first);
mode.bindings.add(binding);
}
@@ -711,8 +742,8 @@ void LLKeyConflictHandler::resetToDefaults(EModes mode)
else
{
mControlsMap.clear();
- mControlsMap = mDefaultsMap;
- generatePlaceholders();
+ generatePlaceholders(mode);
+ mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end());
}
mHasUnsavedChanges = true;
@@ -774,7 +805,7 @@ void LLKeyConflictHandler::resetKeyboardBindings()
gViewerKeyboard.loadBindingsXML(filename);
}
-void LLKeyConflictHandler::generatePlaceholders()
+void LLKeyConflictHandler::generatePlaceholders(EModes load_mode)
{
}
@@ -784,6 +815,6 @@ void LLKeyConflictHandler::registerTemporaryControl(EControlTypes control_type,
LLKeyConflict *type_data = &mControlsMap[control_type];
type_data->mAssignable = false;
type_data->mConflictMask = conflict_mask;
- type_data->mKeyBind.addKeyData(mouse, key, mask);
+ type_data->mKeyBind.addKeyData(mouse, key, mask, false);
}
diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h
index 79bd9b8438..7890be1e28 100644
--- a/indra/newview/llkeyconflict.h
+++ b/indra/newview/llkeyconflict.h
@@ -95,7 +95,6 @@ public:
CONTROL_WEAR,
CONTROL_MOVEMENTS, // Group control, for visual representation
CONTROL_MOVETO,
- CONTROL_SIT,
CONTROL_TELEPORTTO,
CONTROL_FORWARD,
CONTROL_BACKWARD,
@@ -108,6 +107,7 @@ public:
//CONTROL_RUN,
CONTROL_TOGGLE_RUN,
CONTROL_TOGGLE_FLY,
+ CONTROL_SIT,
CONTROL_STOP,
CONTROL_CAMERA, // Group control, for visual representation
CONTROL_LOOK_UP,
@@ -140,8 +140,8 @@ public:
CONTROL_EDIT_AV_MV_FORWARD,
CONTROL_EDIT_AV_MV_BACKWARD,
CONTROL_MEDIACONTENT, // Group control, for visual representation
- CONTROL_PARCEL, // Play pause
- CONTROL_MEDIA, // Play stop
+ CONTROL_PAUSE_MEDIA, // Play pause
+ CONTROL_ENABLE_MEDIA, // Play stop
CONTROL_VOICE, // Keep pressing for it to be ON
CONTROL_TOGGLE_VOICE, // Press once to ON/OFF
CONTROL_START_CHAT, // Press once to ON/OFF
@@ -165,7 +165,7 @@ public:
bool canHandleMouse(EControlTypes control_type, EMouseClickType mouse_ind, MASK mask);
bool canHandleMouse(EControlTypes control_type, S32 mouse_ind, MASK mask); //Just for convinience
bool canAssignControl(EControlTypes control_type);
- void registerControl(EControlTypes control_type, U32 data_index, EMouseClickType mouse_ind, KEY key, MASK mask); //todo: return conflicts?
+ void registerControl(EControlTypes control_type, U32 data_index, EMouseClickType mouse_ind, KEY key, MASK mask, bool ignore_mask); //todo: return conflicts?
LLKeyData getControl(EControlTypes control_type, U32 data_index);
@@ -202,7 +202,7 @@ private:
void loadFromSettings(const LLViewerKeyboard::KeyMode& keymode, control_map_t *destination);
void loadFromSettings(const EModes &load_mode, const std::string &filename, control_map_t *destination);
void resetKeyboardBindings();
- void generatePlaceholders(); //'headers' for ui and non-assignable values
+ void generatePlaceholders(EModes load_mode); //E.x. non-assignable values
control_map_t mControlsMap;
control_map_t mDefaultsMap;
diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp
index 1c93a2e954..fb1f33c6b0 100644
--- a/indra/newview/llviewerkeyboard.cpp
+++ b/indra/newview/llviewerkeyboard.cpp
@@ -605,12 +605,50 @@ void start_gesture( EKeystate s )
}
}
-void toggle_parcel_media(EKeystate s)
+void toggle_run(EKeystate s)
{
+ if (KEYSTATE_DOWN != s) return;
+ bool run = gAgent.getAlwaysRun();
+ if (run)
+ {
+ gAgent.clearAlwaysRun();
+ gAgent.clearRunning();
+ }
+ else
+ {
+ gAgent.setAlwaysRun();
+ gAgent.setRunning();
+ }
+ gAgent.sendWalkRun(!run);
+}
+
+void toggle_sit(EKeystate s)
+{
+ if (KEYSTATE_DOWN != s) return;
+ if (gAgent.isSitting())
+ {
+ gAgent.standUp();
+ }
+ else
+ {
+ gAgent.sitDown();
+ }
+}
+
+void toggle_pause_media(EKeystate s) // analogue of play/pause button in top bar
+{
+ if (KEYSTATE_DOWN != s) return;
bool pause = LLViewerMedia::isAnyMediaPlaying();
LLViewerMedia::setAllMediaPaused(pause);
}
+void toggle_enable_media(EKeystate s)
+{
+ if (KEYSTATE_DOWN != s) return;
+ bool pause = LLViewerMedia::isAnyMediaPlaying() || LLViewerMedia::isAnyMediaShowing();
+ LLViewerMedia::setAllMediaEnabled(!pause);
+}
+
#define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, ACTION);
REGISTER_KEYBOARD_ACTION("jump", agent_jump);
REGISTER_KEYBOARD_ACTION("push_down", agent_push_down);
@@ -652,20 +690,24 @@ REGISTER_KEYBOARD_ACTION("edit_avatar_move_backward", edit_avatar_move_backward)
REGISTER_KEYBOARD_ACTION("stop_moving", stop_moving);
REGISTER_KEYBOARD_ACTION("start_chat", start_chat);
REGISTER_KEYBOARD_ACTION("start_gesture", start_gesture);
-REGISTER_KEYBOARD_ACTION("toggle_parcel_media", toggle_parcel_media);
+REGISTER_KEYBOARD_ACTION("toggle_run", toggle_run);
+REGISTER_KEYBOARD_ACTION("toggle_sit", toggle_sit);
+REGISTER_KEYBOARD_ACTION("toggle_pause_media", toggle_pause_media);
+REGISTER_KEYBOARD_ACTION("toggle_enable_media", toggle_enable_media);
#undef REGISTER_KEYBOARD_ACTION
LLViewerKeyboard::LLViewerKeyboard()
{
- for (S32 i = 0; i < MODE_COUNT; i++)
- {
- mBindingCount[i] = 0;
- }
+ resetBindings();
for (S32 i = 0; i < KEY_COUNT; i++)
{
mKeyHandledByUI[i] = FALSE;
- }
+ }
+ for (S32 i = 0; i < CLICK_COUNT; i++)
+ {
+ mMouseLevel[i] = MOUSE_STATE_SILENT;
+ }
// we want the UI to never see these keys so that they can always control the avatar/camera
for(KEY k = KEY_PAD_UP; k <= KEY_PAD_DIVIDE; k++)
{
@@ -673,7 +715,7 @@ LLViewerKeyboard::LLViewerKeyboard()
}
}
-BOOL LLViewerKeyboard::modeFromString(const std::string& string, S32 *mode)
+BOOL LLViewerKeyboard::modeFromString(const std::string& string, S32 *mode) const
{
if (string == "FIRST_PERSON")
{
@@ -707,6 +749,40 @@ BOOL LLViewerKeyboard::modeFromString(const std::string& string, S32 *mode)
}
}
+BOOL LLViewerKeyboard::mouseFromString(const std::string& string, EMouseClickType *mode) const
+{
+ if (string == "LMB")
+ {
+ *mode = CLICK_LEFT;
+ return TRUE;
+ }
+ else if (string == "DLMB")
+ {
+ *mode = CLICK_DOUBLELEFT;
+ return TRUE;
+ }
+ else if (string == "MMB")
+ {
+ *mode = CLICK_MIDDLE;
+ return TRUE;
+ }
+ else if (string == "MB4")
+ {
+ *mode = CLICK_BUTTON4;
+ return TRUE;
+ }
+ else if (string == "MB5")
+ {
+ *mode = CLICK_BUTTON5;
+ return TRUE;
+ }
+ else
+ {
+ *mode = CLICK_NONE;
+ return FALSE;
+ }
+}
+
BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL repeated)
{
// check for re-map
@@ -750,7 +826,7 @@ BOOL LLViewerKeyboard::handleKeyUp(KEY translated_key, MASK translated_mask)
return gViewerWindow->handleKeyUp(translated_key, translated_mask);
}
-BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name)
+BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const bool ignore, const std::string& function_name)
{
S32 index;
typedef boost::function<void(EKeystate)> function_t;
@@ -791,11 +867,22 @@ BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, c
}
// check for duplicate first and overwrite
- for (index = 0; index < mBindingCount[mode]; index++)
- {
- if (key == mBindings[mode][index].mKey && mask == mBindings[mode][index].mMask)
- break;
- }
+ if (ignore)
+ {
+ for (index = 0; index < mKeyIgnoreMaskCount[mode]; index++)
+ {
+ if (key == mKeyIgnoreMask[mode][index].mKey)
+ break;
+ }
+ }
+ else
+ {
+ for (index = 0; index < mKeyBindingCount[mode]; index++)
+ {
+ if (key == mKeyBindings[mode][index].mKey && mask == mKeyBindings[mode][index].mMask)
+ break;
+ }
+ }
if (index >= MAX_KEY_BINDINGS)
{
@@ -809,20 +896,102 @@ BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, c
return FALSE;
}
- mBindings[mode][index].mKey = key;
- mBindings[mode][index].mMask = mask;
- mBindings[mode][index].mFunction = function;
+ if (ignore)
+ {
+ mKeyIgnoreMask[mode][index].mKey = key;
+ mKeyIgnoreMask[mode][index].mFunction = function;
+
+ if (index == mKeyIgnoreMaskCount[mode])
+ mKeyIgnoreMaskCount[mode]++;
+ }
+ else
+ {
+ mKeyBindings[mode][index].mKey = key;
+ mKeyBindings[mode][index].mMask = mask;
+ mKeyBindings[mode][index].mFunction = function;
- if (index == mBindingCount[mode])
- mBindingCount[mode]++;
+ if (index == mKeyBindingCount[mode])
+ mKeyBindingCount[mode]++;
+ }
return TRUE;
}
+BOOL LLViewerKeyboard::bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const bool ignore, const std::string& function_name)
+{
+ S32 index;
+ typedef boost::function<void(EKeystate)> function_t;
+ function_t function = NULL;
+
+ function_t* result = LLKeyboardActionRegistry::getValue(function_name);
+ if (result)
+ {
+ function = *result;
+ }
+
+ if (!function)
+ {
+ LL_ERRS() << "Can't bind key to function " << function_name << ", no function with this name found" << LL_ENDL;
+ return FALSE;
+ }
+
+ // check for duplicate first and overwrite
+ if (ignore)
+ {
+ for (index = 0; index < mMouseIgnoreMaskCount[mode]; index++)
+ {
+ if (mouse == mMouseIgnoreMask[mode][index].mMouse)
+ break;
+ }
+ }
+ else
+ {
+ for (index = 0; index < mMouseBindingCount[mode]; index++)
+ {
+ if (mouse == mMouseBindings[mode][index].mMouse && mask == mMouseBindings[mode][index].mMask)
+ break;
+ }
+ }
+
+ if (index >= MAX_KEY_BINDINGS)
+ {
+ LL_ERRS() << "LLKeyboard::bindKey() - too many keys for mode " << mode << LL_ENDL;
+ return FALSE;
+ }
+
+ if (mode >= MODE_COUNT)
+ {
+ LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL;
+ return FALSE;
+ }
+
+ if (ignore)
+ {
+ mMouseIgnoreMask[mode][index].mMouse = mouse;
+ mMouseIgnoreMask[mode][index].mFunction = function;
+
+ if (index == mMouseIgnoreMaskCount[mode])
+ mMouseIgnoreMaskCount[mode]++;
+ }
+ else
+ {
+ mMouseBindings[mode][index].mMouse = mouse;
+ mMouseBindings[mode][index].mMask = mask;
+ mMouseBindings[mode][index].mFunction = function;
+
+ if (index == mMouseBindingCount[mode])
+ mMouseBindingCount[mode]++;
+ }
+
+ return TRUE;
+}
+
LLViewerKeyboard::KeyBinding::KeyBinding()
: key("key"),
+ mouse("mouse"),
mask("mask"),
- command("command")
+ command("command"),
+ ignore("ignore", false)
{}
LLViewerKeyboard::KeyMode::KeyMode()
@@ -837,12 +1006,20 @@ LLViewerKeyboard::Keys::Keys()
edit_avatar("edit_avatar")
{}
+void LLViewerKeyboard::resetBindings()
+{
+ for (S32 i = 0; i < MODE_COUNT; i++)
+ {
+ mKeyBindingCount[i] = 0;
+ mKeyIgnoreMaskCount[i] = 0;
+ mMouseBindingCount[i] = 0;
+ mMouseIgnoreMaskCount[i] = 0;
+ }
+}
+
S32 LLViewerKeyboard::loadBindingsXML(const std::string& filename)
{
- for (S32 i = 0; i < MODE_COUNT; i++)
- {
- mBindingCount[i] = 0;
- }
+ resetBindings();
S32 binding_count = 0;
Keys keys;
@@ -872,9 +1049,20 @@ S32 LLViewerKeyboard::loadBindingMode(const LLViewerKeyboard::KeyMode& keymode,
{
KEY key;
MASK mask;
+ bool ignore = it->ignore.isProvided() ? it->ignore.getValue() : false;
LLKeyboard::keyFromString(it->key, &key);
LLKeyboard::maskFromString(it->mask, &mask);
- bindKey(mode, key, mask, it->command);
+ bindKey(mode, key, mask, ignore, it->command);
+ binding_count++;
+ }
+ else if (it->mouse.isProvided() && !it->mouse.getValue().empty())
+ {
+ EMouseClickType mouse;
+ MASK mask;
+ bool ignore = it->ignore.isProvided() ? it->ignore.getValue() : false;
+ mouseFromString(it->mouse.getValue(), &mouse);
+ LLKeyboard::maskFromString(it->mask, &mask);
+ bindMouse(mode, mouse, mask, ignore, it->command);
binding_count++;
}
}
@@ -966,7 +1154,7 @@ S32 LLViewerKeyboard::loadBindings(const std::string& filename)
}
// bind key
- if (bindKey(mode, key, mask, function_string))
+ if (bindKey(mode, key, mask, false, function_string))
{
binding_count++;
}
@@ -978,7 +1166,7 @@ S32 LLViewerKeyboard::loadBindings(const std::string& filename)
}
-EKeyboardMode LLViewerKeyboard::getMode()
+EKeyboardMode LLViewerKeyboard::getMode() const
{
if ( gAgentCamera.cameraMouselook() )
{
@@ -998,56 +1186,184 @@ EKeyboardMode LLViewerKeyboard::getMode()
}
}
-
-// Called from scanKeyboard.
-void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
+bool LLViewerKeyboard::scanKey(const LLKeyboardBinding* binding,
+ S32 binding_count,
+ KEY key,
+ MASK mask,
+ BOOL key_down,
+ BOOL key_up,
+ BOOL key_level,
+ bool repeat) const
{
- if (LLApp::isExiting())
- {
- return;
- }
-
- S32 mode = getMode();
- // Consider keyboard scanning as NOT mouse event. JC
- MASK mask = gKeyboard->currentMask(FALSE);
-
- LLKeyBinding* binding = mBindings[mode];
- S32 binding_count = mBindingCount[mode];
-
-
- if (mKeyHandledByUI[key])
- {
- return;
- }
-
- // don't process key down on repeated keys
- BOOL repeat = gKeyboard->getKeyRepeated(key);
-
for (S32 i = 0; i < binding_count; i++)
{
- //for (S32 key = 0; key < KEY_COUNT; key++)
if (binding[i].mKey == key)
{
- //if (binding[i].mKey == key && binding[i].mMask == mask)
if (binding[i].mMask == mask)
{
if (key_down && !repeat)
{
// ...key went down this frame, call function
binding[i].mFunction( KEYSTATE_DOWN );
+ return true;
}
else if (key_up)
{
// ...key went down this frame, call function
binding[i].mFunction( KEYSTATE_UP );
+ return true;
}
else if (key_level)
{
// ...key held down from previous frame
// Not windows, just call the function.
binding[i].mFunction( KEYSTATE_LEVEL );
+ return true;
}//if
+ // Key+Mask combinations are supposed to be unique, so we won't find anything else
+ return false;
}//if
- }//for
+ }//if
}//for
+ return false;
+}
+
+// Called from scanKeyboard.
+void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) const
+{
+ if (LLApp::isExiting())
+ {
+ return;
+ }
+
+ S32 mode = getMode();
+ // Consider keyboard scanning as NOT mouse event. JC
+ MASK mask = gKeyboard->currentMask(FALSE);
+
+ if (mKeyHandledByUI[key])
+ {
+ return;
+ }
+
+ // don't process key down on repeated keys
+ BOOL repeat = gKeyboard->getKeyRepeated(key);
+
+ if (scanKey(mKeyBindings[mode], mKeyBindingCount[mode], key, mask, key_down, key_up, key_level, repeat))
+ {
+ // Nothing found, try ignore list
+ scanKey(mKeyIgnoreMask[mode], mKeyIgnoreMaskCount[mode], key, MASK_NONE, key_down, key_up, key_level, repeat);
+ }
+}
+
+BOOL LLViewerKeyboard::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down)
+{
+ BOOL handled = gViewerWindow->handleAnyMouseClick(window_impl, pos, mask, clicktype, down);
+
+ if (clicktype != CLICK_NONE)
+ {
+ // special case
+ // if UI doesn't handle double click, LMB click is issued, so supres LMB 'down' when doubleclick is set
+ // handle !down as if we are handling doubleclick
+ bool override_lmb = (clicktype == CLICK_LEFT
+ && (mMouseLevel[CLICK_DOUBLELEFT] == MOUSE_STATE_DOWN || mMouseLevel[CLICK_DOUBLELEFT] == MOUSE_STATE_LEVEL));
+
+ if (override_lmb && !down)
+ {
+ // process doubleclick instead
+ clicktype = CLICK_DOUBLELEFT;
+ }
+
+ if (override_lmb && down)
+ {
+ // else-supress
+ }
+ // if UI handled 'down', it should handle 'up' as well
+ // if we handle 'down' not by UI, then we should handle 'up'/'level' regardless of UI
+ else if (handled && mMouseLevel[clicktype] != MOUSE_STATE_SILENT)
+ {
+ // UI handled new 'down' so iterupt whatever state we were in.
+ mMouseLevel[clicktype] = MOUSE_STATE_UP;
+ }
+ else if (down)
+ {
+ if (mMouseLevel[clicktype] == MOUSE_STATE_DOWN)
+ {
+ // this is repeated hit (mouse does not repeat event until release)
+ // for now treat rapid clicking like mouse being held
+ mMouseLevel[clicktype] = MOUSE_STATE_LEVEL;
+ }
+ else
+ {
+ mMouseLevel[clicktype] = MOUSE_STATE_DOWN;
+ }
+ }
+ else
+ {
+ // Released mouse key
+ mMouseLevel[clicktype] = MOUSE_STATE_UP;
+ }
+ }
+
+ return handled;
+}
+
+bool LLViewerKeyboard::scanMouse(const LLMouseBinding *binding, S32 binding_count, EMouseClickType mouse, MASK mask, EMouseState state) const
+{
+ for (S32 i = 0; i < binding_count; i++)
+ {
+ if (binding[i].mMouse == mouse && binding[i].mMask == mask)
+ {
+ switch (state)
+ {
+ case MOUSE_STATE_DOWN:
+ binding[i].mFunction(KEYSTATE_DOWN);
+ break;
+ case MOUSE_STATE_LEVEL:
+ binding[i].mFunction(KEYSTATE_LEVEL);
+ break;
+ case MOUSE_STATE_UP:
+ binding[i].mFunction(KEYSTATE_UP);
+ break;
+ default:
+ break;
+ }
+ // Key+Mask combinations are supposed to be unique, no need to continue
+ return true;
+ }
+ }
+ return false;
+}
+
+// todo: this recods key, scanMouse() triggers functions with EKeystate
+bool LLViewerKeyboard::scanMouse(EMouseClickType click, EMouseState state) const
+{
+ bool res = false;
+ S32 mode = getMode();
+ MASK mask = gKeyboard->currentMask(TRUE);
+ res = scanMouse(mMouseBindings[mode], mMouseBindingCount[mode], click, mask, state);
+ if (!res)
+ {
+ res = scanMouse(mMouseIgnoreMask[mode], mMouseIgnoreMaskCount[mode], click, MASK_NONE, state);
+ }
+ return res;
+}
+
+void LLViewerKeyboard::scanMouse()
+{
+ for (S32 i = 0; i < CLICK_COUNT; i++)
+ {
+ if (mMouseLevel[i] != MOUSE_STATE_SILENT)
+ {
+ scanMouse((EMouseClickType)i, mMouseLevel[i]);
+ if (mMouseLevel[i] == MOUSE_STATE_DOWN)
+ {
+ // mouse doesn't support 'continued' state like keyboard does, so after handling, switch to LEVEL
+ mMouseLevel[i] = MOUSE_STATE_LEVEL;
+ }
+ else if (mMouseLevel[i] == MOUSE_STATE_UP)
+ {
+ mMouseLevel[i] = MOUSE_STATE_SILENT;
+ }
+ }
+ }
}
diff --git a/indra/newview/llviewerkeyboard.h b/indra/newview/llviewerkeyboard.h
index 2bfe285be4..3ba033509c 100644
--- a/indra/newview/llviewerkeyboard.h
+++ b/indra/newview/llviewerkeyboard.h
@@ -43,6 +43,27 @@ public:
LLKeyFunc mFunction;
};
+class LLKeyboardBinding
+{
+public:
+ KEY mKey;
+ MASK mMask;
+ bool mIgnoreMask; // whether CTRL/ALT/SHIFT should be checked
+
+ LLKeyFunc mFunction;
+};
+
+class LLMouseBinding
+{
+public:
+ EMouseClickType mMouse;
+ MASK mMask;
+ bool mIgnoreMask; // whether CTRL/ALT/SHIFT should be checked
+
+ LLKeyFunc mFunction;
+};
+
+
typedef enum e_keyboard_mode
{
MODE_FIRST_PERSON,
@@ -53,6 +74,7 @@ typedef enum e_keyboard_mode
MODE_COUNT
} EKeyboardMode;
+class LLWindow;
void bind_keyboard_functions();
@@ -64,6 +86,8 @@ public:
Mandatory<std::string> key,
mask,
command;
+ Optional<std::string> mouse; // Note, not mandatory for the sake of backward campatibility
+ Optional<bool> ignore;
KeyBinding();
};
@@ -93,24 +117,68 @@ public:
S32 loadBindings(const std::string& filename); // returns number bound, 0 on error
S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error
- EKeyboardMode getMode();
+ EKeyboardMode getMode() const;
+
+ BOOL modeFromString(const std::string& string, S32 *mode) const; // False on failure
+ BOOL mouseFromString(const std::string& string, EMouseClickType *mode) const;// False on failure
- BOOL modeFromString(const std::string& string, S32 *mode); // False on failure
+ void scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) const;
- void scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);
+ // handleMouse() records state, scanMouse() goes through states, scanMouse(click) processes individual saved states after UI is done with them
+ BOOL handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
+ void LLViewerKeyboard::scanMouse();
private:
- S32 loadBindingMode(const LLViewerKeyboard::KeyMode& keymode, S32 mode);
- BOOL bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name);
+ bool scanKey(const LLKeyboardBinding* binding,
+ S32 binding_count,
+ KEY key,
+ MASK mask,
+ BOOL key_down,
+ BOOL key_up,
+ BOOL key_level,
+ bool repeat) const;
+
+ enum EMouseState
+ {
+ MOUSE_STATE_DOWN, // key down this frame
+ MOUSE_STATE_LEVEL, // clicked again fast, or never released
+ MOUSE_STATE_UP, // went up this frame
+ MOUSE_STATE_SILENT // notified about 'up', do not notify again
+ };
+ bool scanMouse(EMouseClickType click, EMouseState state) const;
+ bool scanMouse(const LLMouseBinding *binding,
+ S32 binding_count,
+ EMouseClickType mouse,
+ MASK mask,
+ EMouseState state) const;
+
+ S32 loadBindingMode(const LLViewerKeyboard::KeyMode& keymode, S32 mode);
+ BOOL bindKey(const S32 mode, const KEY key, const MASK mask, const bool ignore, const std::string& function_name);
+ BOOL bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const bool ignore, const std::string& function_name);
+ void resetBindings();
// Hold all the ugly stuff torn out to make LLKeyboard non-viewer-specific here
- S32 mBindingCount[MODE_COUNT];
- LLKeyBinding mBindings[MODE_COUNT][MAX_KEY_BINDINGS];
+ // We process specific keys first, then keys that should ignore mask.
+ // This way with W+ignore defined to 'forward' and with ctrl+W tied to camera,
+ // pressing undefined Shift+W will do 'forward', yet ctrl+W will do 'camera forward'
+ // With A defined to 'turn', shift+A defined to strafe, pressing Shift+W+A will do strafe+forward
+ S32 mKeyBindingCount[MODE_COUNT];
+ S32 mKeyIgnoreMaskCount[MODE_COUNT];
+ S32 mMouseBindingCount[MODE_COUNT];
+ S32 mMouseIgnoreMaskCount[MODE_COUNT];
+ LLKeyboardBinding mKeyBindings[MODE_COUNT][MAX_KEY_BINDINGS];
+ LLKeyboardBinding mKeyIgnoreMask[MODE_COUNT][MAX_KEY_BINDINGS];
+ LLMouseBinding mMouseBindings[MODE_COUNT][MAX_KEY_BINDINGS];
+ LLMouseBinding mMouseIgnoreMask[MODE_COUNT][MAX_KEY_BINDINGS];
typedef std::map<U32, U32> key_remap_t;
key_remap_t mRemapKeys[MODE_COUNT];
std::set<KEY> mKeysSkippedByUI;
BOOL mKeyHandledByUI[KEY_COUNT]; // key processed successfully by UI
+
+ // This is indentical to what llkeyboard does (mKeyRepeated, mKeyLevel, mKeyDown e t c),
+ // just instead of remembering individually as bools, we record state as enum
+ EMouseState mMouseLevel[CLICK_COUNT]; // records of key state
};
extern LLViewerKeyboard gViewerKeyboard;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 822dc20692..af8347688d 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -914,6 +914,17 @@ LLViewerWindow::Params::Params()
{}
+void LLViewerWindow::handlePieMenu(S32 x, S32 y, MASK mask)
+{
+ if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() && gAgent.isInitialized())
+ {
+ // If the current tool didn't process the click, we should show
+ // the pie menu. This can be done by passing the event to the pie
+ // menu tool.
+ LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
+ }
+}
+
BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down)
{
const char* buttonname = "";
@@ -1012,6 +1023,11 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK m
LLViewerEventRecorder::instance().logMouseEvent(std::string(buttonstatestr),std::string(buttonname));
}
+ else if (down && clicktype == CLICK_RIGHT)
+ {
+ handlePieMenu(x, y, mask);
+ r = TRUE;
+ }
return r;
}
@@ -1058,7 +1074,12 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK m
return TRUE;
}
-
+ if (down && clicktype == CLICK_RIGHT)
+ {
+ handlePieMenu(x, y, mask);
+ return TRUE;
+ }
+
// If we got this far on a down-click, it wasn't handled.
// Up-clicks, though, are always handled as far as the OS is concerned.
BOOL default_rtn = !down;
@@ -1077,7 +1098,8 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask
mMouseDownTimer.reset();
}
BOOL down = TRUE;
- return handleAnyMouseClick(window, pos, mask, CLICK_LEFT, down);
+ //handleMouse() loops back to LLViewerWindow::handleAnyMouseClick
+ return gViewerKeyboard.handleMouse(window, pos, mask, CLICK_LEFT, down);
}
BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask)
@@ -1085,7 +1107,7 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma
// try handling as a double-click first, then a single-click if that
// wasn't handled.
BOOL down = TRUE;
- if (handleAnyMouseClick(window, pos, mask, CLICK_DOUBLELEFT, down))
+ if (gViewerKeyboard.handleMouse(window, pos, mask, CLICK_DOUBLELEFT, down))
{
return TRUE;
}
@@ -1099,46 +1121,24 @@ BOOL LLViewerWindow::handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask)
mMouseDownTimer.stop();
}
BOOL down = FALSE;
- return handleAnyMouseClick(window, pos, mask, CLICK_LEFT, down);
+ return gViewerKeyboard.handleMouse(window, pos, mask, CLICK_LEFT, down);
}
-
-
BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask)
{
- S32 x = pos.mX;
- S32 y = pos.mY;
- x = ll_round((F32)x / mDisplayScale.mV[VX]);
- y = ll_round((F32)y / mDisplayScale.mV[VY]);
-
BOOL down = TRUE;
- BOOL handle = handleAnyMouseClick(window, pos, mask, CLICK_RIGHT, down);
- if (handle)
- return handle;
-
- // *HACK: this should be rolled into the composite tool logic, not
- // hardcoded at the top level.
- if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() && gAgent.isInitialized())
- {
- // If the current tool didn't process the click, we should show
- // the pie menu. This can be done by passing the event to the pie
- // menu tool.
- LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
- // show_context_menu( x, y, mask );
- }
-
- return TRUE;
+ return gViewerKeyboard.handleMouse(window, pos, mask, CLICK_RIGHT, down);
}
BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = FALSE;
- return handleAnyMouseClick(window, pos, mask, CLICK_RIGHT, down);
+ return gViewerKeyboard.handleMouse(window, pos, mask, CLICK_RIGHT, down);
}
BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = TRUE;
- handleAnyMouseClick(window, pos, mask, CLICK_MIDDLE, down);
+ gViewerKeyboard.handleMouse(window, pos, mask, CLICK_MIDDLE, down);
// Always handled as far as the OS is concerned.
return TRUE;
@@ -1293,7 +1293,7 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = FALSE;
- handleAnyMouseClick(window, pos, mask, CLICK_MIDDLE, down);
+ gViewerKeyboard.handleMouse(window, pos, mask, CLICK_MIDDLE, down);
// Always handled as far as the OS is concerned.
return TRUE;
@@ -1304,10 +1304,10 @@ BOOL LLViewerWindow::handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask
switch (button)
{
case 4:
- handleAnyMouseClick(window, pos, mask, CLICK_BUTTON4, down);
+ gViewerKeyboard.handleMouse(window, pos, mask, CLICK_BUTTON4, down);
break;
case 5:
- handleAnyMouseClick(window, pos, mask, CLICK_BUTTON5, down);
+ gViewerKeyboard.handleMouse(window, pos, mask, CLICK_BUTTON5, down);
break;
default:
break;
@@ -1474,7 +1474,8 @@ BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated)
return FALSE;
}
- return gViewerKeyboard.handleKey(key, mask, repeated);
+ // remaps, handles ignored cases and returns back to viewer window.
+ return gViewerKeyboard.handleKey(key, mask, repeated);
}
BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask)
@@ -2950,6 +2951,7 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
{
if (mask != MASK_ALT)
{
+ // remaps, handles ignored cases and returns back to viewer window.
return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
}
}
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 2e1a17596f..451a7775cf 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -175,8 +175,9 @@ public:
void initWorldUI();
void setUIVisibility(bool);
bool getUIVisibility();
+ void handlePieMenu(S32 x, S32 y, MASK mask);
- BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
+ BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
//
// LLWindowCallback interface implementation
diff --git a/indra/newview/skins/default/xui/en/floater_select_key.xml b/indra/newview/skins/default/xui/en/floater_select_key.xml
index c00b805954..32f091938e 100644
--- a/indra/newview/skins/default/xui/en/floater_select_key.xml
+++ b/indra/newview/skins/default/xui/en/floater_select_key.xml
@@ -4,7 +4,7 @@
border="false"
can_close="false"
can_minimize="false"
- height="90"
+ height="116"
layout="topleft"
name="modal container"
width="272">
@@ -31,13 +31,25 @@
Press a key to set your trigger.
Allowed input: [INPUT].
</text>
+ <check_box
+ follows="top|left"
+ height="20"
+ initial_value="false"
+ label="Ignore accelerator keys"
+ layout="topleft"
+ left="8"
+ name="ignore_masks"
+ tool_tip="Ignore Shift, Alt and Ctrl keys. Example: This allows to hold W (forward, ignores shift) and Shift+A (slide left) simultaneously and agent will both move forward and slide left."
+ top_pad="8"
+ width="160" />
+
<button
height="23"
label="Set Empty"
layout="topleft"
left="8"
name="SetEmpty"
- top_pad="8"
+ top_pad="6"
width="80" />
<button
height="23"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_controls.xml b/indra/newview/skins/default/xui/en/panel_preferences_controls.xml
index 1bfee20c81..0c652845f0 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_controls.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_controls.xml
@@ -74,7 +74,7 @@
Move To
</panel.string>
<panel.string
- name="control_sit">
+ name="toggle_sit">
Sit/Stand
</panel.string>
<panel.string
@@ -119,7 +119,7 @@
Run
</panel.string>
<panel.string
- name="control_toggle_run">
+ name="toggle_run">
Toggle Run
</panel.string>
<panel.string
@@ -207,11 +207,11 @@
Sound and Media
</panel.string>
<panel.string
- name="control_parcel">
- Play/Pause Parcel Media
+ name="toggle_pause_media">
+ Play/Pause Media
</panel.string>
<panel.string
- name="control_media">
+ name="toggle_enable_media">
Play/Stop All Media
</panel.string>
<panel.string