From 04b6b6d1ba58ecf5bf70f2e2b9ae80316c4236ae Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 15 Jul 2021 18:37:02 +0300 Subject: SL-443 Keybindings: Do not error on unknown function It is likely be from newer viewer / Preparations for SL-443 deloyment. --- indra/newview/llviewerinput.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llviewerinput.cpp') diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index c0eaa88f54..f269be035e 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1070,7 +1070,7 @@ BOOL LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, cons if (!function) { - LL_ERRS() << "Can't bind key to function " << function_name << ", no function with this name found" << LL_ENDL; + LL_WARNS() << "Can't bind key to function " << function_name << ", no function with this name found" << LL_ENDL; return FALSE; } @@ -1112,7 +1112,7 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const if (!function) { - LL_ERRS() << "Can't bind key to function " << function_name << ", no function with this name found" << LL_ENDL; + LL_WARNS() << "Can't bind mouse key to function " << function_name << ", no function with this name found" << LL_ENDL; return FALSE; } -- cgit v1.3 From 0814ba33222fa86e73ca3e5351175ba4b7b545e8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 15 Jul 2021 17:34:16 +0300 Subject: SL-443 Keybindings: Support reassigment of script interaction button --- indra/newview/app_settings/key_bindings.xml | 8 +++ indra/newview/llkeyconflict.cpp | 58 ++++++++++++++-- indra/newview/llkeyconflict.h | 4 +- indra/newview/lltoolcomp.cpp | 10 ++- indra/newview/lltoolpie.cpp | 2 +- indra/newview/llviewerinput.cpp | 81 +++++++++++++++++++--- indra/newview/llviewerinput.h | 5 +- .../xui/en/control_table_contents_media.xml | 10 +++ 8 files changed, 158 insertions(+), 20 deletions(-) (limited to 'indra/newview/llviewerinput.cpp') diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml index 4f6deb1f98..ffc1b2e7cc 100644 --- a/indra/newview/app_settings/key_bindings.xml +++ b/indra/newview/app_settings/key_bindings.xml @@ -33,6 +33,8 @@ + + @@ -127,6 +129,8 @@ + + @@ -224,6 +228,8 @@ + + @@ -251,5 +257,7 @@ + + diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index d7a17b237e..58a740e16a 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -868,7 +868,7 @@ void LLKeyConflictHandler::resetKeyboardBindings() void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) { - // These controls are meant to cause conflicts when user tries to assign same control somewhere else + // These placeholds are meant to cause conflict resolution when user tries to assign same control somewhere else // also this can be used to pre-record controls that should not conflict or to assign conflict groups/masks if (load_mode == MODE_FIRST_PERSON) @@ -928,25 +928,73 @@ void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) registerTemporaryControl("spin_around_ccw_sitting"); registerTemporaryControl("spin_around_cw_sitting"); } + + + // Special case, mouse clicks passed to scripts have 'lowest' piority + // thus do not conflict, everything else has a chance before them + // also in ML they have highest priority, but only when script-grabbed, + // thus do not conflict + // (see AGENT_CONTROL_ML_LBUTTON_DOWN and CONTROL_LBUTTON_DOWN_INDEX) + LLKeyConflict *type_data = &mControlsMap[script_mouse_handler_name]; + type_data->mAssignable = true; + type_data->mConflictMask = U32_MAX - CONFLICT_LMOUSE; } -bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &conlict_mask) +bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, U32 conlict_mask) { if (conlict_mask == CONFLICT_NOTHING) { // Can't conflict return true; } + + if (data.mMouse == CLICK_LEFT + && data.mMask == MASK_NONE + && data.mKey == KEY_NONE) + { + if ((conlict_mask & CONFLICT_LMOUSE) == 0) + { + // Can't conflict + return true; + } + else + { + // simplify conflict mask + conlict_mask = CONFLICT_LMOUSE; + } + } + else + { + // simplify conflict mask + conlict_mask &= ~CONFLICT_LMOUSE; + } + std::map conflict_list; control_map_t::iterator cntrl_iter = mControlsMap.begin(); control_map_t::iterator cntrl_end = mControlsMap.end(); for (; cntrl_iter != cntrl_end; ++cntrl_iter) { + const U32 cmp_mask = cntrl_iter->second.mConflictMask; + if ((cmp_mask & conlict_mask) == 0) + { + // can't conflict + continue; + } S32 index = cntrl_iter->second.mKeyBind.findKeyData(data); - if (index >= 0 - && cntrl_iter->second.mConflictMask != CONFLICT_NOTHING - && (cntrl_iter->second.mConflictMask & conlict_mask) != 0) + if (index >= 0) { + if (cmp_mask != U32_MAX) + { + const LLKeyData cmp_data = cntrl_iter->second.mKeyBind.getKeyData(index); + if ((cmp_mask & CONFLICT_LMOUSE) == 0 + && cmp_data.mMouse == CLICK_LEFT + && cmp_data.mMask == MASK_NONE + && cmp_data.mKey == KEY_NONE) + { + // Does not conflict + continue; + } + } if (cntrl_iter->second.mAssignable) { // Potentially we can have multiple conflict flags conflicting diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h index 2926ca3aeb..e78d2fa33b 100644 --- a/indra/newview/llkeyconflict.h +++ b/indra/newview/llkeyconflict.h @@ -66,6 +66,7 @@ public: }; const U32 CONFLICT_NOTHING = 0; + const U32 CONFLICT_LMOUSE = 0x1 << 1; // at the moment this just means that key will conflict with everything that is identical const U32 CONFLICT_ANY = U32_MAX; @@ -145,6 +146,7 @@ private: // at the moment these kind of control is not savable, but takes part in conflict resolution void registerTemporaryControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask, U32 conflict_mask); + // conflict mask 0 means that any conflicts will be ignored void registerTemporaryControl(const std::string &control_name, U32 conflict_mask = 0); typedef std::map control_map_t; @@ -152,7 +154,7 @@ private: bool loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination); void generatePlaceholders(ESourceMode load_mode); //E.x. non-assignable values // returns false in case user is trying to reuse control that can't be reassigned - bool removeConflicts(const LLKeyData &data, const U32 &conlict_mask); + bool removeConflicts(const LLKeyData &data, U32 conlict_mask); // removes flags and removes temporary file, returns 'true' if file was removed bool clearUnsavedChanges(); diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp index f9c327b46e..9ac1810964 100644 --- a/indra/newview/lltoolcomp.cpp +++ b/indra/newview/lltoolcomp.cpp @@ -44,6 +44,7 @@ #include "lltoolmgr.h" #include "lltoolselectrect.h" #include "lltoolplacer.h" +#include "llviewerinput.h" #include "llviewermenu.h" #include "llviewerobject.h" #include "llviewerwindow.h" @@ -743,7 +744,7 @@ BOOL LLToolCompGun::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask) { // if the left button is grabbed, don't put up the pie menu - if (gAgent.leftButtonGrabbed()) + if (gAgent.leftButtonGrabbed() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON)) { gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN); return FALSE; @@ -760,7 +761,7 @@ BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLToolCompGun::handleDoubleClick(S32 x, S32 y, MASK mask) { // if the left button is grabbed, don't put up the pie menu - if (gAgent.leftButtonGrabbed()) + if (gAgent.leftButtonGrabbed() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON)) { gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN); return FALSE; @@ -794,7 +795,10 @@ BOOL LLToolCompGun::handleRightMouseDown(S32 x, S32 y, MASK mask) BOOL LLToolCompGun::handleMouseUp(S32 x, S32 y, MASK mask) { - gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP); + if (gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON)) + { + gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP); + } setCurrentTool( (LLTool*) mGun ); return TRUE; } diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 322d0bc727..543a93bf9b 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -746,7 +746,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) else if (!mMouseOutsideSlop && mMouseButtonDown // disable camera steering if click on land is not used for moving - && gViewerInput.isMouseBindUsed(CLICK_LEFT)) + && gViewerInput.isMouseBindUsed(CLICK_LEFT, MASK_NONE, MODE_THIRD_PERSON)) { S32 delta_x = x - mMouseDownX; S32 delta_y = y - mMouseDownY; diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index f269be035e..f163e871c3 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -61,7 +61,7 @@ const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed const LLKeyData agent_control_lbutton(CLICK_LEFT, KEY_NONE, MASK_NONE, true); struct LLKeyboardActionRegistry -: public LLRegistrySingleton, LLKeyboardActionRegistry> +: public LLRegistrySingleton, LLKeyboardActionRegistry> { LLSINGLETON_EMPTY_CTOR(LLKeyboardActionRegistry); }; @@ -836,7 +836,49 @@ bool voice_follow_key(EKeystate s) return false; } -bool agen_control_lbutton_handle(EKeystate s) +bool sript_trigger_lbutton(EKeystate s) +{ + // Check for script overriding/expecting left mouse button. + // Note that this does not pass event further and depends onto mouselook. + // Checks CONTROL_ML_LBUTTON_DOWN_INDEX for mouselook, + // CONTROL_LBUTTON_DOWN_INDEX for normal camera + if (gAgent.leftButtonGrabbed()) + { + bool mouselook = gAgentCamera.cameraMouselook(); + switch (s) + { + case KEYSTATE_DOWN: + // at the moment sript_trigger_lbutton is only intended for mouselook + // but handling other modes just in case + if (mouselook) + { + gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN); + } + else + { + gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN); + } + return true; + case KEYSTATE_UP: + if (mouselook) + { + gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP); + } + else + { + gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP); + } + return true; + default: + break; + } + } + return false; +} + +// Used by scripts, for overriding/handling left mouse button +// see mControlsTakenCount +bool agent_control_lbutton_handle(EKeystate s) { switch (s) { @@ -905,6 +947,7 @@ REGISTER_KEYBOARD_ACTION("teleport_to", teleport_to); REGISTER_KEYBOARD_ACTION("walk_to", walk_to); REGISTER_KEYBOARD_ACTION("toggle_voice", toggle_voice); REGISTER_KEYBOARD_ACTION("voice_follow_key", voice_follow_key); +REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, sript_trigger_lbutton); #undef REGISTER_KEYBOARD_ACTION LLViewerInput::LLViewerInput() @@ -1104,6 +1147,20 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const typedef boost::function function_t; function_t function = NULL; + if (mouse == CLICK_LEFT + && mask == MASK_NONE + && function_name == script_mouse_handler_name) + { + // Special case + // Left click has script overrides and by default + // is handled via agent_control_lbutton as last option + // In case of mouselook and present overrides it has highest + // priority even over UI and is handled in LLToolCompGun::handleMouseDown + // so just mark it as having default handler + mLMouseDefaultHandling[mode] = true; + return TRUE; + } + function_t* result = LLKeyboardActionRegistry::getValue(function_name); if (result) { @@ -1164,6 +1221,7 @@ void LLViewerInput::resetBindings() { mKeyBindings[i].clear(); mMouseBindings[i].clear(); + mLMouseDefaultHandling[i] = false; } } @@ -1355,13 +1413,14 @@ bool LLViewerInput::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) if (!res && agent_control_lbutton.canHandle(CLICK_NONE, key, mask)) { + // pass mouse left button press to script if (key_down && !repeat) { - res = agen_control_lbutton_handle(KEYSTATE_DOWN); + res = agent_control_lbutton_handle(KEYSTATE_DOWN); } if (key_up) { - res = agen_control_lbutton_handle(KEYSTATE_UP); + res = agent_control_lbutton_handle(KEYSTATE_UP); } } return res; @@ -1481,24 +1540,28 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const S32 mode = getMode(); MASK mask = gKeyboard->currentMask(TRUE); res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state); + // no user defined actions found or those actions can't handle the key/button, handle control if nessesary - if (!res && agent_control_lbutton.canHandle(click, KEY_NONE, mask)) + // This will pass AGENT_CONTROL_LBUTTON_DOWN to server, no idea why it doesn't do mouselook variant _ML_ + // but it was set this way forever (moved as is from LLTool::handleMouseDown) so lots of scripts probably + // rely on this. + if (!res && mLMouseDefaultHandling[mode] && agent_control_lbutton.canHandle(click, KEY_NONE, mask)) { switch (state) { case MOUSE_STATE_DOWN: - agen_control_lbutton_handle(KEYSTATE_DOWN); + agent_control_lbutton_handle(KEYSTATE_DOWN); res = true; break; case MOUSE_STATE_CLICK: // might not work best with some functions, // but some function need specific states too specifically - agen_control_lbutton_handle(KEYSTATE_DOWN); - agen_control_lbutton_handle(KEYSTATE_UP); + agent_control_lbutton_handle(KEYSTATE_DOWN); + agent_control_lbutton_handle(KEYSTATE_UP); res = true; break; case MOUSE_STATE_UP: - agen_control_lbutton_handle(KEYSTATE_UP); + agent_control_lbutton_handle(KEYSTATE_UP); res = true; break; default: diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h index 281a209896..32dd3c0e28 100644 --- a/indra/newview/llviewerinput.h +++ b/indra/newview/llviewerinput.h @@ -31,6 +31,7 @@ #include "llinitparam.h" const S32 MAX_KEY_BINDINGS = 128; // was 60 +const std::string script_mouse_handler_name = "sript_trigger_lbutton"; class LLNamedFunction { @@ -124,7 +125,8 @@ public: BOOL handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down); void scanMouse(); - bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask = MASK_NONE, const S32 mode = MODE_THIRD_PERSON); + bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode); + bool isLMouseHandlingDefault(const S32 mode) { return mLMouseDefaultHandling[mode]; } private: bool scanKey(const std::vector &binding, @@ -163,6 +165,7 @@ private: // to send what we think function wants based on collection of bools (mKeyRepeated, mKeyLevel, mKeyDown) std::vector mKeyBindings[MODE_COUNT]; std::vector mMouseBindings[MODE_COUNT]; + bool mLMouseDefaultHandling[MODE_COUNT]; // Due to having special priority typedef std::map key_remap_t; key_remap_t mRemapKeys[MODE_COUNT]; diff --git a/indra/newview/skins/default/xui/en/control_table_contents_media.xml b/indra/newview/skins/default/xui/en/control_table_contents_media.xml index ce5d3556b6..a97c45dd6f 100644 --- a/indra/newview/skins/default/xui/en/control_table_contents_media.xml +++ b/indra/newview/skins/default/xui/en/control_table_contents_media.xml @@ -73,4 +73,14 @@ name="lst_action" value="Start Gesture" /> + + + -- cgit v1.3 From 48921a62322bd4eae17d1085256693aa66041dbd Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 15 Jul 2021 20:22:53 +0300 Subject: SL-443 Keybindings: Backward compatibility --- indra/newview/app_settings/key_bindings.xml | 2 +- indra/newview/llkeyconflict.cpp | 22 ++++++++++++++++++++++ indra/newview/llkeyconflict.h | 4 ++-- indra/newview/llviewerinput.cpp | 13 ++++++++++++- indra/newview/llviewerinput.h | 2 +- 5 files changed, 38 insertions(+), 5 deletions(-) (limited to 'indra/newview/llviewerinput.cpp') diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml index ffc1b2e7cc..5c32ed9afd 100644 --- a/indra/newview/app_settings/key_bindings.xml +++ b/indra/newview/app_settings/key_bindings.xml @@ -1,5 +1,5 @@ - + diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 58a740e16a..3d3d652aa3 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -376,6 +376,22 @@ bool LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const LL_ERRS() << "Not implememted mode " << load_mode << LL_ENDL; break; } + + // verify version + if (keys.version < 1) + { + // Updating from a version that was not aware of LMouse bindings. + // Assign defaults. + // + // mDefaultsMap is always going to have correct version so + // registerControl is usable, but using 'destination' just in case. + LLKeyConflict &type_data = (*destination)[script_mouse_handler_name]; + LLKeyData data(CLICK_LEFT, KEY_NONE, MASK_NONE, true); + type_data.mKeyBind.replaceKeyData(data, 0); + + // Mark this mode for an update + mHasUnsavedChanges = true; + } } return res; } @@ -416,6 +432,12 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) } } mLoadMode = load_mode; + + if (mHasUnsavedChanges) + { + // We ended up with some settings assigned due to changes in version, resave + saveToSettings(false); + } } void LLKeyConflictHandler::saveToSettings(bool temporary) diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h index e78d2fa33b..e60d6d27b7 100644 --- a/indra/newview/llkeyconflict.h +++ b/indra/newview/llkeyconflict.h @@ -129,14 +129,14 @@ public: // resets current mode to defaults void resetToDefaults(); - bool empty() { return mControlsMap.empty(); } + bool empty() const { return mControlsMap.empty(); } void clear(); // reloads bindings from last valid user's xml or from default xml // to keyboard's handler static void resetKeyboardBindings(); - bool hasUnsavedChanges() { return mHasUnsavedChanges; } + bool hasUnsavedChanges() const { return mHasUnsavedChanges; } void setLoadMode(ESourceMode mode) { mLoadMode = mode; } ESourceMode getLoadMode() { return mLoadMode; } diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index f163e871c3..dff199d791 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1212,7 +1212,8 @@ LLViewerInput::Keys::Keys() : first_person("first_person"), third_person("third_person"), sitting("sitting"), - edit_avatar("edit_avatar") + edit_avatar("edit_avatar"), + version("version", 0) {} void LLViewerInput::resetBindings() @@ -1240,6 +1241,16 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename) binding_count += loadBindingMode(keys.third_person, MODE_THIRD_PERSON); binding_count += loadBindingMode(keys.sitting, MODE_SITTING); binding_count += loadBindingMode(keys.edit_avatar, MODE_EDIT_AVATAR); + + // verify version + if (keys.version < 1) + { + // updating from a version that was not aware of LMouse bindings + for (S32 i = 0; i < MODE_COUNT; i++) + { + mLMouseDefaultHandling[i] = true; + } + } } return binding_count; } diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h index 32dd3c0e28..5340ec5fd0 100644 --- a/indra/newview/llviewerinput.h +++ b/indra/newview/llviewerinput.h @@ -101,7 +101,7 @@ public: third_person, sitting, edit_avatar; - + Optional version; Keys(); }; -- cgit v1.3 From e7563ff13fe1e6e77a0c6de5dcf0c1b67a6d2e2c Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 15 Jul 2021 20:28:26 +0300 Subject: SL-443 Keybindings: Backward compatibility #2 --- indra/newview/app_settings/key_bindings.xml | 10 +++--- indra/newview/llkeyconflict.cpp | 37 +++++++--------------- indra/newview/llkeyconflict.h | 4 +-- indra/newview/llviewerinput.cpp | 12 +++---- indra/newview/llviewerinput.h | 9 +++--- .../xui/en/control_table_contents_media.xml | 4 +-- 6 files changed, 30 insertions(+), 46 deletions(-) (limited to 'indra/newview/llviewerinput.cpp') diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml index 5c32ed9afd..e527b7f1df 100644 --- a/indra/newview/app_settings/key_bindings.xml +++ b/indra/newview/app_settings/key_bindings.xml @@ -1,5 +1,5 @@ - + @@ -34,7 +34,7 @@ - + @@ -130,7 +130,7 @@ - + @@ -229,7 +229,7 @@ - + @@ -258,6 +258,6 @@ - + diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 3d3d652aa3..86f3e2fc37 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -378,7 +378,7 @@ bool LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const } // verify version - if (keys.version < 1) + if (keys.xml_version < 1) { // Updating from a version that was not aware of LMouse bindings. // Assign defaults. @@ -389,7 +389,8 @@ bool LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const LLKeyData data(CLICK_LEFT, KEY_NONE, MASK_NONE, true); type_data.mKeyBind.replaceKeyData(data, 0); - // Mark this mode for an update + // Mark this mode for an update, once user clicks 'OK' in preferences + // it should get saved mHasUnsavedChanges = true; } } @@ -432,12 +433,6 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) } } mLoadMode = load_mode; - - if (mHasUnsavedChanges) - { - // We ended up with some settings assigned due to changes in version, resave - saveToSettings(false); - } } void LLKeyConflictHandler::saveToSettings(bool temporary) @@ -597,6 +592,8 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) break; } + keys.xml_version.set(keybindings_xml_version, true); + if (temporary) { // write to temporary xml and use it for gViewerInput @@ -821,9 +818,9 @@ void LLKeyConflictHandler::resetToDefault(const std::string &control_name) resetToDefaultAndResolve(control_name, false); } -void LLKeyConflictHandler::resetToDefaults(ESourceMode mode) +void LLKeyConflictHandler::resetToDefaultsAndResolve() { - if (mode == MODE_SAVED_SETTINGS) + if (mLoadMode == MODE_SAVED_SETTINGS) { control_map_t::iterator iter = mControlsMap.begin(); control_map_t::iterator end = mControlsMap.end(); @@ -836,7 +833,7 @@ void LLKeyConflictHandler::resetToDefaults(ESourceMode mode) else { mControlsMap.clear(); - generatePlaceholders(mode); + generatePlaceholders(mLoadMode); mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end()); } @@ -847,7 +844,7 @@ void LLKeyConflictHandler::resetToDefaults() { if (!empty()) { - resetToDefaults(mLoadMode); + resetToDefaultsAndResolve(); } else { @@ -857,7 +854,7 @@ void LLKeyConflictHandler::resetToDefaults() // 3. We are loading 'current' only to replace it // but it is reliable and works Todo: consider optimizing. loadFromSettings(mLoadMode); - resetToDefaults(mLoadMode); + resetToDefaultsAndResolve(); } } @@ -890,7 +887,7 @@ void LLKeyConflictHandler::resetKeyboardBindings() void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) { - // These placeholds are meant to cause conflict resolution when user tries to assign same control somewhere else + // These placeholders are meant to cause conflict resolution when user tries to assign same control somewhere else // also this can be used to pre-record controls that should not conflict or to assign conflict groups/masks if (load_mode == MODE_FIRST_PERSON) @@ -1005,18 +1002,6 @@ bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, U32 conlict_ma S32 index = cntrl_iter->second.mKeyBind.findKeyData(data); if (index >= 0) { - if (cmp_mask != U32_MAX) - { - const LLKeyData cmp_data = cntrl_iter->second.mKeyBind.getKeyData(index); - if ((cmp_mask & CONFLICT_LMOUSE) == 0 - && cmp_data.mMouse == CLICK_LEFT - && cmp_data.mMask == MASK_NONE - && cmp_data.mKey == KEY_NONE) - { - // Does not conflict - continue; - } - } if (cntrl_iter->second.mAssignable) { // Potentially we can have multiple conflict flags conflicting diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h index e60d6d27b7..23c1adf1e4 100644 --- a/indra/newview/llkeyconflict.h +++ b/indra/newview/llkeyconflict.h @@ -138,11 +138,11 @@ public: bool hasUnsavedChanges() const { return mHasUnsavedChanges; } void setLoadMode(ESourceMode mode) { mLoadMode = mode; } - ESourceMode getLoadMode() { return mLoadMode; } + ESourceMode getLoadMode() const { return mLoadMode; } private: void resetToDefaultAndResolve(const std::string &control_name, bool ignore_conflicts); - void resetToDefaults(ESourceMode mode); + void resetToDefaultsAndResolve(); // at the moment these kind of control is not savable, but takes part in conflict resolution void registerTemporaryControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask, U32 conflict_mask); diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index dff199d791..1ca7d8024a 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -836,7 +836,7 @@ bool voice_follow_key(EKeystate s) return false; } -bool sript_trigger_lbutton(EKeystate s) +bool script_trigger_lbutton(EKeystate s) { // Check for script overriding/expecting left mouse button. // Note that this does not pass event further and depends onto mouselook. @@ -848,8 +848,6 @@ bool sript_trigger_lbutton(EKeystate s) switch (s) { case KEYSTATE_DOWN: - // at the moment sript_trigger_lbutton is only intended for mouselook - // but handling other modes just in case if (mouselook) { gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN); @@ -947,7 +945,7 @@ REGISTER_KEYBOARD_ACTION("teleport_to", teleport_to); REGISTER_KEYBOARD_ACTION("walk_to", walk_to); REGISTER_KEYBOARD_ACTION("toggle_voice", toggle_voice); REGISTER_KEYBOARD_ACTION("voice_follow_key", voice_follow_key); -REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, sript_trigger_lbutton); +REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, script_trigger_lbutton); #undef REGISTER_KEYBOARD_ACTION LLViewerInput::LLViewerInput() @@ -1213,7 +1211,7 @@ LLViewerInput::Keys::Keys() third_person("third_person"), sitting("sitting"), edit_avatar("edit_avatar"), - version("version", 0) + xml_version("xml_version", 0) {} void LLViewerInput::resetBindings() @@ -1243,7 +1241,7 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename) binding_count += loadBindingMode(keys.edit_avatar, MODE_EDIT_AVATAR); // verify version - if (keys.version < 1) + if (keys.xml_version < 1) { // updating from a version that was not aware of LMouse bindings for (S32 i = 0; i < MODE_COUNT; i++) @@ -1602,7 +1600,7 @@ void LLViewerInput::scanMouse() } } -bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) +bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) const { S32 size = mMouseBindings[mode].size(); for (S32 index = 0; index < size; index++) diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h index 5340ec5fd0..b0c53b23ee 100644 --- a/indra/newview/llviewerinput.h +++ b/indra/newview/llviewerinput.h @@ -31,7 +31,8 @@ #include "llinitparam.h" const S32 MAX_KEY_BINDINGS = 128; // was 60 -const std::string script_mouse_handler_name = "sript_trigger_lbutton"; +const S32 keybindings_xml_version = 1; +const std::string script_mouse_handler_name = "script_trigger_lbutton"; class LLNamedFunction { @@ -101,7 +102,7 @@ public: third_person, sitting, edit_avatar; - Optional version; + Optional xml_version; // 'xml', because 'version' appears to be reserved Keys(); }; @@ -125,8 +126,8 @@ public: BOOL handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down); void scanMouse(); - bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode); - bool isLMouseHandlingDefault(const S32 mode) { return mLMouseDefaultHandling[mode]; } + bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) const; + bool isLMouseHandlingDefault(const S32 mode) const { return mLMouseDefaultHandling[mode]; } private: bool scanKey(const std::vector &binding, diff --git a/indra/newview/skins/default/xui/en/control_table_contents_media.xml b/indra/newview/skins/default/xui/en/control_table_contents_media.xml index a97c45dd6f..43e8d730cd 100644 --- a/indra/newview/skins/default/xui/en/control_table_contents_media.xml +++ b/indra/newview/skins/default/xui/en/control_table_contents_media.xml @@ -74,8 +74,8 @@ value="Start Gesture" /> + name="script_trigger_lbutton" + value="script_trigger_lbutton"> Date: Wed, 11 Aug 2021 00:52:34 +0300 Subject: SL-15791 CONTROL_ML_LBUTTON and CONTROL_LBUTTON were triggered simultaneously --- indra/newview/llviewerinput.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'indra/newview/llviewerinput.cpp') diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 1ca7d8024a..15cf0b05db 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1550,11 +1550,16 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const MASK mask = gKeyboard->currentMask(TRUE); res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state); - // no user defined actions found or those actions can't handle the key/button, handle control if nessesary - // This will pass AGENT_CONTROL_LBUTTON_DOWN to server, no idea why it doesn't do mouselook variant _ML_ - // but it was set this way forever (moved as is from LLTool::handleMouseDown) so lots of scripts probably - // rely on this. - if (!res && mLMouseDefaultHandling[mode] && agent_control_lbutton.canHandle(click, KEY_NONE, mask)) + // No user defined actions found or those actions can't handle the key/button, handle control if nessesary + // + // Default handling for MODE_FIRST_PERSON is in LLToolCompGun::handleMouseDown, but only if + // leftButtonGrabbed() + // + // If not grabbed or not in mouse look, should pass AGENT_CONTROL_LBUTTON_DOWN to server + if (!res + && (mode != MODE_FIRST_PERSON || !gAgent.leftButtonGrabbed()) + && mLMouseDefaultHandling[mode] + && agent_control_lbutton.canHandle(click, KEY_NONE, mask)) { switch (state) { -- cgit v1.3 From 10ba971b586ff2d12f58a1ad7d5eed8264584398 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 11 Aug 2021 20:07:51 +0300 Subject: SL-15791 Double click was not causing CONTROL_LBUTTON_DOWN --- indra/newview/llviewerinput.cpp | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) (limited to 'indra/newview/llviewerinput.cpp') diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 15cf0b05db..976d7d9c6b 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -58,8 +58,6 @@ const F32 NUDGE_TIME = 0.25f; // in seconds const S32 NUDGE_FRAMES = 2; const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed -const LLKeyData agent_control_lbutton(CLICK_LEFT, KEY_NONE, MASK_NONE, true); - struct LLKeyboardActionRegistry : public LLRegistrySingleton, LLKeyboardActionRegistry> { @@ -1420,18 +1418,6 @@ bool LLViewerInput::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) bool res = scanKey(mKeyBindings[mode], mKeyBindings[mode].size(), key, mask, key_down, key_up, key_level, repeat); - if (!res && agent_control_lbutton.canHandle(CLICK_NONE, key, mask)) - { - // pass mouse left button press to script - if (key_down && !repeat) - { - res = agent_control_lbutton_handle(KEYSTATE_DOWN); - } - if (key_up) - { - res = agent_control_lbutton_handle(KEYSTATE_UP); - } - } return res; } @@ -1550,16 +1536,18 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const MASK mask = gKeyboard->currentMask(TRUE); res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state); - // No user defined actions found or those actions can't handle the key/button, handle control if nessesary + // No user defined actions found or those actions can't handle the key/button, + // so handle CONTROL_LBUTTON if nessesary. // - // Default handling for MODE_FIRST_PERSON is in LLToolCompGun::handleMouseDown, but only if - // leftButtonGrabbed() - // - // If not grabbed or not in mouse look, should pass AGENT_CONTROL_LBUTTON_DOWN to server + // Default handling for MODE_FIRST_PERSON is in LLToolCompGun::handleMouseDown, + // and sends AGENT_CONTROL_ML_LBUTTON_DOWN, but it only applies if ML controls + // are leftButtonGrabbed(), send a normal click otherwise. + if (!res - && (mode != MODE_FIRST_PERSON || !gAgent.leftButtonGrabbed()) && mLMouseDefaultHandling[mode] - && agent_control_lbutton.canHandle(click, KEY_NONE, mask)) + && (mode != MODE_FIRST_PERSON || !gAgent.leftButtonGrabbed()) + && (click == CLICK_LEFT || click == CLICK_DOUBLELEFT) + ) { switch (state) { -- cgit v1.3 From 6d05c44d712991815e991ba2c61ddc7370b66ead Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 11 Aug 2021 21:29:59 +0300 Subject: SL-15791 Assigned walk_to or teleport_to sometimes prevents controls from triggering --- indra/newview/llviewerinput.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'indra/newview/llviewerinput.cpp') diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 976d7d9c6b..bb8617735f 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -800,13 +800,20 @@ bool toggle_enable_media(EKeystate s) bool walk_to(EKeystate s) { - if (KEYSTATE_DOWN != s) return true; + if (KEYSTATE_DOWN != s) + { + // teleport/walk is usually on mouseclick, mouseclick needs + // to let AGENT_CONTROL_LBUTTON_UP happen if teleport didn't, + // so return false, but if it causes issues, do some kind of + // "return !has_teleported" + return false; + } return LLToolPie::getInstance()->walkToClickedLocation(); } bool teleport_to(EKeystate s) { - if (KEYSTATE_DOWN != s) return true; + if (KEYSTATE_DOWN != s) return false; return LLToolPie::getInstance()->teleportToClickedLocation(); } -- cgit v1.3 From 0dd4577013a48289f84dcb3cc8b673fb1f733b7d Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Fri, 19 Nov 2021 05:53:20 +0200 Subject: DRTVWR-540 Post-merge build fix --- indra/newview/llviewerinput.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llviewerinput.cpp') diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index c900d0f6bf..e76b8c0fcf 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1255,7 +1255,7 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const return TRUE; } - function_t* result = LLKeyboardActionRegistry::getValue(function_name); + LLKeybindFunctionData* result = LLKeyboardActionRegistry::getValue(function_name); if (result) { function = result->mFunction; @@ -1666,7 +1666,7 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const bool res = false; S32 mode = getMode(); MASK mask = gKeyboard->currentMask(TRUE); - res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state); + res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state, false); // No user defined actions found or those actions can't handle the key/button, // so handle CONTROL_LBUTTON if nessesary. -- cgit v1.3 From 93262cf286baba47d271ee0aa700c6c40afaa132 Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Fri, 19 Nov 2021 13:00:36 +0200 Subject: DRTVWR-540 Merge follow up fix --- indra/newview/llviewerinput.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llviewerinput.cpp') diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index e76b8c0fcf..1a08b1a56c 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -967,8 +967,8 @@ REGISTER_KEYBOARD_ACTION("toggle_pause_media", toggle_pause_media); REGISTER_KEYBOARD_ACTION("toggle_enable_media", toggle_enable_media); REGISTER_KEYBOARD_ACTION("teleport_to", teleport_to); REGISTER_KEYBOARD_ACTION("walk_to", walk_to); -REGISTER_KEYBOARD_ACTION("toggle_voice", toggle_voice); -REGISTER_KEYBOARD_ACTION("voice_follow_key", voice_follow_key); +REGISTER_KEYBOARD_GLOBAL_ACTION("toggle_voice", toggle_voice); +REGISTER_KEYBOARD_GLOBAL_ACTION("voice_follow_key", voice_follow_key); REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, script_trigger_lbutton); #undef REGISTER_KEYBOARD_ACTION -- cgit v1.3 From fc90fee5087c91bb8c4c93b5e9508706e46bd409 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 4 Mar 2022 22:24:59 +0200 Subject: SL-16976 SL-443 Keybindings: Backward compatibility #3 --- indra/newview/llkeyconflict.cpp | 17 -------------- indra/newview/llviewerinput.cpp | 49 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 17 deletions(-) (limited to 'indra/newview/llviewerinput.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 4c58c9e68c..d3ba18525b 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -376,23 +376,6 @@ bool LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const LL_ERRS() << "Not implememted mode " << load_mode << LL_ENDL; break; } - - // verify version - if (keys.xml_version < 1) - { - // Updating from a version that was not aware of LMouse bindings. - // Assign defaults. - // - // mDefaultsMap is always going to have correct version so - // registerControl is usable, but using 'destination' just in case. - LLKeyConflict &type_data = (*destination)[script_mouse_handler_name]; - LLKeyData data(CLICK_LEFT, KEY_NONE, MASK_NONE, true); - type_data.mKeyBind.replaceKeyData(data, 0); - - // Mark this mode for an update, once user clicks 'OK' in preferences - // it should get saved - mHasUnsavedChanges = true; - } } return res; } diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 1a08b1a56c..43b9cd90bd 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1371,6 +1371,55 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename) { mLMouseDefaultHandling[i] = true; } + + // fix missing values + KeyBinding mouse_binding; + mouse_binding.key = ""; + mouse_binding.mask = "NONE"; + mouse_binding.mouse = "LMB"; + mouse_binding.command = script_mouse_handler_name; + + if (keys.third_person.isProvided()) + { + keys.third_person.bindings.add(mouse_binding); + } + + if (keys.first_person.isProvided()) + { + keys.first_person.bindings.add(mouse_binding); + } + + if (keys.sitting.isProvided()) + { + keys.sitting.bindings.add(mouse_binding); + } + + if (keys.edit_avatar.isProvided()) + { + keys.edit_avatar.bindings.add(mouse_binding); + } + + // fix version + keys.xml_version.set(keybindings_xml_version, true); + + // Write the resulting XML to file + LLXMLNodePtr output_node = new LLXMLNode("keys", false); + LLXUIParser write_parser; + write_parser.writeXUI(output_node, keys); + + if (!output_node->isNull()) + { + // file in app_settings is supposed to be up to date + // this is only for the file from user_settings + LL_INFOS("ViewerInput") << "Updating file " << filename << " to a newer version" << LL_ENDL; + LLFILE *fp = LLFile::fopen(filename, "w"); + if (fp != NULL) + { + LLXMLNode::writeHeaderToFile(fp); + output_node->writeToFile(fp); + fclose(fp); + } + } } } return binding_count; -- cgit v1.3