SL-6109 Mouse support ready

master
andreykproductengine 2019-09-25 17:54:36 +03:00 committed by Andrey Kleshchev
parent 4df05c5a89
commit c60b929fbb
17 changed files with 818 additions and 216 deletions

View File

@ -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

View File

@ -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 (!canHandle(mouse, key, mask))
if (mouse != CLICK_NONE || key != KEY_NONE)
{
mData.push_back(LLKeyData(mouse, key, mask));
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::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;
@ -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)

View File

@ -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(); };

View File

@ -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

View File

@ -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);

View File

@ -351,6 +351,7 @@ public:
static void toggleFlying();
static bool enableFlying();
BOOL canFly(); // Does this parcel allow you to fly?
static bool isSitting();
//--------------------------------------------------------------------
// Voice

View File

@ -1447,6 +1447,7 @@ bool LLAppViewer::doFrame()
{
joystick->scanJoystick();
gKeyboard->scanKeyboard();
gViewerKeyboard.scanMouse();
}
// Update state based on messages, user input, object idle.

View File

@ -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));

View File

@ -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();

View File

@ -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);
}

View File

@ -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;

View File

@ -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 == mBindingCount[mode])
mBindingCount[mode]++;
if (index == mKeyIgnoreMaskCount[mode])
mKeyIgnoreMaskCount[mode]++;
}
else
{
mKeyBindings[mode][index].mKey = key;
mKeyBindings[mode][index].mMask = mask;
mKeyBindings[mode][index].mFunction = function;
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,9 +1186,50 @@ EKeyboardMode LLViewerKeyboard::getMode()
}
}
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
{
for (S32 i = 0; i < binding_count; i++)
{
if (binding[i].mKey == key)
{
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
}//if
}//for
return false;
}
// Called from scanKeyboard.
void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) const
{
if (LLApp::isExiting())
{
@ -1011,10 +1240,6 @@ void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_lev
// 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;
@ -1023,31 +1248,122 @@ void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_lev
// 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 );
}
else if (key_up)
{
// ...key went down this frame, call function
binding[i].mFunction( KEYSTATE_UP );
}
else if (key_level)
{
// ...key held down from previous frame
// Not windows, just call the function.
binding[i].mFunction( KEYSTATE_LEVEL );
}//if
}//if
}//for
}//for
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;
}
}
}
}

View File

@ -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); // False on failure
BOOL modeFromString(const std::string& string, S32 *mode) const; // False on failure
BOOL mouseFromString(const std::string& string, EMouseClickType *mode) const;// False on failure
void scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);
void scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) const;
// 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;

View File

@ -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));
}
}

View File

@ -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

View File

@ -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"

View File

@ -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