From 4df05c5a8995158922c7b7aacfef442ac8ae6fdd Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Tue, 17 Sep 2019 21:36:59 +0300 Subject: SL-6109 Keyaboard support ready --- indra/newview/llkeyconflict.cpp | 789 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 789 insertions(+) create mode 100644 indra/newview/llkeyconflict.cpp (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp new file mode 100644 index 0000000000..0f0129bf68 --- /dev/null +++ b/indra/newview/llkeyconflict.cpp @@ -0,0 +1,789 @@ +/** + * @file llkeyconflict.cpp + * @brief + * + * $LicenseInfo:firstyear=2019&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2019, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +/* + * App-wide preferences. Note that these are not per-user, + * because we need to load many preferences before we have + * a login name. + */ + +#include "llviewerprecompiledheaders.h" + +#include "llkeyconflict.h" + +#include "llinitparam.h" +#include "llkeyboard.h" +#include "llviewercontrol.h" +#include "llviewerkeyboard.h" +#include "llxuiparser.h" +//#include "llstring.h" + +static const std::string typetostring[LLKeyConflictHandler::CONTROL_NUM_INDICES] = { + "control_view_actions", + "control_about", + "control_orbit", + "control_pan", + "control_world_map", + "control_zoom", + "control_interactions", + "control_build", + //"control_drag", + "control_edit", + //"control_menu", + "control_open", + "control_touch", + "control_wear", + "control_movements", + "control_moveto", + "control_sit", + "control_teleportto", + "push_forward", + "push_backward", + "turn_left", + "turn_right", + "slide_left", + "slide_right", + "jump", + "push_down", + //"control_run", + "control_toggle_run", + "toggle_fly", + "stop_moving", + "control_camera", + "look_up", + "look_down", + "move_forward", + "move_backward", + "move_forward_fast", + "move_backward_fast", + "move_forward_sitting", + "move_backward_sitting", + "spin_over", + "spin_under", + "spin_over_sitting", + "spin_under_sitting", + "pan_up", + "pan_down", + "pan_left", + "pan_right", + "pan_in", + "pan_out", + "spin_around_ccw", + "spin_around_cw", + "spin_around_ccw_sitting", + "spin_around_cw_sitting", + "control_edit_title", + "edit_avatar_spin_ccw", + "edit_avatar_spin_cw", + "edit_avatar_spin_over", + "edit_avatar_spin_under", + "edit_avatar_move_forward", + "edit_avatar_move_backward", + "control_mediacontent", + "control_parcel", + "control_media", + "control_voice", + "control_toggle_voice", + "start_chat", + "start_gesture", + "control_reserved", + "control_delete", + "control_menu", + "control_reserved_select", + "control_shift_select", + "control_cntrl_select" +}; + +// note, a solution is needed that will keep this up to date with llviewerkeyboard +typedef std::map control_enum_t; +static const control_enum_t command_to_key = +{ + { "jump", LLKeyConflictHandler::CONTROL_JUMP }, + { "push_down", LLKeyConflictHandler::CONTROL_DOWN }, + { "push_forward", LLKeyConflictHandler::CONTROL_FORWARD }, + { "push_backward", LLKeyConflictHandler::CONTROL_BACKWARD }, + { "look_up", LLKeyConflictHandler::CONTROL_LOOK_UP }, + { "look_down", LLKeyConflictHandler::CONTROL_LOOK_DOWN }, + { "toggle_fly", LLKeyConflictHandler::CONTROL_TOGGLE_FLY }, + { "turn_left", LLKeyConflictHandler::CONTROL_LEFT }, + { "turn_right", LLKeyConflictHandler::CONTROL_RIGHT }, + { "slide_left", LLKeyConflictHandler::CONTROL_LSTRAFE }, + { "slide_right", LLKeyConflictHandler::CONTROL_RSTRAFE }, + { "spin_around_ccw", LLKeyConflictHandler::CONTROL_CAMERA_SPIN_CCW }, // todo, no idea what these spins are + { "spin_around_cw", LLKeyConflictHandler::CONTROL_CAMERA_SPIN_CW }, + { "spin_around_ccw_sitting", LLKeyConflictHandler::CONTROL_CAMERA_SPIN_CCW_SITTING }, + { "spin_around_cw_sitting", LLKeyConflictHandler::CONTROL_CAMERA_SPIN_CCW_SITTING }, + { "spin_over", LLKeyConflictHandler::CONTROL_CAMERA_SOVER }, + { "spin_under", LLKeyConflictHandler::CONTROL_CAMERA_SUNDER }, + { "spin_over_sitting", LLKeyConflictHandler::CONTROL_CAMERA_SOVER_SITTING }, + { "spin_under_sitting", LLKeyConflictHandler::CONTROL_CAMERA_SUNDER_SITTING }, + { "move_forward", LLKeyConflictHandler::CONTROL_CAMERA_FORWARD }, + { "move_backward", LLKeyConflictHandler::CONTROL_CAMERA_BACKWARD }, + { "move_forward_sitting", LLKeyConflictHandler::CONTROL_CAMERA_FSITTING }, + { "move_backward_sitting", LLKeyConflictHandler::CONTROL_CAMERA_BSITTING }, + { "pan_up", LLKeyConflictHandler::CONTROL_CAMERA_PANUP }, + { "pan_down", LLKeyConflictHandler::CONTROL_CAMERA_PANDOWN }, + { "pan_left", LLKeyConflictHandler::CONTROL_CAMERA_PANLEFT }, + { "pan_right", LLKeyConflictHandler::CONTROL_CAMERA_PANRIGHT }, + { "pan_in", LLKeyConflictHandler::CONTROL_CAMERA_PANIN }, + { "pan_out", LLKeyConflictHandler::CONTROL_CAMERA_PANOUT }, + { "move_forward_fast", LLKeyConflictHandler::CONTROL_CAMERA_FFORWARD }, + { "move_backward_fast", LLKeyConflictHandler::CONTROL_CAMERA_FBACKWARD }, + { "edit_avatar_spin_ccw", LLKeyConflictHandler::CONTROL_EDIT_AV_SPIN_CCW }, + { "edit_avatar_spin_cw", LLKeyConflictHandler::CONTROL_EDIT_AV_SPIN_CW }, + { "edit_avatar_spin_over", LLKeyConflictHandler::CONTROL_EDIT_AV_SPIN_OVER }, + { "edit_avatar_spin_under", LLKeyConflictHandler::CONTROL_EDIT_AV_SPIN_UNDER }, + { "edit_avatar_move_forward", LLKeyConflictHandler::CONTROL_EDIT_AV_MV_FORWARD }, + { "edit_avatar_move_backward", LLKeyConflictHandler::CONTROL_EDIT_AV_MV_BACKWARD }, + { "stop_moving", LLKeyConflictHandler::CONTROL_STOP }, + { "start_chat", LLKeyConflictHandler::CONTROL_START_CHAT }, + { "start_gesture", LLKeyConflictHandler::CONTROL_START_GESTURE }, +}; + + +// LLKeyboard::stringFromMask is meant for UI and is OS dependent, +// so this class uses it's own version +std::string string_from_mask(MASK mask) +{ + std::string res; + if ((mask & MASK_CONTROL) != 0) + { + res = "CTL"; + } + if ((mask & MASK_ALT) != 0) + { + if (!res.empty()) res += "_"; + res += "ALT"; + } + if ((mask & MASK_SHIFT) != 0) + { + if (!res.empty()) res += "_"; + res += "SHIFT"; + } + + if (mask == MASK_NONE) + { + res = "NONE"; + } + return res; +} + +// LLKeyConflictHandler + +LLKeyConflictHandler::LLKeyConflictHandler() + : mHasUnsavedChanges(false) +{ + // todo: assign conflic priorities + // todo: load from keys.xml? + + // Thise controls are meant to cause conflicts when user tries to assign same control somewhere else + /*registerTemporaryControl(CONTROL_RESERVED_MENU, CLICK_RIGHT, KEY_NONE, MASK_NONE, 0); + registerTemporaryControl(CONTROL_SHIFT_SELECT, CLICK_LEFT, KEY_NONE, MASK_SHIFT, 0); + registerTemporaryControl(CONTROL_CNTRL_SELECT, CLICK_LEFT, KEY_NONE, MASK_CONTROL, 0); + registerTemporaryControl(CONTROL_DELETE, CLICK_NONE, KEY_DELETE, MASK_NONE, 0); + + loadFromSettings();*/ +} + +LLKeyConflictHandler::LLKeyConflictHandler(EModes mode) + : mHasUnsavedChanges(false), + mLoadedMode(mode) +{ + loadFromSettings(mode); +} + +bool LLKeyConflictHandler::canHandleControl(LLKeyConflictHandler::EControlTypes control_type, EMouseClickType mouse_ind, KEY key, MASK mask) +{ + return mControlsMap[control_type].canHandle(mouse_ind, key, mask); +} + +bool LLKeyConflictHandler::canHandleKey(EControlTypes control_type, KEY key, MASK mask) +{ + return canHandleControl(control_type, CLICK_NONE, key, mask); +} + +bool LLKeyConflictHandler::canHandleMouse(LLKeyConflictHandler::EControlTypes control_type, EMouseClickType mouse_ind, MASK mask) +{ + return canHandleControl(control_type, mouse_ind, KEY_NONE, mask); +} + +bool LLKeyConflictHandler::canHandleMouse(EControlTypes control_type, S32 mouse_ind, MASK mask) +{ + return canHandleControl(control_type, (EMouseClickType)mouse_ind, KEY_NONE, mask); +} + +bool LLKeyConflictHandler::canAssignControl(EControlTypes control_type) +{ + std::map::iterator iter = mControlsMap.find(control_type); + if (iter != mControlsMap.end()) + { + return iter->second.mAssignable; + } + return false; +} + +void LLKeyConflictHandler::registerControl(EControlTypes control_type, U32 index, EMouseClickType mouse, KEY key, MASK 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); + + mHasUnsavedChanges = true; +} + +LLKeyData LLKeyConflictHandler::getControl(EControlTypes control_type, U32 index) +{ + return mControlsMap[control_type].getKeyData(index); +} + +// static +std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata) +{ + std::string result; + + if (keydata.mMask != MASK_NONE && keydata.mKey != KEY_NONE) + { + result = LLKeyboard::stringFromAccelerator(keydata.mMask, keydata.mKey); + } + else if (keydata.mKey != KEY_NONE) + { + result = LLKeyboard::stringFromKey(keydata.mKey); + } + else if (keydata.mMask != MASK_NONE) + { + LL_ERRS() << "Masks binding without keys is not supported yet" << LL_ENDL; + } + + #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 + + 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; +} + +// static +std::string LLKeyConflictHandler::getControlName(EControlTypes control_type) +{ + return typetostring[control_type]; +} + +std::string LLKeyConflictHandler::getControlString(EControlTypes control_type, U32 index) +{ + return getStringFromKeyData(mControlsMap[control_type].getKeyData(index)); +} + +void LLKeyConflictHandler::loadFromSettings(const LLViewerKeyboard::KeyMode& keymode, control_map_t *destination) +{ + for (LLInitParam::ParamIterator::const_iterator it = keymode.bindings.begin(), + end_it = keymode.bindings.end(); + it != end_it; + ++it) + { + KEY key; + MASK mask; + if (it->key.getValue().empty()) + { + key = KEY_NONE; + } + else + { + LLKeyboard::keyFromString(it->key, &key); + } + LLKeyboard::maskFromString(it->mask, &mask); + std::string command_name = it->command; + // it->command + // It might be better to have map, but at the moment enum is easier to iterate through. + // Besides keys.xml might not contain all commands + control_enum_t::const_iterator iter = command_to_key.find(command_name); + if (iter != command_to_key.end()) + { + 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); + } + } +} + +void LLKeyConflictHandler::loadFromSettings(const EModes &load_mode, const std::string &filename, control_map_t *destination) +{ + if (filename.empty()) + { + return; + } + + LLViewerKeyboard::Keys keys; + LLSimpleXUIParser parser; + + if (parser.readXUI(filename, keys) + && keys.validateBlock()) + { + switch (load_mode) + { + case MODE_FIRST_PERSON: + if (keys.first_person.isProvided()) + { + loadFromSettings(keys.first_person, destination); + } + break; + case MODE_THIRD_PERSON: + if (keys.third_person.isProvided()) + { + loadFromSettings(keys.third_person, destination); + } + break; + case MODE_EDIT: + if (keys.edit.isProvided()) + { + loadFromSettings(keys.edit, destination); + } + break; + case MODE_EDIT_AVATAR: + if (keys.edit_avatar.isProvided()) + { + loadFromSettings(keys.edit_avatar, destination); + } + break; + case MODE_SITTING: + if (keys.sitting.isProvided()) + { + loadFromSettings(keys.sitting, destination); + } + break; + default: + break; + } + } +} + +void LLKeyConflictHandler::loadFromSettings(EModes load_mode) +{ + mControlsMap.clear(); + mDefaultsMap.clear(); + if (load_mode == MODE_GENERAL) + { + for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) + { + EControlTypes type = (EControlTypes)i; + switch (type) + { + case LLKeyConflictHandler::CONTROL_VIEW_ACTIONS: + case LLKeyConflictHandler::CONTROL_INTERACTIONS: + case LLKeyConflictHandler::CONTROL_MOVEMENTS: + case LLKeyConflictHandler::CONTROL_MEDIACONTENT: + case LLKeyConflictHandler::CONTROL_CAMERA: + case LLKeyConflictHandler::CONTROL_EDIT_TITLE: + case LLKeyConflictHandler::CONTROL_RESERVED: + // ignore 'headers', they are for representation and organization purposes + break; + default: + { + std::string name = getControlName(type); + LLControlVariablePtr var = gSavedSettings.getControl(name); + if (var) + { + LLKeyBind bind(var->getValue()); + LLKeyConflict key(bind, true, 0); + mControlsMap[type] = key; + } + break; + } + } + } + } + else + { + // load defaults + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "keys.xml"); + loadFromSettings(load_mode, filename, &mDefaultsMap); + + // load user's + filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "keys.xml"); + if (gDirUtilp->fileExists(filename)) + { + loadFromSettings(load_mode, filename, &mControlsMap); + } + else + { + mControlsMap = mDefaultsMap; + } + } + mLoadedMode = load_mode; + + generatePlaceholders(); +} + +void LLKeyConflictHandler::saveToSettings() +{ + if (mControlsMap.empty()) + { + return; + } + + if (mLoadedMode == MODE_GENERAL) + { + for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) + { + EControlTypes type = (EControlTypes)i; + switch (type) + { + case LLKeyConflictHandler::CONTROL_VIEW_ACTIONS: + case LLKeyConflictHandler::CONTROL_INTERACTIONS: + case LLKeyConflictHandler::CONTROL_MOVEMENTS: + case LLKeyConflictHandler::CONTROL_MEDIACONTENT: + case LLKeyConflictHandler::CONTROL_CAMERA: + case LLKeyConflictHandler::CONTROL_EDIT_TITLE: + case LLKeyConflictHandler::CONTROL_RESERVED: + // ignore 'headers', they are for representation and organization purposes + break; + default: + { + if (mControlsMap[type].mAssignable) + { + std::string name = getControlName(type); + if (gSavedSettings.controlExists(name)) + { + gSavedSettings.setLLSD(name, mControlsMap[type].mKeyBind.asLLSD()); + } + else if (!mControlsMap[type].mKeyBind.empty()) + { + // shouldn't happen user side since all settings are supposed to be declared already, but handy when creating new ones + // (just don't forget to change comment and to copy them from user's folder) + LL_INFOS() << "Creating new keybinding " << name << LL_ENDL; + gSavedSettings.declareLLSD(name, mControlsMap[type].mKeyBind.asLLSD(), "comment", LLControlVariable::PERSIST_ALWAYS); + } + } + break; + } + } + } + } + else + { + // loaded full copy of original file + std::string filename = gDirUtilp->findFile("keys.xml", + gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""), + gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + + LLViewerKeyboard::Keys keys; + LLSimpleXUIParser parser; + + if (parser.readXUI(filename, keys) + && keys.validateBlock()) + { + // replace category we edited + + // todo: fix this + // workaround to avoid doing own param container + LLViewerKeyboard::KeyMode mode; + LLViewerKeyboard::KeyBinding binding; + + control_map_t::iterator iter = mControlsMap.begin(); + control_map_t::iterator end = mControlsMap.end(); + for (; iter != end; ++iter) + { + U32 size = iter->second.mKeyBind.getDataCount(); + for (U32 i = 0; i < size; ++i) + { + // Still write empty keys to make sure we will maintain UI position + LLKeyData data = iter->second.mKeyBind.getKeyData(i); + if (data.mKey == KEY_NONE) + { + binding.key = ""; + } + else + { + // Note: this is UI string, we might want to hardcode our own for 'fixed' use in keys.xml + binding.key = LLKeyboard::stringFromKey(data.mKey); + } + binding.mask = string_from_mask(data.mMask); + binding.command = getControlName(iter->first); + mode.bindings.add(binding); + } + } + + switch (mLoadedMode) + { + case MODE_FIRST_PERSON: + if (keys.first_person.isProvided()) + { + keys.first_person.bindings.set(mode.bindings, true); + } + break; + case MODE_THIRD_PERSON: + if (keys.third_person.isProvided()) + { + keys.third_person.bindings.set(mode.bindings, true); + } + break; + case MODE_EDIT: + if (keys.edit.isProvided()) + { + keys.edit.bindings.set(mode.bindings, true); + } + break; + case MODE_EDIT_AVATAR: + if (keys.edit_avatar.isProvided()) + { + keys.edit_avatar.bindings.set(mode.bindings, true); + } + break; + case MODE_SITTING: + if (keys.sitting.isProvided()) + { + keys.sitting.bindings.set(mode.bindings, true); + } + break; + default: + break; + } + + // write back to user's xml; + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "keys.xml"); + + LLXMLNodePtr output_node = new LLXMLNode("keys", false); + LLXUIParser parser; + parser.writeXUI(output_node, keys); + + // Write the resulting XML to file + if (!output_node->isNull()) + { + LLFILE *fp = LLFile::fopen(filename, "w"); + if (fp != NULL) + { + LLXMLNode::writeHeaderToFile(fp); + output_node->writeToFile(fp); + fclose(fp); + } + } + // Now force a rebind for keyboard + if (gDirUtilp->fileExists(filename)) + { + gViewerKeyboard.loadBindingsXML(filename); + } + } + } + mHasUnsavedChanges = false; +} + +LLKeyData LLKeyConflictHandler::getDefaultControl(EControlTypes control_type, U32 index) +{ + if (mLoadedMode == MODE_GENERAL) + { + std::string name = getControlName(control_type); + LLControlVariablePtr var = gSavedSettings.getControl(name); + if (var) + { + return LLKeyBind(var->getDefault()).getKeyData(index); + } + return LLKeyData(); + } + else + { + control_map_t::iterator iter = mDefaultsMap.find(control_type); + if (iter != mDefaultsMap.end()) + { + return iter->second.mKeyBind.getKeyData(index); + } + return LLKeyData(); + } +} + +void LLKeyConflictHandler::resetToDefault(EControlTypes control_type, U32 index) +{ + LLKeyData data = getDefaultControl(control_type, index); + mControlsMap[control_type].setKeyData(data, index); +} + +void LLKeyConflictHandler::resetToDefault(EControlTypes control_type) +{ + if (mLoadedMode == MODE_GENERAL) + { + std::string name = getControlName(control_type); + LLControlVariablePtr var = gSavedSettings.getControl(name); + if (var) + { + mControlsMap[control_type].mKeyBind = LLKeyBind(var->getDefault()); + } + else + { + mControlsMap[control_type].mKeyBind.clear(); + } + } + else + { + control_map_t::iterator iter = mDefaultsMap.find(control_type); + if (iter != mDefaultsMap.end()) + { + mControlsMap[control_type].mKeyBind = iter->second.mKeyBind; + } + else + { + mControlsMap[control_type].mKeyBind.clear(); + } + } +} + +void LLKeyConflictHandler::resetToDefaults(EModes mode) +{ + if (mode == MODE_GENERAL) + { + for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) + { + EControlTypes type = (EControlTypes)i; + switch (type) + { + case LLKeyConflictHandler::CONTROL_VIEW_ACTIONS: + case LLKeyConflictHandler::CONTROL_INTERACTIONS: + case LLKeyConflictHandler::CONTROL_MOVEMENTS: + case LLKeyConflictHandler::CONTROL_MEDIACONTENT: + case LLKeyConflictHandler::CONTROL_CAMERA: + case LLKeyConflictHandler::CONTROL_EDIT_TITLE: + case LLKeyConflictHandler::CONTROL_RESERVED: + // ignore 'headers', they are for representation and organization purposes + break; + default: + { + resetToDefault(type); + break; + } + } + } + } + else + { + mControlsMap.clear(); + mControlsMap = mDefaultsMap; + generatePlaceholders(); + } + + mHasUnsavedChanges = true; +} + +void LLKeyConflictHandler::resetToDefaults() +{ + if (!empty()) + { + resetToDefaults(mLoadedMode); + } +} + +void LLKeyConflictHandler::resetAllToDefaults() +{ + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "keys.xml"); + if (gDirUtilp->fileExists(filename)) + { + LLFile::remove(filename); + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "keys.xml"); + gViewerKeyboard.loadBindingsXML(filename); + } + + for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) + { + EControlTypes type = (EControlTypes)i; + switch (type) + { + case LLKeyConflictHandler::CONTROL_VIEW_ACTIONS: + case LLKeyConflictHandler::CONTROL_INTERACTIONS: + case LLKeyConflictHandler::CONTROL_MOVEMENTS: + case LLKeyConflictHandler::CONTROL_MEDIACONTENT: + case LLKeyConflictHandler::CONTROL_RESERVED: + // ignore 'headers', they are for representation and organization purposes + break; + default: + { + resetToDefault(type); + break; + } + } + } + mHasUnsavedChanges = false; +} + +void LLKeyConflictHandler::clear() +{ + mHasUnsavedChanges = false; + mControlsMap.clear(); + mDefaultsMap.clear(); +} + +void LLKeyConflictHandler::resetKeyboardBindings() +{ + std::string filename = gDirUtilp->findFile("keys.xml", + gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""), + gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + + gViewerKeyboard.loadBindingsXML(filename); +} + +void LLKeyConflictHandler::generatePlaceholders() +{ + +} + +void LLKeyConflictHandler::registerTemporaryControl(EControlTypes control_type, EMouseClickType mouse, KEY key, MASK mask, U32 conflict_mask) +{ + LLKeyConflict *type_data = &mControlsMap[control_type]; + type_data->mAssignable = false; + type_data->mConflictMask = conflict_mask; + type_data->mKeyBind.addKeyData(mouse, key, mask); +} + -- cgit v1.2.3 From c60b929fbb615f8d73f7bf42849b5628bf0f8f7a Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 25 Sep 2019 17:54:36 +0300 Subject: SL-6109 Mouse support ready --- indra/newview/llkeyconflict.cpp | 131 +++++++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 50 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 0f0129bf68..be0b8fd4ca 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -58,7 +58,6 @@ static const std::string typetostring[LLKeyConflictHandler::CONTROL_NUM_INDICES] "control_wear", "control_movements", "control_moveto", - "control_sit", "control_teleportto", "push_forward", "push_backward", @@ -69,8 +68,9 @@ static const std::string typetostring[LLKeyConflictHandler::CONTROL_NUM_INDICES] "jump", "push_down", //"control_run", - "control_toggle_run", + "toggle_run", "toggle_fly", + "toggle_sit", "stop_moving", "control_camera", "look_up", @@ -103,8 +103,8 @@ static const std::string typetostring[LLKeyConflictHandler::CONTROL_NUM_INDICES] "edit_avatar_move_forward", "edit_avatar_move_backward", "control_mediacontent", - "control_parcel", - "control_media", + "toggle_pause_media", + "toggle_enable_media", "control_voice", "control_toggle_voice", "start_chat", @@ -161,6 +161,10 @@ static const control_enum_t command_to_key = { "stop_moving", LLKeyConflictHandler::CONTROL_STOP }, { "start_chat", LLKeyConflictHandler::CONTROL_START_CHAT }, { "start_gesture", LLKeyConflictHandler::CONTROL_START_GESTURE }, + { "toggle_run", LLKeyConflictHandler::CONTROL_TOGGLE_RUN }, + { "toggle_sit", LLKeyConflictHandler::CONTROL_SIT }, + { "toggle_parcel_media", LLKeyConflictHandler::CONTROL_PAUSE_MEDIA }, + { "toggle_enable_media", LLKeyConflictHandler::CONTROL_ENABLE_MEDIA }, }; @@ -191,6 +195,60 @@ std::string string_from_mask(MASK mask) return res; } +std::string string_from_mouse(EMouseClickType click) +{ + std::string res; + switch (click) + { + case CLICK_LEFT: + res = "LMB"; + break; + case CLICK_MIDDLE: + res = "MMB"; + break; + case CLICK_RIGHT: + res = "RMB"; + break; + case CLICK_BUTTON4: + res = "MB4"; + break; + case CLICK_BUTTON5: + res = "MB5"; + break; + case CLICK_DOUBLELEFT: + res = "Double LMB"; + break; + default: + break; + } + return res; +} + +EMouseClickType mouse_from_string(const std::string& input) +{ + if (input == "LMB") + { + return CLICK_LEFT; + } + if (input == "MMB") + { + return CLICK_MIDDLE; + } + if (input == "RMB") + { + return CLICK_RIGHT; + } + if (input == "MB4") + { + return CLICK_BUTTON4; + } + if (input == "MB5") + { + return CLICK_BUTTON5; + } + return CLICK_NONE; +} + // LLKeyConflictHandler LLKeyConflictHandler::LLKeyConflictHandler() @@ -245,14 +303,14 @@ bool LLKeyConflictHandler::canAssignControl(EControlTypes control_type) return false; } -void LLKeyConflictHandler::registerControl(EControlTypes control_type, U32 index, EMouseClickType mouse, KEY key, MASK mask) +void LLKeyConflictHandler::registerControl(EControlTypes control_type, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask) { LLKeyConflict &type_data = mControlsMap[control_type]; if (!type_data.mAssignable) { LL_ERRS() << "Error in code, user or system should not be able to change certain controls" << LL_ENDL; } - type_data.mKeyBind.replaceKeyData(mouse, key, mask, index); + type_data.mKeyBind.replaceKeyData(mouse, key, mask, ignore_mask, index); mHasUnsavedChanges = true; } @@ -277,45 +335,11 @@ std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata) } else if (keydata.mMask != MASK_NONE) { - LL_ERRS() << "Masks binding without keys is not supported yet" << LL_ENDL; + result = LLKeyboard::stringFromAccelerator(keydata.mMask); } - #ifdef LL_DARWIN - // darwin uses special symbols and doesn't need '+' for masks - if (mMouse != CLICK_NONE && mKey != KEY_NONE) - { - result += " + "; - } - #else - if (keydata.mMouse != CLICK_NONE && !result.empty()) - { - result += " + "; - } - #endif + result += string_from_mouse(keydata.mMouse); - switch (keydata.mMouse) - { - case CLICK_LEFT: - result += "LMB"; - break; - case CLICK_MIDDLE: - result += "MMB"; - break; - case CLICK_RIGHT: - result += "RMB"; - break; - case CLICK_BUTTON4: - result += "MB4"; - break; - case CLICK_BUTTON5: - result += "MB5"; - break; - case CLICK_DOUBLELEFT: - result += "Double LMB"; - break; - default: - break; - } return result; } @@ -339,6 +363,8 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerKeyboard::KeyMode& ke { KEY key; MASK mask; + EMouseClickType mouse = it->mouse.isProvided() ? mouse_from_string(it->mouse) : CLICK_NONE; + bool ignore = it->ignore.isProvided() ? it->ignore.getValue() : false; if (it->key.getValue().empty()) { key = KEY_NONE; @@ -358,7 +384,7 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerKeyboard::KeyMode& ke LLKeyConflict &type_data = (*destination)[iter->second]; type_data.mAssignable = true; // Don't care about conflict level, all movement and view commands already account for it - type_data.mKeyBind.addKeyData(CLICK_NONE, key, mask); + type_data.mKeyBind.addKeyData(mouse, key, mask, ignore); } } } @@ -418,6 +444,10 @@ void LLKeyConflictHandler::loadFromSettings(EModes load_mode) { mControlsMap.clear(); mDefaultsMap.clear(); + + // E.X. In case we need placeholder keys for conflict resolution. + generatePlaceholders(load_mode); + if (load_mode == MODE_GENERAL) { for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) @@ -463,12 +493,11 @@ void LLKeyConflictHandler::loadFromSettings(EModes load_mode) } else { - mControlsMap = mDefaultsMap; + // mind placeholders + mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end()); } } mLoadedMode = load_mode; - - generatePlaceholders(); } void LLKeyConflictHandler::saveToSettings() @@ -555,6 +584,8 @@ void LLKeyConflictHandler::saveToSettings() binding.key = LLKeyboard::stringFromKey(data.mKey); } binding.mask = string_from_mask(data.mMask); + binding.mouse.set(string_from_mouse(data.mMouse), true); //set() because 'optional', for compatibility purposes + binding.ignore.set(data.mIgnoreMasks, true); binding.command = getControlName(iter->first); mode.bindings.add(binding); } @@ -711,8 +742,8 @@ void LLKeyConflictHandler::resetToDefaults(EModes mode) else { mControlsMap.clear(); - mControlsMap = mDefaultsMap; - generatePlaceholders(); + generatePlaceholders(mode); + mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end()); } mHasUnsavedChanges = true; @@ -774,7 +805,7 @@ void LLKeyConflictHandler::resetKeyboardBindings() gViewerKeyboard.loadBindingsXML(filename); } -void LLKeyConflictHandler::generatePlaceholders() +void LLKeyConflictHandler::generatePlaceholders(EModes load_mode) { } @@ -784,6 +815,6 @@ void LLKeyConflictHandler::registerTemporaryControl(EControlTypes control_type, LLKeyConflict *type_data = &mControlsMap[control_type]; type_data->mAssignable = false; type_data->mConflictMask = conflict_mask; - type_data->mKeyBind.addKeyData(mouse, key, mask); + type_data->mKeyBind.addKeyData(mouse, key, mask, false); } -- cgit v1.2.3 From 4ae2165c4516a74012d30610b4c53de6d3ccaf90 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 25 Sep 2019 22:23:09 +0300 Subject: SL-6109 LMB DLMB in progress --- indra/newview/llkeyconflict.cpp | 60 ++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 40 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index be0b8fd4ca..87ea408a6a 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -57,8 +57,8 @@ static const std::string typetostring[LLKeyConflictHandler::CONTROL_NUM_INDICES] "control_touch", "control_wear", "control_movements", - "control_moveto", - "control_teleportto", + "walk_to", + "teleport_to", "push_forward", "push_backward", "turn_left", @@ -164,7 +164,9 @@ static const control_enum_t command_to_key = { "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 }, + { "toggle_enable_media", LLKeyConflictHandler::CONTROL_ENABLE_MEDIA }, + { "walk_to", LLKeyConflictHandler::CONTROL_MOVETO }, + { "teleport_to", LLKeyConflictHandler::CONTROL_TELEPORTTO }, }; @@ -268,7 +270,7 @@ LLKeyConflictHandler::LLKeyConflictHandler() LLKeyConflictHandler::LLKeyConflictHandler(EModes mode) : mHasUnsavedChanges(false), - mLoadedMode(mode) + mLoadMode(mode) { loadFromSettings(mode); } @@ -497,7 +499,7 @@ void LLKeyConflictHandler::loadFromSettings(EModes load_mode) mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end()); } } - mLoadedMode = load_mode; + mLoadMode = load_mode; } void LLKeyConflictHandler::saveToSettings() @@ -507,7 +509,7 @@ void LLKeyConflictHandler::saveToSettings() return; } - if (mLoadedMode == MODE_GENERAL) + if (mLoadMode == MODE_GENERAL) { for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) { @@ -591,7 +593,7 @@ void LLKeyConflictHandler::saveToSettings() } } - switch (mLoadedMode) + switch (mLoadMode) { case MODE_FIRST_PERSON: if (keys.first_person.isProvided()) @@ -657,7 +659,7 @@ void LLKeyConflictHandler::saveToSettings() LLKeyData LLKeyConflictHandler::getDefaultControl(EControlTypes control_type, U32 index) { - if (mLoadedMode == MODE_GENERAL) + if (mLoadMode == MODE_GENERAL) { std::string name = getControlName(control_type); LLControlVariablePtr var = gSavedSettings.getControl(name); @@ -686,7 +688,7 @@ void LLKeyConflictHandler::resetToDefault(EControlTypes control_type, U32 index) void LLKeyConflictHandler::resetToDefault(EControlTypes control_type) { - if (mLoadedMode == MODE_GENERAL) + if (mLoadMode == MODE_GENERAL) { std::string name = getControlName(control_type); LLControlVariablePtr var = gSavedSettings.getControl(name); @@ -753,40 +755,18 @@ void LLKeyConflictHandler::resetToDefaults() { if (!empty()) { - resetToDefaults(mLoadedMode); + resetToDefaults(mLoadMode); } -} - -void LLKeyConflictHandler::resetAllToDefaults() -{ - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "keys.xml"); - if (gDirUtilp->fileExists(filename)) + else { - LLFile::remove(filename); - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "keys.xml"); - gViewerKeyboard.loadBindingsXML(filename); + // not optimal since: + // 1. We are not sure that mLoadMode was set + // 2. We are not sure if there are any changes in comparison to default + // 3. We are loading 'current' only to replace it + // but it is reliable and works Todo: consider optimizing. + loadFromSettings(mLoadMode); + resetToDefaults(mLoadMode); } - - for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) - { - EControlTypes type = (EControlTypes)i; - switch (type) - { - case LLKeyConflictHandler::CONTROL_VIEW_ACTIONS: - case LLKeyConflictHandler::CONTROL_INTERACTIONS: - case LLKeyConflictHandler::CONTROL_MOVEMENTS: - case LLKeyConflictHandler::CONTROL_MEDIACONTENT: - case LLKeyConflictHandler::CONTROL_RESERVED: - // ignore 'headers', they are for representation and organization purposes - break; - default: - { - resetToDefault(type); - break; - } - } - } - mHasUnsavedChanges = false; } void LLKeyConflictHandler::clear() -- cgit v1.2.3 From 2532a2ee9ee9003e2c6b72f8da19979a9e3dd2f6 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 26 Sep 2019 22:28:18 +0300 Subject: SL-6109 Conflict resolution --- indra/newview/llkeyconflict.cpp | 128 ++++++++++++++++++++++++++++++++-------- 1 file changed, 103 insertions(+), 25 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 87ea408a6a..66d420369e 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -105,8 +105,8 @@ static const std::string typetostring[LLKeyConflictHandler::CONTROL_NUM_INDICES] "control_mediacontent", "toggle_pause_media", "toggle_enable_media", - "control_voice", - "control_toggle_voice", + "voice_follow_key", + "toggle_voice", "start_chat", "start_gesture", "control_reserved", @@ -167,6 +167,8 @@ static const control_enum_t command_to_key = { "toggle_enable_media", LLKeyConflictHandler::CONTROL_ENABLE_MEDIA }, { "walk_to", LLKeyConflictHandler::CONTROL_MOVETO }, { "teleport_to", LLKeyConflictHandler::CONTROL_TELEPORTTO }, + { "toggle_voice", LLKeyConflictHandler::CONTROL_TOGGLE_VOICE }, + { "voice_follow_key", LLKeyConflictHandler::CONTROL_VOICE }, }; @@ -256,19 +258,9 @@ EMouseClickType mouse_from_string(const std::string& input) LLKeyConflictHandler::LLKeyConflictHandler() : mHasUnsavedChanges(false) { - // todo: assign conflic priorities - // todo: load from keys.xml? - - // Thise controls are meant to cause conflicts when user tries to assign same control somewhere else - /*registerTemporaryControl(CONTROL_RESERVED_MENU, CLICK_RIGHT, KEY_NONE, MASK_NONE, 0); - registerTemporaryControl(CONTROL_SHIFT_SELECT, CLICK_LEFT, KEY_NONE, MASK_SHIFT, 0); - registerTemporaryControl(CONTROL_CNTRL_SELECT, CLICK_LEFT, KEY_NONE, MASK_CONTROL, 0); - registerTemporaryControl(CONTROL_DELETE, CLICK_NONE, KEY_DELETE, MASK_NONE, 0); - - loadFromSettings();*/ } -LLKeyConflictHandler::LLKeyConflictHandler(EModes mode) +LLKeyConflictHandler::LLKeyConflictHandler(ESourceMode mode) : mHasUnsavedChanges(false), mLoadMode(mode) { @@ -305,16 +297,26 @@ bool LLKeyConflictHandler::canAssignControl(EControlTypes control_type) return false; } -void LLKeyConflictHandler::registerControl(EControlTypes control_type, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask) +bool 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, ignore_mask, index); - - mHasUnsavedChanges = true; + LLKeyData data(mouse, key, mask, ignore_mask); + if (type_data.mKeyBind.getKeyData(index) == data) + { + return true; + } + if (removeConflicts(data, type_data.mConflictMask)) + { + type_data.mKeyBind.replaceKeyData(data, index); + mHasUnsavedChanges = true; + return true; + } + // control already in use/blocked + return false; } LLKeyData LLKeyConflictHandler::getControl(EControlTypes control_type, U32 index) @@ -391,7 +393,7 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerKeyboard::KeyMode& ke } } -void LLKeyConflictHandler::loadFromSettings(const EModes &load_mode, const std::string &filename, control_map_t *destination) +void LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination) { if (filename.empty()) { @@ -442,7 +444,7 @@ void LLKeyConflictHandler::loadFromSettings(const EModes &load_mode, const std:: } } -void LLKeyConflictHandler::loadFromSettings(EModes load_mode) +void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) { mControlsMap.clear(); mDefaultsMap.clear(); @@ -571,6 +573,11 @@ void LLKeyConflictHandler::saveToSettings() control_map_t::iterator end = mControlsMap.end(); for (; iter != end; ++iter) { + // By default xml have (had) up to 6 elements per function + // eventually it will be cleaned up and UI will only shows 3 per function, + // so make sure to cleanup. + // Also this helps in keeping file small. + iter->second.mKeyBind.trimEmpty(); U32 size = iter->second.mKeyBind.getDataCount(); for (U32 i = 0; i < size; ++i) { @@ -683,10 +690,16 @@ LLKeyData LLKeyConflictHandler::getDefaultControl(EControlTypes control_type, U3 void LLKeyConflictHandler::resetToDefault(EControlTypes control_type, U32 index) { LLKeyData data = getDefaultControl(control_type, index); - mControlsMap[control_type].setKeyData(data, index); + + if (data != mControlsMap[control_type].getKeyData(index)) + { + // reset controls that might have been switched to our current control + removeConflicts(data, mControlsMap[control_type].mConflictMask); + mControlsMap[control_type].setKeyData(data, index); + } } -void LLKeyConflictHandler::resetToDefault(EControlTypes control_type) +void LLKeyConflictHandler::resetToDefaultAndResolve(EControlTypes control_type, bool ignore_conflicts) { if (mLoadMode == MODE_GENERAL) { @@ -694,7 +707,15 @@ void LLKeyConflictHandler::resetToDefault(EControlTypes control_type) LLControlVariablePtr var = gSavedSettings.getControl(name); if (var) { - mControlsMap[control_type].mKeyBind = LLKeyBind(var->getDefault()); + LLKeyBind bind(var->getDefault()); + if (!ignore_conflicts) + { + for (S32 i = 0; i < bind.getDataCount(); ++i) + { + removeConflicts(bind.getKeyData(i), mControlsMap[control_type].mConflictMask); + } + } + mControlsMap[control_type].mKeyBind = bind; } else { @@ -706,6 +727,13 @@ void LLKeyConflictHandler::resetToDefault(EControlTypes control_type) control_map_t::iterator iter = mDefaultsMap.find(control_type); if (iter != mDefaultsMap.end()) { + if (!ignore_conflicts) + { + for (S32 i = 0; i < iter->second.mKeyBind.getDataCount(); ++i) + { + removeConflicts(iter->second.mKeyBind.getKeyData(i), mControlsMap[control_type].mConflictMask); + } + } mControlsMap[control_type].mKeyBind = iter->second.mKeyBind; } else @@ -715,7 +743,13 @@ void LLKeyConflictHandler::resetToDefault(EControlTypes control_type) } } -void LLKeyConflictHandler::resetToDefaults(EModes mode) +void LLKeyConflictHandler::resetToDefault(EControlTypes control_type) +{ + // reset specific binding without ignoring conflicts + resetToDefaultAndResolve(control_type, false); +} + +void LLKeyConflictHandler::resetToDefaults(ESourceMode mode) { if (mode == MODE_GENERAL) { @@ -735,7 +769,7 @@ void LLKeyConflictHandler::resetToDefaults(EModes mode) break; default: { - resetToDefault(type); + resetToDefaultAndResolve(type, true); break; } } @@ -785,9 +819,53 @@ void LLKeyConflictHandler::resetKeyboardBindings() gViewerKeyboard.loadBindingsXML(filename); } -void LLKeyConflictHandler::generatePlaceholders(EModes load_mode) +void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) { + // These controls are meant to cause conflicts 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 + /*registerTemporaryControl(CONTROL_RESERVED_MENU, CLICK_RIGHT, KEY_NONE, MASK_NONE, 0); + registerTemporaryControl(CONTROL_DELETE, CLICK_NONE, KEY_DELETE, MASK_NONE, 0);*/ +} +bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &conlict_mask) +{ + if (conlict_mask == CONFLICT_NOTHING) + { + // Can't conflict + return true; + } + 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) + { + 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 (cntrl_iter->second.mAssignable) + { + // Potentially we can have multiple conflict flags conflicting + // including unassignable keys. + // So record the conflict and find all others before doing any changes. + // Assume that there is only one conflict per bind + conflict_list[cntrl_iter->first] = index; + } + else + { + return false; + } + } + } + + std::map::iterator cnflct_iter = conflict_list.begin(); + std::map::iterator cnflct_end = conflict_list.end(); + for (; cnflct_iter != cnflct_end; ++cnflct_iter) + { + mControlsMap[cnflct_iter->first].mKeyBind.resetKeyData(cnflct_iter->second); + } + return true; } void LLKeyConflictHandler::registerTemporaryControl(EControlTypes control_type, EMouseClickType mouse, KEY key, MASK mask, U32 conflict_mask) -- cgit v1.2.3 From b12cf6696348520556cf70f96e0562776479fe70 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Fri, 27 Sep 2019 15:25:47 +0300 Subject: SL-6109 Small reorganisation --- indra/newview/llkeyconflict.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 66d420369e..e81d121e3b 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -37,7 +37,7 @@ #include "llinitparam.h" #include "llkeyboard.h" #include "llviewercontrol.h" -#include "llviewerkeyboard.h" +#include "llviewerinput.h" #include "llxuiparser.h" //#include "llstring.h" @@ -117,7 +117,7 @@ static const std::string typetostring[LLKeyConflictHandler::CONTROL_NUM_INDICES] "control_cntrl_select" }; -// note, a solution is needed that will keep this up to date with llviewerkeyboard +// note, a solution is needed that will keep this up to date with llviewerinput typedef std::map control_enum_t; static const control_enum_t command_to_key = { @@ -358,9 +358,9 @@ std::string LLKeyConflictHandler::getControlString(EControlTypes control_type, U return getStringFromKeyData(mControlsMap[control_type].getKeyData(index)); } -void LLKeyConflictHandler::loadFromSettings(const LLViewerKeyboard::KeyMode& keymode, control_map_t *destination) +void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymode, control_map_t *destination) { - for (LLInitParam::ParamIterator::const_iterator it = keymode.bindings.begin(), + for (LLInitParam::ParamIterator::const_iterator it = keymode.bindings.begin(), end_it = keymode.bindings.end(); it != end_it; ++it) @@ -400,7 +400,7 @@ void LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const return; } - LLViewerKeyboard::Keys keys; + LLViewerInput::Keys keys; LLSimpleXUIParser parser; if (parser.readXUI(filename, keys) @@ -556,7 +556,7 @@ void LLKeyConflictHandler::saveToSettings() gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""), gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - LLViewerKeyboard::Keys keys; + LLViewerInput::Keys keys; LLSimpleXUIParser parser; if (parser.readXUI(filename, keys) @@ -566,8 +566,8 @@ void LLKeyConflictHandler::saveToSettings() // todo: fix this // workaround to avoid doing own param container - LLViewerKeyboard::KeyMode mode; - LLViewerKeyboard::KeyBinding binding; + LLViewerInput::KeyMode mode; + LLViewerInput::KeyBinding binding; control_map_t::iterator iter = mControlsMap.begin(); control_map_t::iterator end = mControlsMap.end(); @@ -657,7 +657,7 @@ void LLKeyConflictHandler::saveToSettings() // Now force a rebind for keyboard if (gDirUtilp->fileExists(filename)) { - gViewerKeyboard.loadBindingsXML(filename); + gViewerInput.loadBindingsXML(filename); } } } @@ -816,7 +816,7 @@ void LLKeyConflictHandler::resetKeyboardBindings() gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""), gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - gViewerKeyboard.loadBindingsXML(filename); + gViewerInput.loadBindingsXML(filename); } void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) -- cgit v1.2.3 From 0b8021870335ff9b9684fb193c6e0fe2f02b4091 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Fri, 27 Sep 2019 19:53:33 +0300 Subject: SL-6109 Cleanup, run commands, and preparation for tooltip support --- indra/newview/llkeyconflict.cpp | 426 ++++++++++++++-------------------------- 1 file changed, 150 insertions(+), 276 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index e81d121e3b..c74eea6e47 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -41,135 +41,7 @@ #include "llxuiparser.h" //#include "llstring.h" -static const std::string typetostring[LLKeyConflictHandler::CONTROL_NUM_INDICES] = { - "control_view_actions", - "control_about", - "control_orbit", - "control_pan", - "control_world_map", - "control_zoom", - "control_interactions", - "control_build", - //"control_drag", - "control_edit", - //"control_menu", - "control_open", - "control_touch", - "control_wear", - "control_movements", - "walk_to", - "teleport_to", - "push_forward", - "push_backward", - "turn_left", - "turn_right", - "slide_left", - "slide_right", - "jump", - "push_down", - //"control_run", - "toggle_run", - "toggle_fly", - "toggle_sit", - "stop_moving", - "control_camera", - "look_up", - "look_down", - "move_forward", - "move_backward", - "move_forward_fast", - "move_backward_fast", - "move_forward_sitting", - "move_backward_sitting", - "spin_over", - "spin_under", - "spin_over_sitting", - "spin_under_sitting", - "pan_up", - "pan_down", - "pan_left", - "pan_right", - "pan_in", - "pan_out", - "spin_around_ccw", - "spin_around_cw", - "spin_around_ccw_sitting", - "spin_around_cw_sitting", - "control_edit_title", - "edit_avatar_spin_ccw", - "edit_avatar_spin_cw", - "edit_avatar_spin_over", - "edit_avatar_spin_under", - "edit_avatar_move_forward", - "edit_avatar_move_backward", - "control_mediacontent", - "toggle_pause_media", - "toggle_enable_media", - "voice_follow_key", - "toggle_voice", - "start_chat", - "start_gesture", - "control_reserved", - "control_delete", - "control_menu", - "control_reserved_select", - "control_shift_select", - "control_cntrl_select" -}; - -// note, a solution is needed that will keep this up to date with llviewerinput -typedef std::map control_enum_t; -static const control_enum_t command_to_key = -{ - { "jump", LLKeyConflictHandler::CONTROL_JUMP }, - { "push_down", LLKeyConflictHandler::CONTROL_DOWN }, - { "push_forward", LLKeyConflictHandler::CONTROL_FORWARD }, - { "push_backward", LLKeyConflictHandler::CONTROL_BACKWARD }, - { "look_up", LLKeyConflictHandler::CONTROL_LOOK_UP }, - { "look_down", LLKeyConflictHandler::CONTROL_LOOK_DOWN }, - { "toggle_fly", LLKeyConflictHandler::CONTROL_TOGGLE_FLY }, - { "turn_left", LLKeyConflictHandler::CONTROL_LEFT }, - { "turn_right", LLKeyConflictHandler::CONTROL_RIGHT }, - { "slide_left", LLKeyConflictHandler::CONTROL_LSTRAFE }, - { "slide_right", LLKeyConflictHandler::CONTROL_RSTRAFE }, - { "spin_around_ccw", LLKeyConflictHandler::CONTROL_CAMERA_SPIN_CCW }, // todo, no idea what these spins are - { "spin_around_cw", LLKeyConflictHandler::CONTROL_CAMERA_SPIN_CW }, - { "spin_around_ccw_sitting", LLKeyConflictHandler::CONTROL_CAMERA_SPIN_CCW_SITTING }, - { "spin_around_cw_sitting", LLKeyConflictHandler::CONTROL_CAMERA_SPIN_CCW_SITTING }, - { "spin_over", LLKeyConflictHandler::CONTROL_CAMERA_SOVER }, - { "spin_under", LLKeyConflictHandler::CONTROL_CAMERA_SUNDER }, - { "spin_over_sitting", LLKeyConflictHandler::CONTROL_CAMERA_SOVER_SITTING }, - { "spin_under_sitting", LLKeyConflictHandler::CONTROL_CAMERA_SUNDER_SITTING }, - { "move_forward", LLKeyConflictHandler::CONTROL_CAMERA_FORWARD }, - { "move_backward", LLKeyConflictHandler::CONTROL_CAMERA_BACKWARD }, - { "move_forward_sitting", LLKeyConflictHandler::CONTROL_CAMERA_FSITTING }, - { "move_backward_sitting", LLKeyConflictHandler::CONTROL_CAMERA_BSITTING }, - { "pan_up", LLKeyConflictHandler::CONTROL_CAMERA_PANUP }, - { "pan_down", LLKeyConflictHandler::CONTROL_CAMERA_PANDOWN }, - { "pan_left", LLKeyConflictHandler::CONTROL_CAMERA_PANLEFT }, - { "pan_right", LLKeyConflictHandler::CONTROL_CAMERA_PANRIGHT }, - { "pan_in", LLKeyConflictHandler::CONTROL_CAMERA_PANIN }, - { "pan_out", LLKeyConflictHandler::CONTROL_CAMERA_PANOUT }, - { "move_forward_fast", LLKeyConflictHandler::CONTROL_CAMERA_FFORWARD }, - { "move_backward_fast", LLKeyConflictHandler::CONTROL_CAMERA_FBACKWARD }, - { "edit_avatar_spin_ccw", LLKeyConflictHandler::CONTROL_EDIT_AV_SPIN_CCW }, - { "edit_avatar_spin_cw", LLKeyConflictHandler::CONTROL_EDIT_AV_SPIN_CW }, - { "edit_avatar_spin_over", LLKeyConflictHandler::CONTROL_EDIT_AV_SPIN_OVER }, - { "edit_avatar_spin_under", LLKeyConflictHandler::CONTROL_EDIT_AV_SPIN_UNDER }, - { "edit_avatar_move_forward", LLKeyConflictHandler::CONTROL_EDIT_AV_MV_FORWARD }, - { "edit_avatar_move_backward", LLKeyConflictHandler::CONTROL_EDIT_AV_MV_BACKWARD }, - { "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 }, - { "walk_to", LLKeyConflictHandler::CONTROL_MOVETO }, - { "teleport_to", LLKeyConflictHandler::CONTROL_TELEPORTTO }, - { "toggle_voice", LLKeyConflictHandler::CONTROL_TOGGLE_VOICE }, - { "voice_follow_key", LLKeyConflictHandler::CONTROL_VOICE }, -}; +static const std::string saved_settings_key_controls[] = { "placeholder" }; // LLKeyboard::stringFromMask is meant for UI and is OS dependent, @@ -267,29 +139,29 @@ LLKeyConflictHandler::LLKeyConflictHandler(ESourceMode mode) loadFromSettings(mode); } -bool LLKeyConflictHandler::canHandleControl(LLKeyConflictHandler::EControlTypes control_type, EMouseClickType mouse_ind, KEY key, MASK mask) +bool LLKeyConflictHandler::canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask) { - return mControlsMap[control_type].canHandle(mouse_ind, key, mask); + return mControlsMap[control_name].canHandle(mouse_ind, key, mask); } -bool LLKeyConflictHandler::canHandleKey(EControlTypes control_type, KEY key, MASK mask) +bool LLKeyConflictHandler::canHandleKey(const std::string &control_name, KEY key, MASK mask) { - return canHandleControl(control_type, CLICK_NONE, key, mask); + return canHandleControl(control_name, CLICK_NONE, key, mask); } -bool LLKeyConflictHandler::canHandleMouse(LLKeyConflictHandler::EControlTypes control_type, EMouseClickType mouse_ind, MASK mask) +bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask) { - return canHandleControl(control_type, mouse_ind, KEY_NONE, mask); + return canHandleControl(control_name, mouse_ind, KEY_NONE, mask); } -bool LLKeyConflictHandler::canHandleMouse(EControlTypes control_type, S32 mouse_ind, MASK mask) +bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask) { - return canHandleControl(control_type, (EMouseClickType)mouse_ind, KEY_NONE, mask); + return canHandleControl(control_name, (EMouseClickType)mouse_ind, KEY_NONE, mask); } -bool LLKeyConflictHandler::canAssignControl(EControlTypes control_type) +bool LLKeyConflictHandler::canAssignControl(const std::string &control_name) { - std::map::iterator iter = mControlsMap.find(control_type); + control_map_t::iterator iter = mControlsMap.find(control_name); if (iter != mControlsMap.end()) { return iter->second.mAssignable; @@ -297,9 +169,13 @@ bool LLKeyConflictHandler::canAssignControl(EControlTypes control_type) return false; } -bool LLKeyConflictHandler::registerControl(EControlTypes control_type, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask) +bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask) { - LLKeyConflict &type_data = mControlsMap[control_type]; + if (control_name.empty()) + { + return false; + } + LLKeyConflict &type_data = mControlsMap[control_name]; if (!type_data.mAssignable) { LL_ERRS() << "Error in code, user or system should not be able to change certain controls" << LL_ENDL; @@ -319,9 +195,13 @@ bool LLKeyConflictHandler::registerControl(EControlTypes control_type, U32 index return false; } -LLKeyData LLKeyConflictHandler::getControl(EControlTypes control_type, U32 index) +LLKeyData LLKeyConflictHandler::getControl(const std::string &control_name, U32 index) { - return mControlsMap[control_type].getKeyData(index); + if (control_name.empty()) + { + return LLKeyData(); + } + return mControlsMap[control_name].getKeyData(index); } // static @@ -341,24 +221,37 @@ std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata) { result = LLKeyboard::stringFromAccelerator(keydata.mMask); } + else if (keydata.mIgnoreMasks) + { + result = "acc+"; + } result += string_from_mouse(keydata.mMouse); return result; } -// static -std::string LLKeyConflictHandler::getControlName(EControlTypes control_type) +std::string LLKeyConflictHandler::getControlString(const std::string &control_name, U32 index) { - return typetostring[control_type]; + if (control_name.empty()) + { + return ""; + } + return getStringFromKeyData(mControlsMap[control_name].getKeyData(index)); } -std::string LLKeyConflictHandler::getControlString(EControlTypes control_type, U32 index) +void LLKeyConflictHandler::loadFromControlSettings(const std::string &name) { - return getStringFromKeyData(mControlsMap[control_type].getKeyData(index)); + LLControlVariablePtr var = gSavedSettings.getControl(name); + if (var) + { + LLKeyBind bind(var->getValue()); + LLKeyConflict key(bind, true, 0); + mControlsMap[name] = key; + } } -void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymode, control_map_t *destination) +void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymode, control_map_t *destination) { for (LLInitParam::ParamIterator::const_iterator it = keymode.bindings.begin(), end_it = keymode.bindings.end(); @@ -378,28 +271,23 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymo LLKeyboard::keyFromString(it->key, &key); } LLKeyboard::maskFromString(it->mask, &mask); - std::string command_name = it->command; - // it->command - // It might be better to have map, but at the moment enum is easier to iterate through. - // Besides keys.xml might not contain all commands - control_enum_t::const_iterator iter = command_to_key.find(command_name); - if (iter != command_to_key.end()) - { - 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(mouse, key, mask, ignore); - } + // Note: it->command is also the name of UI element, howhever xml we are loading from + // might not know all the commands, so UI will have to know what to fill by its own + LLKeyConflict &type_data = (*destination)[it->command]; + type_data.mAssignable = true; + type_data.mKeyBind.addKeyData(mouse, key, mask, ignore); } } -void LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination) +bool LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination) { if (filename.empty()) { - return; + return false; } + bool res = false; + LLViewerInput::Keys keys; LLSimpleXUIParser parser; @@ -412,39 +300,45 @@ void LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const if (keys.first_person.isProvided()) { loadFromSettings(keys.first_person, destination); + res = true; } break; case MODE_THIRD_PERSON: if (keys.third_person.isProvided()) { loadFromSettings(keys.third_person, destination); + res = true; } break; case MODE_EDIT: if (keys.edit.isProvided()) { loadFromSettings(keys.edit, destination); + res = true; } break; case MODE_EDIT_AVATAR: if (keys.edit_avatar.isProvided()) { loadFromSettings(keys.edit_avatar, destination); + res = true; } break; case MODE_SITTING: if (keys.sitting.isProvided()) { loadFromSettings(keys.sitting, destination); + res = true; } break; default: break; } } + return res; } -void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) +void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) { mControlsMap.clear(); mDefaultsMap.clear(); @@ -454,48 +348,26 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) if (load_mode == MODE_GENERAL) { - for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) + // load settings clss knows about, but it also possible to load settings by name separately + const S32 size = std::extent::value; + for (U32 i = 0; i < size; i++) { - EControlTypes type = (EControlTypes)i; - switch (type) - { - case LLKeyConflictHandler::CONTROL_VIEW_ACTIONS: - case LLKeyConflictHandler::CONTROL_INTERACTIONS: - case LLKeyConflictHandler::CONTROL_MOVEMENTS: - case LLKeyConflictHandler::CONTROL_MEDIACONTENT: - case LLKeyConflictHandler::CONTROL_CAMERA: - case LLKeyConflictHandler::CONTROL_EDIT_TITLE: - case LLKeyConflictHandler::CONTROL_RESERVED: - // ignore 'headers', they are for representation and organization purposes - break; - default: - { - std::string name = getControlName(type); - LLControlVariablePtr var = gSavedSettings.getControl(name); - if (var) - { - LLKeyBind bind(var->getValue()); - LLKeyConflict key(bind, true, 0); - mControlsMap[type] = key; - } - break; - } - } + loadFromControlSettings(saved_settings_key_controls[i]); } } else { // load defaults std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "keys.xml"); - loadFromSettings(load_mode, filename, &mDefaultsMap); + if (!loadFromSettings(load_mode, filename, &mDefaultsMap)) + { + LL_WARNS() << "Failed to load default settings, aborting" << LL_ENDL; + return; + } // load user's filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "keys.xml"); - if (gDirUtilp->fileExists(filename)) - { - loadFromSettings(load_mode, filename, &mControlsMap); - } - else + if (!gDirUtilp->fileExists(filename) || loadFromSettings(load_mode, filename, &mControlsMap)) { // mind placeholders mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end()); @@ -504,7 +376,7 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) mLoadMode = load_mode; } -void LLKeyConflictHandler::saveToSettings() +void LLKeyConflictHandler::saveToSettings() { if (mControlsMap.empty()) { @@ -513,39 +385,33 @@ void LLKeyConflictHandler::saveToSettings() if (mLoadMode == MODE_GENERAL) { - for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) + control_map_t::iterator iter = mControlsMap.begin(); + control_map_t::iterator end = mControlsMap.end(); + + for (; iter != end; ++iter) { - EControlTypes type = (EControlTypes)i; - switch (type) + if (iter->first.empty()) { - case LLKeyConflictHandler::CONTROL_VIEW_ACTIONS: - case LLKeyConflictHandler::CONTROL_INTERACTIONS: - case LLKeyConflictHandler::CONTROL_MOVEMENTS: - case LLKeyConflictHandler::CONTROL_MEDIACONTENT: - case LLKeyConflictHandler::CONTROL_CAMERA: - case LLKeyConflictHandler::CONTROL_EDIT_TITLE: - case LLKeyConflictHandler::CONTROL_RESERVED: - // ignore 'headers', they are for representation and organization purposes - break; - default: + continue; + } + + LLKeyConflict &key = iter->second; + key.mKeyBind.trimEmpty(); + if (!key.mAssignable) { - if (mControlsMap[type].mAssignable) - { - std::string name = getControlName(type); - if (gSavedSettings.controlExists(name)) - { - gSavedSettings.setLLSD(name, mControlsMap[type].mKeyBind.asLLSD()); - } - else if (!mControlsMap[type].mKeyBind.empty()) - { - // shouldn't happen user side since all settings are supposed to be declared already, but handy when creating new ones - // (just don't forget to change comment and to copy them from user's folder) - LL_INFOS() << "Creating new keybinding " << name << LL_ENDL; - gSavedSettings.declareLLSD(name, mControlsMap[type].mKeyBind.asLLSD(), "comment", LLControlVariable::PERSIST_ALWAYS); - } - } - break; + continue; + } + + if (gSavedSettings.controlExists(iter->first)) + { + gSavedSettings.setLLSD(iter->first, key.mKeyBind.asLLSD()); } + else if (!key.mKeyBind.empty()) + { + // Note: this is currently not in use, might be better for load mechanics to ask for and retain control group + // otherwise settings loaded from other control groups will end in this one + LL_INFOS() << "Creating new keybinding " << iter->first << LL_ENDL; + gSavedSettings.declareLLSD(iter->first, key.mKeyBind.asLLSD(), "comment", LLControlVariable::PERSIST_ALWAYS); } } } @@ -564,8 +430,8 @@ void LLKeyConflictHandler::saveToSettings() { // replace category we edited - // todo: fix this - // workaround to avoid doing own param container + // mode is a HACK to correctly reset bindings without reparsing whole file and avoid doing + // own param container (which will face issues with inasseesible members of LLInitParam) LLViewerInput::KeyMode mode; LLViewerInput::KeyBinding binding; @@ -581,8 +447,20 @@ void LLKeyConflictHandler::saveToSettings() U32 size = iter->second.mKeyBind.getDataCount(); for (U32 i = 0; i < size; ++i) { - // Still write empty keys to make sure we will maintain UI position - LLKeyData data = iter->second.mKeyBind.getKeyData(i); + if (iter->first.empty()) + { + continue; + } + + LLKeyConflict &key = iter->second; + key.mKeyBind.trimEmpty(); + if (key.mKeyBind.empty() || !key.mAssignable) + { + continue; + } + + LLKeyData data = key.mKeyBind.getKeyData(i); + // Still write empty LLKeyData to make sure we will maintain UI position if (data.mKey == KEY_NONE) { binding.key = ""; @@ -595,7 +473,7 @@ void LLKeyConflictHandler::saveToSettings() 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); + binding.command = iter->first; mode.bindings.add(binding); } } @@ -664,12 +542,15 @@ void LLKeyConflictHandler::saveToSettings() mHasUnsavedChanges = false; } -LLKeyData LLKeyConflictHandler::getDefaultControl(EControlTypes control_type, U32 index) +LLKeyData LLKeyConflictHandler::getDefaultControl(const std::string &control_name, U32 index) { + if (control_name.empty()) + { + return LLKeyData(); + } if (mLoadMode == MODE_GENERAL) { - std::string name = getControlName(control_type); - LLControlVariablePtr var = gSavedSettings.getControl(name); + LLControlVariablePtr var = gSavedSettings.getControl(control_name); if (var) { return LLKeyBind(var->getDefault()).getKeyData(index); @@ -678,7 +559,7 @@ LLKeyData LLKeyConflictHandler::getDefaultControl(EControlTypes control_type, U3 } else { - control_map_t::iterator iter = mDefaultsMap.find(control_type); + control_map_t::iterator iter = mDefaultsMap.find(control_name); if (iter != mDefaultsMap.end()) { return iter->second.mKeyBind.getKeyData(index); @@ -687,24 +568,31 @@ LLKeyData LLKeyConflictHandler::getDefaultControl(EControlTypes control_type, U3 } } -void LLKeyConflictHandler::resetToDefault(EControlTypes control_type, U32 index) +void LLKeyConflictHandler::resetToDefault(const std::string &control_name, U32 index) { - LLKeyData data = getDefaultControl(control_type, index); + if (control_name.empty()) + { + return; + } + LLKeyData data = getDefaultControl(control_name, index); - if (data != mControlsMap[control_type].getKeyData(index)) + if (data != mControlsMap[control_name].getKeyData(index)) { // reset controls that might have been switched to our current control - removeConflicts(data, mControlsMap[control_type].mConflictMask); - mControlsMap[control_type].setKeyData(data, index); + removeConflicts(data, mControlsMap[control_name].mConflictMask); + mControlsMap[control_name].setKeyData(data, index); } } -void LLKeyConflictHandler::resetToDefaultAndResolve(EControlTypes control_type, bool ignore_conflicts) +void LLKeyConflictHandler::resetToDefaultAndResolve(const std::string &control_name, bool ignore_conflicts) { + if (control_name.empty()) + { + return; + } if (mLoadMode == MODE_GENERAL) { - std::string name = getControlName(control_type); - LLControlVariablePtr var = gSavedSettings.getControl(name); + LLControlVariablePtr var = gSavedSettings.getControl(control_name); if (var) { LLKeyBind bind(var->getDefault()); @@ -712,67 +600,53 @@ void LLKeyConflictHandler::resetToDefaultAndResolve(EControlTypes control_type, { for (S32 i = 0; i < bind.getDataCount(); ++i) { - removeConflicts(bind.getKeyData(i), mControlsMap[control_type].mConflictMask); + removeConflicts(bind.getKeyData(i), mControlsMap[control_name].mConflictMask); } } - mControlsMap[control_type].mKeyBind = bind; + mControlsMap[control_name].mKeyBind = bind; } else { - mControlsMap[control_type].mKeyBind.clear(); + mControlsMap[control_name].mKeyBind.clear(); } } else { - control_map_t::iterator iter = mDefaultsMap.find(control_type); + control_map_t::iterator iter = mDefaultsMap.find(control_name); if (iter != mDefaultsMap.end()) { if (!ignore_conflicts) { for (S32 i = 0; i < iter->second.mKeyBind.getDataCount(); ++i) { - removeConflicts(iter->second.mKeyBind.getKeyData(i), mControlsMap[control_type].mConflictMask); + removeConflicts(iter->second.mKeyBind.getKeyData(i), mControlsMap[control_name].mConflictMask); } } - mControlsMap[control_type].mKeyBind = iter->second.mKeyBind; + mControlsMap[control_name].mKeyBind = iter->second.mKeyBind; } else { - mControlsMap[control_type].mKeyBind.clear(); + mControlsMap[control_name].mKeyBind.clear(); } } } -void LLKeyConflictHandler::resetToDefault(EControlTypes control_type) +void LLKeyConflictHandler::resetToDefault(const std::string &control_name) { // reset specific binding without ignoring conflicts - resetToDefaultAndResolve(control_type, false); + resetToDefaultAndResolve(control_name, false); } void LLKeyConflictHandler::resetToDefaults(ESourceMode mode) { if (mode == MODE_GENERAL) { - for (U32 i = 0; i < CONTROL_NUM_INDICES; i++) + control_map_t::iterator iter = mControlsMap.begin(); + control_map_t::iterator end = mControlsMap.end(); + + for (; iter != end; ++iter) { - EControlTypes type = (EControlTypes)i; - switch (type) - { - case LLKeyConflictHandler::CONTROL_VIEW_ACTIONS: - case LLKeyConflictHandler::CONTROL_INTERACTIONS: - case LLKeyConflictHandler::CONTROL_MOVEMENTS: - case LLKeyConflictHandler::CONTROL_MEDIACONTENT: - case LLKeyConflictHandler::CONTROL_CAMERA: - case LLKeyConflictHandler::CONTROL_EDIT_TITLE: - case LLKeyConflictHandler::CONTROL_RESERVED: - // ignore 'headers', they are for representation and organization purposes - break; - default: - { - resetToDefaultAndResolve(type, true); - break; - } - } + resetToDefaultAndResolve(iter->first, true); } } else @@ -834,7 +708,7 @@ bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &con // Can't conflict return true; } - std::map conflict_list; + 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) @@ -859,8 +733,8 @@ bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &con } } - std::map::iterator cnflct_iter = conflict_list.begin(); - std::map::iterator cnflct_end = conflict_list.end(); + std::map::iterator cnflct_iter = conflict_list.begin(); + std::map::iterator cnflct_end = conflict_list.end(); for (; cnflct_iter != cnflct_end; ++cnflct_iter) { mControlsMap[cnflct_iter->first].mKeyBind.resetKeyData(cnflct_iter->second); @@ -868,9 +742,9 @@ bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &con return true; } -void LLKeyConflictHandler::registerTemporaryControl(EControlTypes control_type, EMouseClickType mouse, KEY key, MASK mask, U32 conflict_mask) +void LLKeyConflictHandler::registerTemporaryControl(const std::string &control_name, EMouseClickType mouse, KEY key, MASK mask, U32 conflict_mask) { - LLKeyConflict *type_data = &mControlsMap[control_type]; + LLKeyConflict *type_data = &mControlsMap[control_name]; type_data->mAssignable = false; type_data->mConflictMask = conflict_mask; type_data->mKeyBind.addKeyData(mouse, key, mask, false); -- cgit v1.2.3 From 2e656ed358af28f56c8b900345956d431f8c7b4d Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 2 Oct 2019 20:51:47 +0300 Subject: SL-6109 Removed obsolete control, moved table init to xml, cleanup --- indra/newview/llkeyconflict.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index c74eea6e47..01230ea26a 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -166,7 +166,8 @@ bool LLKeyConflictHandler::canAssignControl(const std::string &control_name) { return iter->second.mAssignable; } - return false; + // If we don't know this control means it wasn't assigned by user yet and thus is editable + return true; } bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask) @@ -346,7 +347,7 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) // E.X. In case we need placeholder keys for conflict resolution. generatePlaceholders(load_mode); - if (load_mode == MODE_GENERAL) + if (load_mode == MODE_SAVED_SETTINGS) { // load settings clss knows about, but it also possible to load settings by name separately const S32 size = std::extent::value; @@ -383,7 +384,7 @@ void LLKeyConflictHandler::saveToSettings() return; } - if (mLoadMode == MODE_GENERAL) + if (mLoadMode == MODE_SAVED_SETTINGS) { control_map_t::iterator iter = mControlsMap.begin(); control_map_t::iterator end = mControlsMap.end(); @@ -548,7 +549,7 @@ LLKeyData LLKeyConflictHandler::getDefaultControl(const std::string &control_nam { return LLKeyData(); } - if (mLoadMode == MODE_GENERAL) + if (mLoadMode == MODE_SAVED_SETTINGS) { LLControlVariablePtr var = gSavedSettings.getControl(control_name); if (var) @@ -590,7 +591,7 @@ void LLKeyConflictHandler::resetToDefaultAndResolve(const std::string &control_n { return; } - if (mLoadMode == MODE_GENERAL) + if (mLoadMode == MODE_SAVED_SETTINGS) { LLControlVariablePtr var = gSavedSettings.getControl(control_name); if (var) @@ -639,7 +640,7 @@ void LLKeyConflictHandler::resetToDefault(const std::string &control_name) void LLKeyConflictHandler::resetToDefaults(ESourceMode mode) { - if (mode == MODE_GENERAL) + if (mode == MODE_SAVED_SETTINGS) { control_map_t::iterator iter = mControlsMap.begin(); control_map_t::iterator end = mControlsMap.end(); -- cgit v1.2.3 From 13a25be08f0c81a759076907d7950baf4f2c3ef2 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 3 Oct 2019 19:46:12 +0300 Subject: SL-6109 Better menu accelerator support and slight reorganization --- indra/newview/llkeyconflict.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 01230ea26a..bad4e4a2d8 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -38,6 +38,7 @@ #include "llkeyboard.h" #include "llviewercontrol.h" #include "llviewerinput.h" +#include "llviewermenu.h" #include "llxuiparser.h" //#include "llstring.h" @@ -170,6 +171,22 @@ bool LLKeyConflictHandler::canAssignControl(const std::string &control_name) return true; } +// static +bool LLKeyConflictHandler::isReservedByMenu(const KEY &key, const MASK &mask) +{ + return gMenuBarView->hasAccelerator(key, mask) || gLoginMenuBarView->hasAccelerator(key, mask); +} + +// static +bool LLKeyConflictHandler::isReservedByMenu(const LLKeyData &data) +{ + if (data.mMouse != CLICK_NONE) + { + return false; + } + return gMenuBarView->hasAccelerator(data.mKey, data.mMask) || gLoginMenuBarView->hasAccelerator(data.mKey, data.mMask); +} + bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask) { if (control_name.empty()) @@ -186,6 +203,10 @@ bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 { return true; } + if (isReservedByMenu(data)) + { + return false; + } if (removeConflicts(data, type_data.mConflictMask)) { type_data.mKeyBind.replaceKeyData(data, index); -- cgit v1.2.3 From e211372923bed31e632bc9825913d3d57cdc2d52 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 3 Oct 2019 22:45:29 +0300 Subject: SL-6109 Remade 'ignore' list processing, renamed and reformed keybindings --- indra/newview/llkeyconflict.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index bad4e4a2d8..0b9aaea478 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -243,10 +243,6 @@ std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata) { result = LLKeyboard::stringFromAccelerator(keydata.mMask); } - else if (keydata.mIgnoreMasks) - { - result = "acc+"; - } result += string_from_mouse(keydata.mMouse); @@ -283,7 +279,6 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymod 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; @@ -297,7 +292,7 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymod // might not know all the commands, so UI will have to know what to fill by its own LLKeyConflict &type_data = (*destination)[it->command]; type_data.mAssignable = true; - type_data.mKeyBind.addKeyData(mouse, key, mask, ignore); + type_data.mKeyBind.addKeyData(mouse, key, mask, true); } } @@ -380,7 +375,7 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) else { // load defaults - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "keys.xml"); + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml"); if (!loadFromSettings(load_mode, filename, &mDefaultsMap)) { LL_WARNS() << "Failed to load default settings, aborting" << LL_ENDL; @@ -388,7 +383,7 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) } // load user's - filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "keys.xml"); + filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml"); if (!gDirUtilp->fileExists(filename) || loadFromSettings(load_mode, filename, &mControlsMap)) { // mind placeholders @@ -440,7 +435,7 @@ void LLKeyConflictHandler::saveToSettings() else { // loaded full copy of original file - std::string filename = gDirUtilp->findFile("keys.xml", + std::string filename = gDirUtilp->findFile("key_bindings.xml", gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""), gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); @@ -494,7 +489,6 @@ void LLKeyConflictHandler::saveToSettings() } 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 = iter->first; mode.bindings.add(binding); } @@ -537,7 +531,7 @@ void LLKeyConflictHandler::saveToSettings() } // write back to user's xml; - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "keys.xml"); + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml"); LLXMLNodePtr output_node = new LLXMLNode("keys", false); LLXUIParser parser; @@ -708,7 +702,7 @@ void LLKeyConflictHandler::clear() void LLKeyConflictHandler::resetKeyboardBindings() { - std::string filename = gDirUtilp->findFile("keys.xml", + std::string filename = gDirUtilp->findFile("key_bindings.xml", gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""), gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); -- cgit v1.2.3 From 7cec1f3381291ffbf4cc6a07daf4a74d5af5a9ee Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Fri, 4 Oct 2019 16:20:07 +0300 Subject: SL-6109 Added default key for voice --- indra/newview/llkeyconflict.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 0b9aaea478..71ba0d37b3 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -480,6 +480,7 @@ void LLKeyConflictHandler::saveToSettings() // Still write empty LLKeyData to make sure we will maintain UI position if (data.mKey == KEY_NONE) { + // Might be better idea to be consistent and use NONE. LLViewerInput can work with both cases binding.key = ""; } else -- cgit v1.2.3 From 62214b53f09c453dc410465ba6e64a772562e6db Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 28 Oct 2019 18:27:13 +0200 Subject: SL-6109 Fixed conflict resolution issue caused by menu accelerators --- indra/newview/llkeyconflict.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 71ba0d37b3..fcf1a7953c 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -174,17 +174,23 @@ bool LLKeyConflictHandler::canAssignControl(const std::string &control_name) // static bool LLKeyConflictHandler::isReservedByMenu(const KEY &key, const MASK &mask) { - return gMenuBarView->hasAccelerator(key, mask) || gLoginMenuBarView->hasAccelerator(key, mask); + if (key == KEY_NONE) + { + return false; + } + return (gMenuBarView && gMenuBarView->hasAccelerator(key, mask)) + || (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(key, mask)); } // static bool LLKeyConflictHandler::isReservedByMenu(const LLKeyData &data) { - if (data.mMouse != CLICK_NONE) + if (data.mMouse != CLICK_NONE || data.mKey == KEY_NONE) { return false; } - return gMenuBarView->hasAccelerator(data.mKey, data.mMask) || gLoginMenuBarView->hasAccelerator(data.mKey, data.mMask); + return (gMenuBarView && gMenuBarView->hasAccelerator(data.mKey, data.mMask)) + || (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(data.mKey, data.mMask)); } bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask) -- cgit v1.2.3 From 7a14cf420397b225d53f9bb3c7544a766627cf5c Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 30 Oct 2019 20:48:54 +0200 Subject: SL-6109 Now changes are applied on the go and reverted on cancel --- indra/newview/llkeyconflict.cpp | 117 +++++++++++++++++++++++++++++++++------- 1 file changed, 99 insertions(+), 18 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index fcf1a7953c..d88038816b 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -40,10 +40,11 @@ #include "llviewerinput.h" #include "llviewermenu.h" #include "llxuiparser.h" -//#include "llstring.h" -static const std::string saved_settings_key_controls[] = { "placeholder" }; +static const std::string saved_settings_key_controls[] = { "placeholder" }; // add settings from gSavedSettings here +static const std::string filename_default = "key_bindings.xml"; +static const std::string filename_temporary = "key_bindings_tmp.xml"; // used to apply uncommited changes on the go. // LLKeyboard::stringFromMask is meant for UI and is OS dependent, // so this class uses it's own version @@ -128,18 +129,28 @@ EMouseClickType mouse_from_string(const std::string& input) // LLKeyConflictHandler +S32 LLKeyConflictHandler::sTemporaryFileUseCount = 0; + LLKeyConflictHandler::LLKeyConflictHandler() - : mHasUnsavedChanges(false) +: mHasUnsavedChanges(false), + mUsesTemporaryFile(false), + mLoadMode(MODE_COUNT) { } LLKeyConflictHandler::LLKeyConflictHandler(ESourceMode mode) - : mHasUnsavedChanges(false), +: mHasUnsavedChanges(false), + mUsesTemporaryFile(false), mLoadMode(mode) { loadFromSettings(mode); } +LLKeyConflictHandler::~LLKeyConflictHandler() +{ + clearUnsavedChanges(); +} + bool LLKeyConflictHandler::canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask) { return mControlsMap[control_name].canHandle(mouse_ind, key, mask); @@ -355,6 +366,7 @@ bool LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const } break; default: + LL_ERRS() << "Not implememted mode " << load_mode << LL_ENDL; break; } } @@ -381,7 +393,7 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) else { // load defaults - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml"); + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename_default); if (!loadFromSettings(load_mode, filename, &mDefaultsMap)) { LL_WARNS() << "Failed to load default settings, aborting" << LL_ENDL; @@ -389,7 +401,7 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) } // load user's - filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml"); + filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default); if (!gDirUtilp->fileExists(filename) || loadFromSettings(load_mode, filename, &mControlsMap)) { // mind placeholders @@ -399,7 +411,7 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) mLoadMode = load_mode; } -void LLKeyConflictHandler::saveToSettings() +void LLKeyConflictHandler::saveToSettings(bool temporary) { if (mControlsMap.empty()) { @@ -408,6 +420,8 @@ void LLKeyConflictHandler::saveToSettings() if (mLoadMode == MODE_SAVED_SETTINGS) { + // Does not support 'temporary', preferences handle that themself + // so in case of saved settings we just do not clear mHasUnsavedChanges control_map_t::iterator iter = mControlsMap.begin(); control_map_t::iterator end = mControlsMap.end(); @@ -440,10 +454,24 @@ void LLKeyConflictHandler::saveToSettings() } else { - // loaded full copy of original file - std::string filename = gDirUtilp->findFile("key_bindings.xml", - gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""), - gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + // Determine what file to load and load full copy of that file + std::string filename; + + if (temporary) + { + filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_temporary); + if (!gDirUtilp->fileExists(filename)) + { + filename.clear(); + } + } + + if (filename.empty()) + { + filename = gDirUtilp->findFile(filename_default, + gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""), + gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + } LLViewerInput::Keys keys; LLSimpleXUIParser parser; @@ -495,7 +523,16 @@ 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 + if (data.mMouse == CLICK_NONE) + { + binding.mouse.setProvided(false); + } + else + { + // set() because 'optional', for compatibility purposes + // just copy old keys.xml and rename to key_bindings.xml, it should work + binding.mouse.set(string_from_mouse(data.mMouse), true); + } binding.command = iter->first; mode.bindings.add(binding); } @@ -534,11 +571,22 @@ void LLKeyConflictHandler::saveToSettings() } break; default: + LL_ERRS() << "Not implememted mode " << mLoadMode << LL_ENDL; break; } - // write back to user's xml; - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml"); + if (temporary) + { + // write to temporary xml and use it for gViewerInput + filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_temporary); + mUsesTemporaryFile = true; + sTemporaryFileUseCount++; + } + else + { + // write back to user's xml and use it for gViewerInput + filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default); + } LLXMLNodePtr output_node = new LLXMLNode("keys", false); LLXUIParser parser; @@ -562,7 +610,11 @@ void LLKeyConflictHandler::saveToSettings() } } } - mHasUnsavedChanges = false; + + if (!temporary) + { + clearUnsavedChanges(); + } } LLKeyData LLKeyConflictHandler::getDefaultControl(const std::string &control_name, U32 index) @@ -702,17 +754,17 @@ void LLKeyConflictHandler::resetToDefaults() void LLKeyConflictHandler::clear() { - mHasUnsavedChanges = false; + clearUnsavedChanges(); mControlsMap.clear(); mDefaultsMap.clear(); } void LLKeyConflictHandler::resetKeyboardBindings() { - std::string filename = gDirUtilp->findFile("key_bindings.xml", + std::string filename = gDirUtilp->findFile(filename_default, gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""), gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - + gViewerInput.loadBindingsXML(filename); } @@ -773,3 +825,32 @@ void LLKeyConflictHandler::registerTemporaryControl(const std::string &control_n type_data->mKeyBind.addKeyData(mouse, key, mask, false); } +void LLKeyConflictHandler::clearUnsavedChanges() +{ + mHasUnsavedChanges = false; + + if (mUsesTemporaryFile) + { + mUsesTemporaryFile = false; + sTemporaryFileUseCount--; + if (!sTemporaryFileUseCount) + { + clearTemporaryFile(); + } + // else: might be usefull to overwrite content of temp file with defaults + // but at the moment there is no such need + } +} + +//static +void LLKeyConflictHandler::clearTemporaryFile() +{ + // At the moment single file needs five handlers (one per mode), so doing this + // will remove file for all hadlers + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_temporary); + if (gDirUtilp->fileExists(filename)) + { + LLFile::remove(filename); + } +} + -- cgit v1.2.3 From b5b266c4d2bdf71d89f5d2545e7d6e7966082c90 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 4 Nov 2019 15:48:45 +0200 Subject: SL-6109 - Fixed defaults not restoring reliably - Fixed temporary changes not lifting reliably - Fixed switching modes was dropping changes to mode we switch to --- indra/newview/llkeyconflict.cpp | 47 +++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 11 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index d88038816b..d9c2b3d53a 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -149,6 +149,7 @@ LLKeyConflictHandler::LLKeyConflictHandler(ESourceMode mode) LLKeyConflictHandler::~LLKeyConflictHandler() { clearUnsavedChanges(); + // Note: does not reset bindings if temporary file was used } bool LLKeyConflictHandler::canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask) @@ -579,13 +580,17 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) { // write to temporary xml and use it for gViewerInput filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_temporary); - mUsesTemporaryFile = true; - sTemporaryFileUseCount++; + if (!mUsesTemporaryFile) + { + mUsesTemporaryFile = true; + sTemporaryFileUseCount++; + } } else { // write back to user's xml and use it for gViewerInput filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default); + // Don't reset mUsesTemporaryFile, it will be reset at cleanup stage } LLXMLNodePtr output_node = new LLXMLNode("keys", false); @@ -606,6 +611,10 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) // Now force a rebind for keyboard if (gDirUtilp->fileExists(filename)) { + // Ideally instead of rebinding immediately we should shedule + // the rebind since single file can have multiple handlers, + // one per mode, saving simultaneously. + // Or whatever uses LLKeyConflictHandler should control the process. gViewerInput.loadBindingsXML(filename); } } @@ -613,6 +622,7 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) if (!temporary) { + // will remove any temporary file if there were any clearUnsavedChanges(); } } @@ -754,18 +764,29 @@ void LLKeyConflictHandler::resetToDefaults() void LLKeyConflictHandler::clear() { - clearUnsavedChanges(); + if (clearUnsavedChanges()) + { + // temporary file was removed, this means we were using it and need to reload keyboard's bindings + resetKeyboardBindings(); + } mControlsMap.clear(); mDefaultsMap.clear(); } +// static void LLKeyConflictHandler::resetKeyboardBindings() { - std::string filename = gDirUtilp->findFile(filename_default, - gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""), - gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - - gViewerInput.loadBindingsXML(filename); + // Try to load User's bindings first + std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default); + if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file)) + { + // Failed to load custom bindings, try default ones + key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename_default); + if (!gViewerInput.loadBindingsXML(key_bindings_file)) + { + LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL; + } + } } void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) @@ -825,8 +846,9 @@ void LLKeyConflictHandler::registerTemporaryControl(const std::string &control_n type_data->mKeyBind.addKeyData(mouse, key, mask, false); } -void LLKeyConflictHandler::clearUnsavedChanges() +bool LLKeyConflictHandler::clearUnsavedChanges() { + bool result = false; mHasUnsavedChanges = false; if (mUsesTemporaryFile) @@ -835,15 +857,16 @@ void LLKeyConflictHandler::clearUnsavedChanges() sTemporaryFileUseCount--; if (!sTemporaryFileUseCount) { - clearTemporaryFile(); + result = clearTemporaryFile(); } // else: might be usefull to overwrite content of temp file with defaults // but at the moment there is no such need } + return result; } //static -void LLKeyConflictHandler::clearTemporaryFile() +bool LLKeyConflictHandler::clearTemporaryFile() { // At the moment single file needs five handlers (one per mode), so doing this // will remove file for all hadlers @@ -851,6 +874,8 @@ void LLKeyConflictHandler::clearTemporaryFile() if (gDirUtilp->fileExists(filename)) { LLFile::remove(filename); + return true; } + return false; } -- cgit v1.2.3 From 73a1877ff0abcba46f66ef55440274119427723b Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 7 Nov 2019 20:09:25 +0200 Subject: SL-6109 - Edit mode appears to be obsolete and is not used, cleaned up - Improved ability to set defaults - Improved some labels - Made buttons bigger to accomodate languages with longer descriptions - Added ability to assign key for all modes simultaneously --- indra/newview/llkeyconflict.cpp | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index d9c2b3d53a..b4f5ec4d57 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -345,13 +345,6 @@ bool LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const res = true; } break; - case MODE_EDIT: - if (keys.edit.isProvided()) - { - loadFromSettings(keys.edit, destination); - res = true; - } - break; case MODE_EDIT_AVATAR: if (keys.edit_avatar.isProvided()) { @@ -553,12 +546,6 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) keys.third_person.bindings.set(mode.bindings, true); } break; - case MODE_EDIT: - if (keys.edit.isProvided()) - { - keys.edit.bindings.set(mode.bindings, true); - } - break; case MODE_EDIT_AVATAR: if (keys.edit_avatar.isProvided()) { -- cgit v1.2.3 From 9b218acc351cdd2eb06a9f87951314e0eb34daa9 Mon Sep 17 00:00:00 2001 From: Ansariel Hiller Date: Sat, 9 Nov 2019 15:06:09 +0000 Subject: Fix custom user keybindings not being displayed in preferences correctly --- indra/newview/llkeyconflict.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index b4f5ec4d57..121965a388 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -124,6 +124,10 @@ EMouseClickType mouse_from_string(const std::string& input) { return CLICK_BUTTON5; } + if (input == "Double LMB") + { + return CLICK_DOUBLELEFT; + } return CLICK_NONE; } @@ -396,7 +400,7 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) // load user's filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default); - if (!gDirUtilp->fileExists(filename) || loadFromSettings(load_mode, filename, &mControlsMap)) + if (!gDirUtilp->fileExists(filename) || !loadFromSettings(load_mode, filename, &mControlsMap)) { // mind placeholders mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end()); -- cgit v1.2.3 From 5568018bd20a43c30caca0c6288e63bfae29a2e3 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Sun, 10 Nov 2019 19:06:03 +0200 Subject: SL-6109 Better key and table localization support and fix for key-replacing --- indra/newview/llkeyconflict.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 121965a388..882a1d0caf 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -517,8 +517,7 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) } else { - // Note: this is UI string, we might want to hardcode our own for 'fixed' use in keys.xml - binding.key = LLKeyboard::stringFromKey(data.mKey); + binding.key = LLKeyboard::stringFromKey(data.mKey, false /*Do not localize*/); } binding.mask = string_from_mask(data.mMask); if (data.mMouse == CLICK_NONE) -- cgit v1.2.3 From 708fdb4e67393dbf03a0e0c82608d62f1868926a Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Tue, 12 Nov 2019 14:08:01 +0200 Subject: SL-6109 Mouse localization support --- indra/newview/llkeyconflict.cpp | 43 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 31 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 882a1d0caf..a94836c59d 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -36,6 +36,7 @@ #include "llinitparam.h" #include "llkeyboard.h" +#include "lltrans.h" #include "llviewercontrol.h" #include "llviewerinput.h" #include "llviewermenu.h" @@ -73,7 +74,7 @@ std::string string_from_mask(MASK mask) return res; } -std::string string_from_mouse(EMouseClickType click) +std::string string_from_mouse(EMouseClickType click, bool translate) { std::string res; switch (click) @@ -99,36 +100,12 @@ std::string string_from_mouse(EMouseClickType click) 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; - } - if (input == "Double LMB") + if (translate && !res.empty()) { - return CLICK_DOUBLELEFT; + res = LLTrans::getString(res); } - return CLICK_NONE; + return res; } // LLKeyConflictHandler @@ -266,7 +243,7 @@ std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata) result = LLKeyboard::stringFromAccelerator(keydata.mMask); } - result += string_from_mouse(keydata.mMouse); + result += string_from_mouse(keydata.mMouse, true); return result; } @@ -300,7 +277,11 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymod { KEY key; MASK mask; - EMouseClickType mouse = it->mouse.isProvided() ? mouse_from_string(it->mouse) : CLICK_NONE; + EMouseClickType mouse = CLICK_NONE; + if (it->mouse.isProvided()) + { + LLViewerInput::mouseFromString(it->mouse.getValue(), &mouse); + } if (it->key.getValue().empty()) { key = KEY_NONE; @@ -528,7 +509,7 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) { // set() because 'optional', for compatibility purposes // just copy old keys.xml and rename to key_bindings.xml, it should work - binding.mouse.set(string_from_mouse(data.mMouse), true); + binding.mouse.set(string_from_mouse(data.mMouse, false), true); } binding.command = iter->first; mode.bindings.add(binding); -- cgit v1.2.3 From 629cd92c47e90a1fb8711c46bd406476d01e9b9b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 12 Jun 2020 18:51:13 +0300 Subject: SL-13421 Removed camera control keybindings from mouselook --- indra/newview/llkeyconflict.cpp | 51 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index a94836c59d..be774e7765 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -160,7 +160,7 @@ bool LLKeyConflictHandler::canAssignControl(const std::string &control_name) { return iter->second.mAssignable; } - // If we don't know this control means it wasn't assigned by user yet and thus is editable + // If we don't know this control, means it wasn't assigned by user yet and thus is editable return true; } @@ -195,7 +195,8 @@ bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 LLKeyConflict &type_data = mControlsMap[control_name]; if (!type_data.mAssignable) { - LL_ERRS() << "Error in code, user or system should not be able to change certain controls" << LL_ENDL; + // Example: user tried to assign camera spin to all modes, but first person mode doesn't support it + return false; } LLKeyData data(mouse, key, mask, ignore_mask); if (type_data.mKeyBind.getKeyData(index) == data) @@ -764,8 +765,43 @@ void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) { // These controls are meant to cause conflicts 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 - /*registerTemporaryControl(CONTROL_RESERVED_MENU, CLICK_RIGHT, KEY_NONE, MASK_NONE, 0); - registerTemporaryControl(CONTROL_DELETE, CLICK_NONE, KEY_DELETE, MASK_NONE, 0);*/ + + if (load_mode == MODE_FIRST_PERSON) + { + // First person view doesn't support camera controls + // Note: might be better idea to just load these from control_table_contents_camera.xml + // or to pass from floaterpreferences when it loads said file + registerTemporaryControl("look_up"); + registerTemporaryControl("look_down"); + registerTemporaryControl("move_forward"); + registerTemporaryControl("move_backward"); + registerTemporaryControl("move_forward_fast"); + registerTemporaryControl("move_backward_fast"); + registerTemporaryControl("move_forward_sitting"); + registerTemporaryControl("move_backward_sitting"); + registerTemporaryControl("spin_over"); + registerTemporaryControl("spin_under"); + registerTemporaryControl("spin_over_sitting"); + registerTemporaryControl("spin_under_sitting"); + registerTemporaryControl("pan_up"); + registerTemporaryControl("pan_down"); + registerTemporaryControl("pan_left"); + registerTemporaryControl("pan_right"); + registerTemporaryControl("pan_in"); + registerTemporaryControl("pan_out"); + registerTemporaryControl("spin_around_ccw"); + registerTemporaryControl("spin_around_cw"); + registerTemporaryControl("spin_around_ccw_sitting"); + registerTemporaryControl("spin_around_cw_sitting"); + + // control_table_contents_editing.xml + registerTemporaryControl("edit_avatar_spin_ccw"); + registerTemporaryControl("edit_avatar_spin_cw"); + registerTemporaryControl("edit_avatar_spin_over"); + registerTemporaryControl("edit_avatar_spin_under"); + registerTemporaryControl("edit_avatar_move_forward"); + registerTemporaryControl("edit_avatar_move_backward"); + } } bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &conlict_mask) @@ -817,6 +853,13 @@ void LLKeyConflictHandler::registerTemporaryControl(const std::string &control_n type_data->mKeyBind.addKeyData(mouse, key, mask, false); } +void LLKeyConflictHandler::registerTemporaryControl(const std::string &control_name) +{ + LLKeyConflict *type_data = &mControlsMap[control_name]; + type_data->mAssignable = false; + type_data->mConflictMask = 0; +} + bool LLKeyConflictHandler::clearUnsavedChanges() { bool result = false; -- cgit v1.2.3 From c604b274fb4ab218a89fc03a4ea5cc1b739ad65f Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 12 Jun 2020 20:09:43 +0300 Subject: SL-13421 Separated some sitting-exclusive controls --- indra/newview/llkeyconflict.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index be774e7765..e44f79000e 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -294,8 +294,9 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymod LLKeyboard::maskFromString(it->mask, &mask); // Note: it->command is also the name of UI element, howhever xml we are loading from // might not know all the commands, so UI will have to know what to fill by its own + // Assumes U32_MAX conflict mask, and is assignable by default, + // but assignability might have been overriden by generatePlaceholders. LLKeyConflict &type_data = (*destination)[it->command]; - type_data.mAssignable = true; type_data.mKeyBind.addKeyData(mouse, key, mask, true); } } @@ -777,12 +778,8 @@ void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) registerTemporaryControl("move_backward"); registerTemporaryControl("move_forward_fast"); registerTemporaryControl("move_backward_fast"); - registerTemporaryControl("move_forward_sitting"); - registerTemporaryControl("move_backward_sitting"); registerTemporaryControl("spin_over"); registerTemporaryControl("spin_under"); - registerTemporaryControl("spin_over_sitting"); - registerTemporaryControl("spin_under_sitting"); registerTemporaryControl("pan_up"); registerTemporaryControl("pan_down"); registerTemporaryControl("pan_left"); @@ -791,8 +788,6 @@ void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) registerTemporaryControl("pan_out"); registerTemporaryControl("spin_around_ccw"); registerTemporaryControl("spin_around_cw"); - registerTemporaryControl("spin_around_ccw_sitting"); - registerTemporaryControl("spin_around_cw_sitting"); // control_table_contents_editing.xml registerTemporaryControl("edit_avatar_spin_ccw"); @@ -802,6 +797,16 @@ void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) registerTemporaryControl("edit_avatar_move_forward"); registerTemporaryControl("edit_avatar_move_backward"); } + + if (load_mode != MODE_SITTING) + { + registerTemporaryControl("move_forward_sitting"); + registerTemporaryControl("move_backward_sitting"); + registerTemporaryControl("spin_over_sitting"); + registerTemporaryControl("spin_under_sitting"); + registerTemporaryControl("spin_around_ccw_sitting"); + registerTemporaryControl("spin_around_cw_sitting"); + } } bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &conlict_mask) @@ -853,11 +858,11 @@ void LLKeyConflictHandler::registerTemporaryControl(const std::string &control_n type_data->mKeyBind.addKeyData(mouse, key, mask, false); } -void LLKeyConflictHandler::registerTemporaryControl(const std::string &control_name) +void LLKeyConflictHandler::registerTemporaryControl(const std::string &control_name, U32 conflict_mask) { LLKeyConflict *type_data = &mControlsMap[control_name]; type_data->mAssignable = false; - type_data->mConflictMask = 0; + type_data->mConflictMask = conflict_mask; } bool LLKeyConflictHandler::clearUnsavedChanges() -- cgit v1.2.3 From 6092e2ffab9ec76bdd8821e188db9cb785456eee Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 15 Jun 2020 18:13:46 +0300 Subject: SL-13418 Added converter from old mouse binding settings to new ones --- indra/newview/llkeyconflict.cpp | 67 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index e44f79000e..5f966624ca 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -427,7 +427,7 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) else if (!key.mKeyBind.empty()) { // Note: this is currently not in use, might be better for load mechanics to ask for and retain control group - // otherwise settings loaded from other control groups will end in this one + // otherwise settings loaded from other control groups will end in gSavedSettings LL_INFOS() << "Creating new keybinding " << iter->first << LL_ENDL; gSavedSettings.declareLLSD(iter->first, key.mKeyBind.asLLSD(), "comment", LLControlVariable::PERSIST_ALWAYS); } @@ -598,6 +598,71 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) // will remove any temporary file if there were any clearUnsavedChanges(); } + +#if 1 + // Legacy support + // Remove #if-#endif section half a year after DRTVWR-501 releases. + // Update legacy settings in settings.xml + // We only care for third person view since legacy settings can't store + // more than one mode. + // We are saving this even if we are in temporary mode - preferences + // will restore values on cancel + if (mLoadMode == MODE_THIRD_PERSON) + { + bool value = canHandleMouse("walk_to", CLICK_DOUBLELEFT, MASK_NONE); + gSavedSettings.setBOOL("DoubleClickAutoPilot", value); + + value = canHandleMouse("walk_to", CLICK_LEFT, MASK_NONE); + gSavedSettings.setBOOL("ClickToWalk", value); + + value = canHandleMouse("teleport_to", CLICK_DOUBLELEFT, MASK_NONE); + gSavedSettings.setBOOL("DoubleClickTeleport", value); + + // new method can save both toggle and push-to-talk values simultaneously, + // but legacy one can save only one. It also doesn't support mask. + LLKeyData data = getControl("toggle_voice", 0); + bool can_toggle = !data.isEmpty(); + if (!can_toggle) + { + data = getControl("voice_follow_key", 0); + } + + gSavedSettings.setBOOL("PushToTalkToggle", can_toggle); + if (data.isEmpty()) + { + // legacy viewer has a bug that might crash it if NONE value is assigned. + // just reset to default + gSavedSettings.getControl("PushToTalkButton")->resetToDefault(false); + } + else + { + if (data.mKey != KEY_NONE) + { + gSavedSettings.setString("PushToTalkButton", LLKeyboard::stringFromKey(data.mKey)); + } + else + { + std::string ctrl_value; + switch (data.mMouse) + { + case CLICK_MIDDLE: + ctrl_value = "MiddleMouse"; + break; + case CLICK_BUTTON4: + ctrl_value = "MouseButton4"; + break; + case CLICK_BUTTON5: + ctrl_value = "MouseButton5"; + break; + default: + ctrl_value = "MiddleMouse"; + break; + } + gSavedSettings.setString("PushToTalkButton", ctrl_value); + } + } + } +#endif } LLKeyData LLKeyConflictHandler::getDefaultControl(const std::string &control_name, U32 index) -- cgit v1.2.3 From e578491be761fefa34e4041458e2cf5badc81873 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 15 Jun 2020 20:35:58 +0300 Subject: SL-13418 Restored previously removed 'click on land' controls from 'move & view' According to UX UI engineer. Also adapted it to new system, but it needs a better solution. --- indra/newview/llkeyconflict.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 5f966624ca..b426dc14fc 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -217,6 +217,22 @@ bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 return false; } +bool LLKeyConflictHandler::clearControl(const std::string &control_name, U32 data_index) +{ + if (control_name.empty()) + { + return false; + } + LLKeyConflict &type_data = mControlsMap[control_name]; + if (!type_data.mAssignable) + { + // Example: user tried to assign camera spin to all modes, but first person mode doesn't support it + return false; + } + type_data.mKeyBind.resetKeyData(data_index); + return true; +} + LLKeyData LLKeyConflictHandler::getControl(const std::string &control_name, U32 index) { if (control_name.empty()) -- cgit v1.2.3 From 74aba5768e62f2260ac44c5244145a0a689bf3d5 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 16 Jun 2020 09:27:41 +0300 Subject: SL-13418 Move and view panel now applies changes on the go --- indra/newview/llkeyconflict.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index b426dc14fc..4c055fcee6 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -230,6 +230,7 @@ bool LLKeyConflictHandler::clearControl(const std::string &control_name, U32 dat return false; } type_data.mKeyBind.resetKeyData(data_index); + mHasUnsavedChanges = true; return true; } -- cgit v1.2.3 From df306eec5b9479dac72418bdd8c42a4f328e4f2b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 17 Jun 2020 01:22:16 +0300 Subject: SL-13418 Restored original default value for DoubleClickTeleport --- indra/newview/llkeyconflict.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 4c055fcee6..8ee50d5c52 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -610,12 +610,6 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) } } - if (!temporary) - { - // will remove any temporary file if there were any - clearUnsavedChanges(); - } - #if 1 // Legacy support // Remove #if-#endif section half a year after DRTVWR-501 releases. @@ -624,7 +618,7 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) // more than one mode. // We are saving this even if we are in temporary mode - preferences // will restore values on cancel - if (mLoadMode == MODE_THIRD_PERSON) + if (mLoadMode == MODE_THIRD_PERSON && mHasUnsavedChanges) { bool value = canHandleMouse("walk_to", CLICK_DOUBLELEFT, MASK_NONE); gSavedSettings.setBOOL("DoubleClickAutoPilot", value); @@ -632,9 +626,6 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) value = canHandleMouse("walk_to", CLICK_LEFT, MASK_NONE); gSavedSettings.setBOOL("ClickToWalk", value); - value = canHandleMouse("teleport_to", CLICK_DOUBLELEFT, MASK_NONE); - gSavedSettings.setBOOL("DoubleClickTeleport", value); - // new method can save both toggle and push-to-talk values simultaneously, // but legacy one can save only one. It also doesn't support mask. LLKeyData data = getControl("toggle_voice", 0); @@ -680,6 +671,22 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) } } #endif + + if (mLoadMode == MODE_THIRD_PERSON && mHasUnsavedChanges) + { + // Map floater should react to doubleclick if doubleclick for teleport is set + // Todo: Seems conterintuitive for map floater to share inworld controls + // after these changes release, discuss with UI UX engineer if this should just + // be set to 1 by default (before release this also doubles as legacy support) + bool value = canHandleMouse("teleport_to", CLICK_DOUBLELEFT, MASK_NONE); + gSavedSettings.setBOOL("DoubleClickTeleport", value); + } + + if (!temporary) + { + // will remove any temporary file if there were any + clearUnsavedChanges(); + } } LLKeyData LLKeyConflictHandler::getDefaultControl(const std::string &control_name, U32 index) -- cgit v1.2.3 From 7717097f7cfa1deaa934b9846c22523f53c600d3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 23 Jun 2020 20:29:00 +0300 Subject: SL-6109 Teleport and autopilot should not work in some cases Hides teleport_to and walk_to also optimizes couple things. --- indra/newview/llkeyconflict.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'indra/newview/llkeyconflict.cpp') diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 8ee50d5c52..b6107eeedf 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -243,6 +243,15 @@ LLKeyData LLKeyConflictHandler::getControl(const std::string &control_name, U32 return mControlsMap[control_name].getKeyData(index); } +bool LLKeyConflictHandler::isControlEmpty(const std::string &control_name) +{ + if (control_name.empty()) + { + return true; + } + return mControlsMap[control_name].mKeyBind.isEmpty(); +} + // static std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata) { @@ -885,10 +894,27 @@ void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) registerTemporaryControl("edit_avatar_spin_under"); registerTemporaryControl("edit_avatar_move_forward"); registerTemporaryControl("edit_avatar_move_backward"); + + // no autopilot or teleport + registerTemporaryControl("walk_to"); + registerTemporaryControl("teleport_to"); + } + + if (load_mode == MODE_EDIT_AVATAR) + { + // no autopilot or teleport + registerTemporaryControl("walk_to"); + registerTemporaryControl("teleport_to"); } - if (load_mode != MODE_SITTING) + if (load_mode == MODE_SITTING) + { + // no autopilot + registerTemporaryControl("walk_to"); + } + else { + // sitting related functions should only be avaliable in sitting mode registerTemporaryControl("move_forward_sitting"); registerTemporaryControl("move_backward_sitting"); registerTemporaryControl("spin_over_sitting"); -- cgit v1.2.3