diff options
Diffstat (limited to 'indra/newview/llviewerkeyboard.cpp')
-rw-r--r-- | indra/newview/llviewerkeyboard.cpp | 424 |
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; + } + } + } } |