summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerkeyboard.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewerkeyboard.cpp')
-rw-r--r--indra/newview/llviewerkeyboard.cpp424
1 files changed, 370 insertions, 54 deletions
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;
+ }
+ }
+ }
}