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/llsetkeybinddialog.cpp | 298 +++++++++++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 indra/newview/llsetkeybinddialog.cpp (limited to 'indra/newview/llsetkeybinddialog.cpp') diff --git a/indra/newview/llsetkeybinddialog.cpp b/indra/newview/llsetkeybinddialog.cpp new file mode 100644 index 0000000000..0ad71cb372 --- /dev/null +++ b/indra/newview/llsetkeybinddialog.cpp @@ -0,0 +1,298 @@ +/** + * @file llsetkeybinddialog.cpp + * @brief LLSetKeyBindDialog class implementation. + * + * $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$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llsetkeybinddialog.h" + +//#include "llkeyboard.h" + +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "lleventtimer.h" +#include "llfocusmgr.h" + +class LLSetKeyBindDialog::Updater : public LLEventTimer +{ +public: + + typedef boost::function callback_t; + + Updater(callback_t cb, F32 period, MASK mask) + :LLEventTimer(period), + mMask(mask), + mCallback(cb) + { + mEventTimer.start(); + } + + virtual ~Updater(){} + +protected: + BOOL tick() + { + mCallback(mMask); + // Deletes itseft after execution + return TRUE; + } + +private: + MASK mMask; + callback_t mCallback; +}; + +LLSetKeyBindDialog::LLSetKeyBindDialog(const LLSD& key) + : LLModalDialog(key), + pParent(NULL), + mKeyFilterMask(DEFAULT_KEY_FILTER), + pUpdater(NULL) +{ +} + +LLSetKeyBindDialog::~LLSetKeyBindDialog() +{ +} + +//virtual +BOOL LLSetKeyBindDialog::postBuild() +{ + childSetAction("SetEmpty", onBlank, this); + childSetAction("Default", onDefault, this); + childSetAction("Cancel", onCancel, this); + getChild("Cancel")->setFocus(TRUE); + + pCheckBox = getChild("ignore_masks"); + + gFocusMgr.setKeystrokesOnly(TRUE); + + return TRUE; +} + +//virtual +void LLSetKeyBindDialog::onClose(bool app_quiting) +{ + if (pParent) + { + pParent->onCancelKeyBind(); + pParent = NULL; + } + if (pUpdater) + { + // Doubleclick timer has't fired, delete it + delete pUpdater; + pUpdater = NULL; + } + LLModalDialog::onClose(app_quiting); +} + +//virtual +void LLSetKeyBindDialog::draw() +{ + LLRect local_rect; + drawFrustum(local_rect, this, (LLView*)getDragHandle(), hasFocus()); + LLModalDialog::draw(); +} + +void LLSetKeyBindDialog::setParent(LLPanelPreferenceControls* parent, U32 key_mask) +{ + pParent = parent; + setFrustumOrigin(parent); + mKeyFilterMask = key_mask; + + LLTextBase *text_ctrl = getChild("descritption"); + + std::string input; + if ((key_mask & ALLOW_MOUSE) != 0) + { + input = getString("mouse"); + } + if ((key_mask & ALLOW_KEYS) != 0) + { + if (!input.empty()) + { + input += ", "; + } + input += getString("keyboard"); + } + text_ctrl->setTextArg("[INPUT]", input); + + bool can_ignore_masks = (key_mask & CAN_IGNORE_MASKS) != 0; + pCheckBox->setVisible(can_ignore_masks); + pCheckBox->setValue(false); +} + +BOOL LLSetKeyBindDialog::handleKeyHere(KEY key, MASK mask) +{ + if ((key == 'Q' && mask == MASK_CONTROL) + || key == KEY_ESCAPE) + { + closeFloater(); + return TRUE; + } + + if (key == KEY_DELETE) + { + setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false); + closeFloater(); + return FALSE; + } + + // forbidden keys + if (key == KEY_NONE + || key == KEY_RETURN + || key == KEY_BACKSPACE) + { + return FALSE; + } + + if ((mKeyFilterMask & ALLOW_MASKS) == 0 + && (key == KEY_CONTROL || key == KEY_SHIFT || key == KEY_ALT)) + { + // mask by themself are not allowed + return FALSE; + } + else if ((mKeyFilterMask & ALLOW_KEYS) == 0) + { + // basic keys not allowed + return FALSE; + } + else if ((mKeyFilterMask & ALLOW_MASK_KEYS) == 0 && mask != 0) + { + // masked keys not allowed + return FALSE; + } + + setKeyBind(CLICK_NONE, key, mask, pCheckBox->getValue().asBoolean()); + closeFloater(); + return TRUE; +} + +BOOL LLSetKeyBindDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down) +{ + BOOL result = FALSE; + if (!pParent) + { + // we already processed 'down' event, this is 'up', consume + closeFloater(); + result = TRUE; + } + if (!result && clicktype == CLICK_LEFT) + { + // try handling buttons first + if (down) + { + result = LLView::handleMouseDown(x, y, mask); + } + else + { + result = LLView::handleMouseUp(x, y, mask); + } + if (result) + { + setFocus(TRUE); + gFocusMgr.setKeystrokesOnly(TRUE); + } + // ignore selection related combinations + else if (down && (mask & (MASK_SHIFT | MASK_CONTROL)) == 0) + { + // this can be a double click, wait a bit; + if (!pUpdater) + { + // Note: default doubleclick time is 500ms, but can stretch up to 5s + pUpdater = new Updater(boost::bind(&onClickTimeout, this, _1), 0.7f, mask); + result = TRUE; + } + } + } + + if (!result + && (clicktype != CLICK_LEFT) // subcases were handled above + && ((mKeyFilterMask & ALLOW_MOUSE) != 0) + && (clicktype != CLICK_RIGHT || mask != 0) // reassigning menu button is not supported + && ((mKeyFilterMask & ALLOW_MASK_MOUSE) != 0 || mask == 0)) // reserved for selection + { + setKeyBind(clicktype, KEY_NONE, mask, pCheckBox->getValue().asBoolean()); + result = TRUE; + if (!down) + { + // wait for 'up' event before closing + // alternative: set pUpdater + closeFloater(); + } + } + + return result; +} + +//static +void LLSetKeyBindDialog::onCancel(void* user_data) +{ + LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data; + self->closeFloater(); +} + +//static +void LLSetKeyBindDialog::onBlank(void* user_data) +{ + LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data; + // tmp needs 'no key' button + self->setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false); + self->closeFloater(); +} + +//static +void LLSetKeyBindDialog::onDefault(void* user_data) +{ + LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data; + if (self->pParent) + { + self->pParent->onDefaultKeyBind(); + self->pParent = NULL; + } + self->closeFloater(); +} + +//static +void LLSetKeyBindDialog::onClickTimeout(void* user_data, MASK mask) +{ + LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data; + + // timer will delete itself after timeout + self->pUpdater = NULL; + + self->setKeyBind(CLICK_LEFT, KEY_NONE, mask, self->pCheckBox->getValue().asBoolean()); + self->closeFloater(); +} + +void LLSetKeyBindDialog::setKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore) +{ + if (pParent) + { + pParent->onSetKeyBind(click, key, mask, ignore); + pParent = NULL; + } +} + -- cgit v1.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/llcommon/llkeybind.cpp | 9 +- indra/llcommon/llkeybind.h | 3 +- indra/llui/llscrolllistcell.h | 2 +- indra/newview/CMakeLists.txt | 2 +- indra/newview/app_settings/key_bindings.xml | 302 +++++++++++++++++ indra/newview/app_settings/keys.xml | 363 --------------------- indra/newview/llappviewer.cpp | 4 +- indra/newview/llfloaterpreference.cpp | 20 +- indra/newview/llfloaterpreference.h | 8 +- indra/newview/llkeyconflict.cpp | 18 +- indra/newview/llpanelpresetspulldown.cpp | 1 + indra/newview/llsetkeybinddialog.cpp | 18 +- indra/newview/llsetkeybinddialog.h | 18 +- indra/newview/llviewerinput.cpp | 164 ++++------ indra/newview/llviewerinput.h | 28 +- .../default/xui/en/control_table_contents.xml | 14 +- .../skins/default/xui/en/floater_select_key.xml | 15 +- 17 files changed, 445 insertions(+), 544 deletions(-) create mode 100644 indra/newview/app_settings/key_bindings.xml delete mode 100644 indra/newview/app_settings/keys.xml (limited to 'indra/newview/llsetkeybinddialog.cpp') diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp index ff88a9c9aa..46a3230240 100644 --- a/indra/llcommon/llkeybind.cpp +++ b/indra/llcommon/llkeybind.cpp @@ -92,14 +92,11 @@ LLSD LLKeyData::asLLSD() const LLSD data; data["mouse"] = (LLSD::Integer)mMouse; data["key"] = (LLSD::Integer)mKey; + data["mask"] = (LLSD::Integer)mMask; if (mIgnoreMasks) { data["ignore_accelerators"] = (LLSD::Boolean)mIgnoreMasks; } - else - { - data["mask"] = (LLSD::Integer)mMask; - } return data; } @@ -147,7 +144,7 @@ bool LLKeyData::canHandle(const LLKeyData& data) const { if (data.mKey == mKey && data.mMouse == mMouse - && (mIgnoreMasks || data.mMask == mMask)) + && ((mIgnoreMasks && (data.mMask & mMask) == data.mMask) || data.mMask == mMask)) { return true; } @@ -158,7 +155,7 @@ bool LLKeyData::canHandle(EMouseClickType mouse, KEY key, MASK mask) const { if (mouse == mMouse && key == mKey - && (mIgnoreMasks || mask == mMask)) + && ((mIgnoreMasks && (mask & mMask) == mask) || mask == mMask)) { return true; } diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h index 39cb668aac..ad0ebec67c 100644 --- a/indra/llcommon/llkeybind.h +++ b/indra/llcommon/llkeybind.h @@ -53,7 +53,8 @@ public: EMouseClickType mMouse; KEY mKey; MASK mMask; - bool mIgnoreMasks; + // Either to expect exact match or ignore not expected masks + bool mIgnoreMasks; }; // One function can bind to multiple Key options diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h index ef7f717b57..19576fb247 100644 --- a/indra/llui/llscrolllistcell.h +++ b/indra/llui/llscrolllistcell.h @@ -70,7 +70,7 @@ public: Optional color; Params() - : type("cell_type", "text"), // Don't use "type", it overlaps with xml's parameter + : type("type", "text"), column("column"), width("width"), enabled("enabled", true), diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 111aefe186..b8fa60ddcb 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1671,7 +1671,7 @@ set(viewer_APPSETTINGS_FILES app_settings/grass.xml app_settings/high_graphics.xml app_settings/ignorable_dialogs.xml - app_settings/keys.xml + app_settings/key_bindings.xml app_settings/keywords_lsl_default.xml app_settings/logcontrol.xml app_settings/low_graphics.xml diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml new file mode 100644 index 0000000000..0c90ef26df --- /dev/null +++ b/indra/newview/app_settings/key_bindings.xml @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/indra/newview/app_settings/keys.xml b/indra/newview/app_settings/keys.xml deleted file mode 100644 index a8037fec05..0000000000 --- a/indra/newview/app_settings/keys.xml +++ /dev/null @@ -1,363 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 7145f0f29c..857cd86739 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1003,11 +1003,11 @@ bool LLAppViewer::init() gGLManager.printGLInfoString(); // Load User's bindings - std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "keys.xml"); + std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml"); 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, "keys.xml"); + key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml"); if (!gViewerInput.loadBindingsXML(key_bindings_file)) { LL_ERRS("InitInfo") << "Unable to open default key bindings from" << key_bindings_file << LL_ENDL; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index e71c7d58e2..9e1330dca7 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -2875,7 +2875,7 @@ void LLPanelPreferenceControls::onListCommit() { mEditingControl = control; mEditingColumn = cell_ind; - dialog->setParent(this, DEFAULT_KEY_FILTER); + dialog->setParent(this, pControlsTable, DEFAULT_KEY_FILTER); LLFloater* root_floater = gFloaterView->getParentFloater(this); if (root_floater) @@ -2895,6 +2895,14 @@ void LLPanelPreferenceControls::onModeCommit() regenerateControls(); } +void LLPanelPreferenceControls::onRestoreDefaults() +{ + for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i) + { + mConflictHandler[mEditingMode].resetToDefaults(); + } +} + // todo: copy onSetKeyBind to interface and inherit from interface bool LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore_mask) { @@ -2905,21 +2913,13 @@ bool LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MAS if ( mEditingColumn > 0) { - mConflictHandler[mEditingMode].registerControl(mEditingControl, mEditingColumn - 1, click, key, mask, ignore_mask); + mConflictHandler[mEditingMode].registerControl(mEditingControl, mEditingColumn - 1, click, key, mask, true); } updateTable(); return true; } -void LLPanelPreferenceControls::onRestoreDefaults() -{ - for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i) - { - mConflictHandler[mEditingMode].resetToDefaults(); - } -} - void LLPanelPreferenceControls::onDefaultKeyBind() { if (!mConflictHandler[mEditingMode].canAssignControl(mEditingControl)) diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 9c4f6fad46..8adfb79038 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -292,7 +292,7 @@ class LLPanelPreferenceControls : public LLPanelPreference, public LLKeyBindResp LOG_CLASS(LLPanelPreferenceControls); public: LLPanelPreferenceControls(); - ~LLPanelPreferenceControls(); + virtual ~LLPanelPreferenceControls(); BOOL postBuild(); @@ -303,10 +303,10 @@ public: void onListCommit(); void onModeCommit(); - bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore_mask); void onRestoreDefaults(); - void onDefaultKeyBind(); - void onCancelKeyBind(); + /*virtual*/ bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore_mask); + /*virtual*/ void onDefaultKeyBind(); + /*virtual*/ void onCancelKeyBind(); private: void regenerateControls(); 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, "")); diff --git a/indra/newview/llpanelpresetspulldown.cpp b/indra/newview/llpanelpresetspulldown.cpp index 8a3bcf7172..d52ad8056f 100644 --- a/indra/newview/llpanelpresetspulldown.cpp +++ b/indra/newview/llpanelpresetspulldown.cpp @@ -33,6 +33,7 @@ #include "llbutton.h" #include "lltabcontainer.h" +#include "llfloater.h" #include "llfloaterreg.h" #include "llpresetsmanager.h" #include "llsliderctrl.h" diff --git a/indra/newview/llsetkeybinddialog.cpp b/indra/newview/llsetkeybinddialog.cpp index 0ad71cb372..320f1f297d 100644 --- a/indra/newview/llsetkeybinddialog.cpp +++ b/indra/newview/llsetkeybinddialog.cpp @@ -34,6 +34,7 @@ #include "llcheckboxctrl.h" #include "lleventtimer.h" #include "llfocusmgr.h" +#include "llkeyconflict.h" class LLSetKeyBindDialog::Updater : public LLEventTimer { @@ -85,6 +86,7 @@ BOOL LLSetKeyBindDialog::postBuild() getChild("Cancel")->setFocus(TRUE); pCheckBox = getChild("ignore_masks"); + pDesription = getChild("descritption"); gFocusMgr.setKeystrokesOnly(TRUE); @@ -116,14 +118,12 @@ void LLSetKeyBindDialog::draw() LLModalDialog::draw(); } -void LLSetKeyBindDialog::setParent(LLPanelPreferenceControls* parent, U32 key_mask) +void LLSetKeyBindDialog::setParent(LLKeyBindResponderInterface* parent, LLView* frustum_origin, U32 key_mask) { pParent = parent; - setFrustumOrigin(parent); + setFrustumOrigin(frustum_origin); mKeyFilterMask = key_mask; - LLTextBase *text_ctrl = getChild("descritption"); - std::string input; if ((key_mask & ALLOW_MOUSE) != 0) { @@ -137,7 +137,8 @@ void LLSetKeyBindDialog::setParent(LLPanelPreferenceControls* parent, U32 key_ma } input += getString("keyboard"); } - text_ctrl->setTextArg("[INPUT]", input); + pDesription->setText(getString("basic_description")); + pDesription->setTextArg("[INPUT]", input); bool can_ignore_masks = (key_mask & CAN_IGNORE_MASKS) != 0; pCheckBox->setVisible(can_ignore_masks); @@ -185,6 +186,13 @@ BOOL LLSetKeyBindDialog::handleKeyHere(KEY key, MASK mask) return FALSE; } + if (LLKeyConflictHandler::isReservedByMenu(key, mask)) + { + pDesription->setText(getString("reserved_by_menu")); + pDesription->setTextArg("[KEYSTR]", LLKeyboard::stringFromAccelerator(mask,key)); + return TRUE; + } + setKeyBind(CLICK_NONE, key, mask, pCheckBox->getValue().asBoolean()); closeFloater(); return TRUE; diff --git a/indra/newview/llsetkeybinddialog.h b/indra/newview/llsetkeybinddialog.h index fb3b2a2269..8faa2cc363 100644 --- a/indra/newview/llsetkeybinddialog.h +++ b/indra/newview/llsetkeybinddialog.h @@ -32,6 +32,7 @@ #include "lldrawfrustum.h" class LLCheckBoxCtrl; +class LLTextBase; // Filters for LLSetKeyBindDialog static const U32 ALLOW_MOUSE = 1; @@ -40,18 +41,18 @@ static const U32 ALLOW_KEYS = 4; //keyboard static const U32 ALLOW_MASK_KEYS = 8; static const U32 ALLOW_MASKS = 16; static const U32 CAN_IGNORE_MASKS = 32; // For example W (aka Forward) should work regardless of SHIFT being pressed -static const U32 DEFAULT_KEY_FILTER = ALLOW_MOUSE | ALLOW_MASK_MOUSE | ALLOW_KEYS | ALLOW_MASK_KEYS | CAN_IGNORE_MASKS; +static const U32 DEFAULT_KEY_FILTER = ALLOW_MOUSE | ALLOW_MASK_MOUSE | ALLOW_KEYS | ALLOW_MASK_KEYS; class LLKeyBindResponderInterface { public: - virtual ~LLKeyBindResponderInterface(); + virtual ~LLKeyBindResponderInterface() {}; - virtual void onCancelKeyBind(); - virtual void onDefaultKeyBind(); + virtual void onCancelKeyBind() = 0; + virtual void onDefaultKeyBind() = 0; // returns true if parent failed to set key due to key being in use - virtual bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore); + virtual bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore) = 0; }; class LLSetKeyBindDialog : public LLModalDialog, public LLDrawFrustum @@ -64,7 +65,7 @@ public: /*virtual*/ void onClose(bool app_quiting); /*virtual*/ void draw(); - void setParent(LLKeyBindResponderInterface* parent, U32 key_mask = DEFAULT_KEY_FILTER); + void setParent(LLKeyBindResponderInterface* parent, LLView* frustum_origin, U32 key_mask = DEFAULT_KEY_FILTER); BOOL handleKeyHere(KEY key, MASK mask); BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down); @@ -77,8 +78,9 @@ public: private: void setKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore); - LLKeyBindResponderInterface* pParent; - LLCheckBoxCtrl* pCheckBox; + LLKeyBindResponderInterface *pParent; + LLCheckBoxCtrl *pCheckBox; + LLTextBase *pDesription; U32 mKeyFilterMask; Updater *pUpdater; diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 4a06a2012f..02d0dcb6c7 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1007,7 +1007,7 @@ BOOL LLViewerInput::handleKeyUp(KEY translated_key, MASK translated_mask) return gViewerWindow->handleKeyUp(translated_key, translated_mask); } -BOOL LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, const bool ignore, const std::string& function_name) +BOOL LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name) { S32 index; typedef boost::function function_t; @@ -1048,57 +1048,30 @@ BOOL LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, cons } // check for duplicate first and overwrite - if (ignore) + S32 size = mKeyBindings[mode].size(); + for (index = 0; index < size; index++) { - for (index = 0; index < mKeyIgnoreMaskCount[mode]; index++) - { - if (key == mKeyIgnoreMask[mode][index].mKey) - break; - } - } - else - { - for (index = 0; index < mKeyBindingCount[mode]; index++) - { - if (key == mKeyBindings[mode][index].mKey && mask == mKeyBindings[mode][index].mMask) - break; - } + if (key == mKeyBindings[mode][index].mKey && mask == mKeyBindings[mode][index].mMask) + break; } - if (index >= MAX_KEY_BINDINGS) - { - LL_ERRS() << "LLKeyboard::bindKey() - too many keys for mode " << mode << LL_ENDL; - return FALSE; - } - if (mode >= MODE_COUNT) { LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL; return FALSE; } - if (ignore) - { - mKeyIgnoreMask[mode][index].mKey = key; - mKeyIgnoreMask[mode][index].mFunction = function; - - if (index == mKeyIgnoreMaskCount[mode]) - mKeyIgnoreMaskCount[mode]++; - } - else - { - mKeyBindings[mode][index].mKey = key; - mKeyBindings[mode][index].mMask = mask; - mKeyBindings[mode][index].mFunction = function; + LLKeyboardBinding bind; + bind.mKey = key; + bind.mMask = mask; + bind.mFunction = function; - if (index == mKeyBindingCount[mode]) - mKeyBindingCount[mode]++; - } + mKeyBindings[mode].push_back(bind); return TRUE; } -BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const bool ignore, const std::string& function_name) +BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const std::string& function_name) { S32 index; typedef boost::function function_t; @@ -1117,27 +1090,11 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const } // check for duplicate first and overwrite - if (ignore) - { - for (index = 0; index < mMouseIgnoreMaskCount[mode]; index++) - { - if (mouse == mMouseIgnoreMask[mode][index].mMouse) - break; - } - } - else - { - for (index = 0; index < mMouseBindingCount[mode]; index++) - { - if (mouse == mMouseBindings[mode][index].mMouse && mask == mMouseBindings[mode][index].mMask) - break; - } - } - - if (index >= MAX_KEY_BINDINGS) + S32 size = mMouseBindings[mode].size(); + for (index = 0; index < size; index++) { - LL_ERRS() << "LLKeyboard::bindKey() - too many keys for mode " << mode << LL_ENDL; - return FALSE; + if (mouse == mMouseBindings[mode][index].mMouse && mask == mMouseBindings[mode][index].mMask) + break; } if (mode >= MODE_COUNT) @@ -1146,23 +1103,12 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const return FALSE; } - if (ignore) - { - mMouseIgnoreMask[mode][index].mMouse = mouse; - mMouseIgnoreMask[mode][index].mFunction = function; - - if (index == mMouseIgnoreMaskCount[mode]) - mMouseIgnoreMaskCount[mode]++; - } - else - { - mMouseBindings[mode][index].mMouse = mouse; - mMouseBindings[mode][index].mMask = mask; - mMouseBindings[mode][index].mFunction = function; + LLMouseBinding bind; + bind.mMouse = mouse; + bind.mMask = mask; + bind.mFunction = function; - if (index == mMouseBindingCount[mode]) - mMouseBindingCount[mode]++; - } + mMouseBindings[mode].push_back(bind); return TRUE; } @@ -1171,8 +1117,7 @@ LLViewerInput::KeyBinding::KeyBinding() : key("key"), mouse("mouse"), mask("mask"), - command("command"), - ignore("ignore", false) + command("command") {} LLViewerInput::KeyMode::KeyMode() @@ -1191,10 +1136,8 @@ void LLViewerInput::resetBindings() { for (S32 i = 0; i < MODE_COUNT; i++) { - mKeyBindingCount[i] = 0; - mKeyIgnoreMaskCount[i] = 0; - mMouseBindingCount[i] = 0; - mMouseIgnoreMaskCount[i] = 0; + mKeyBindings[i].clear(); + mMouseBindings[i].clear(); } } @@ -1218,6 +1161,34 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename) return binding_count; } +S32 count_masks(const MASK &mask) +{ + S32 res = 0; + if (mask & MASK_CONTROL) + { + res++; + } + if (mask & MASK_SHIFT) + { + res++; + } + if (mask & MASK_ALT) + { + res++; + } + return res; +} + +bool compare_key_by_mask(LLKeyboardBinding i1, LLKeyboardBinding i2) +{ + return (count_masks(i1.mMask) > count_masks(i2.mMask)); +} + +bool compare_mouse_by_mask(LLMouseBinding i1, LLMouseBinding i2) +{ + return (count_masks(i1.mMask) > count_masks(i2.mMask)); +} + S32 LLViewerInput::loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mode) { S32 binding_count = 0; @@ -1234,9 +1205,8 @@ S32 LLViewerInput::loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mo if (key != KEY_NONE) { MASK mask; - bool ignore = it->ignore.isProvided() ? it->ignore.getValue() : false; LLKeyboard::maskFromString(it->mask, &mask); - bindKey(mode, key, mask, ignore, it->command); + bindKey(mode, key, mask, it->command); processed = true; } else @@ -1251,9 +1221,8 @@ S32 LLViewerInput::loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mo if (mouse != CLICK_NONE) { MASK mask; - bool ignore = it->ignore.isProvided() ? it->ignore.getValue() : false; LLKeyboard::maskFromString(it->mask, &mask); - bindMouse(mode, mouse, mask, ignore, it->command); + bindMouse(mode, mouse, mask, it->command); processed = true; } else @@ -1266,7 +1235,11 @@ S32 LLViewerInput::loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mo // total binding_count++; } - } + } + + // sort lists by mask (so that Shift+W is executed before W, if both are assigned, but if Shift+W is not assigned W should be executed) + std::sort(mKeyBindings[mode].begin(), mKeyBindings[mode].end(), compare_key_by_mask); + std::sort(mMouseBindings[mode].begin(), mMouseBindings[mode].end(), compare_mouse_by_mask); return binding_count; } @@ -1291,7 +1264,7 @@ EKeyboardMode LLViewerInput::getMode() const } } -bool LLViewerInput::scanKey(const LLKeyboardBinding* binding, +bool LLViewerInput::scanKey(const std::vector &binding, S32 binding_count, KEY key, MASK mask, @@ -1304,7 +1277,7 @@ bool LLViewerInput::scanKey(const LLKeyboardBinding* binding, { if (binding[i].mKey == key) { - if (binding[i].mMask == mask) + if ((binding[i].mMask & mask) == binding[i].mMask) { bool res = false; if (key_down && !repeat) @@ -1352,12 +1325,7 @@ bool LLViewerInput::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) // don't process key down on repeated keys BOOL repeat = gKeyboard->getKeyRepeated(key); - bool res = scanKey(mKeyBindings[mode], mKeyBindingCount[mode], key, mask, key_down, key_up, key_level, repeat); - if (!res) - { - // Nothing found, try ignore list - res = scanKey(mKeyIgnoreMask[mode], mKeyIgnoreMaskCount[mode], key, MASK_NONE, key_down, key_up, key_level, repeat); - } + bool res = scanKey(mKeyBindings[mode], mKeyBindings[mode].size(), key, mask, key_down, key_up, key_level, repeat); if (!res && agent_control_lbutton.canHandle(CLICK_NONE, key, mask)) { @@ -1445,11 +1413,11 @@ BOOL LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, return handled; } -bool LLViewerInput::scanMouse(const LLMouseBinding *binding, S32 binding_count, EMouseClickType mouse, MASK mask, EMouseState state) const +bool LLViewerInput::scanMouse(const std::vector &binding, S32 binding_count, EMouseClickType mouse, MASK mask, EMouseState state) const { for (S32 i = 0; i < binding_count; i++) { - if (binding[i].mMouse == mouse && binding[i].mMask == mask) + if (binding[i].mMouse == mouse && (binding[i].mMask & mask) == binding[i].mMask) { bool res = false; switch (state) @@ -1486,11 +1454,7 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const bool res = false; S32 mode = getMode(); MASK mask = gKeyboard->currentMask(TRUE); - res = scanMouse(mMouseBindings[mode], mMouseBindingCount[mode], click, mask, state); - if (!res) - { - res = scanMouse(mMouseIgnoreMask[mode], mMouseIgnoreMaskCount[mode], click, MASK_NONE, state); - } + res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state); // no user defined actions found or those actions can't handle the key/button, handle control if nessesary if (!res && agent_control_lbutton.canHandle(click, KEY_NONE, mask)) { diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h index d18a61eaf0..b7124a54b2 100644 --- a/indra/newview/llviewerinput.h +++ b/indra/newview/llviewerinput.h @@ -30,7 +30,6 @@ #include "llkeyboard.h" // For EKeystate #include "llinitparam.h" -const S32 MAX_NAMED_FUNCTIONS = 100; const S32 MAX_KEY_BINDINGS = 128; // was 60 class LLNamedFunction @@ -48,7 +47,6 @@ class LLKeyboardBinding public: KEY mKey; MASK mMask; - bool mIgnoreMask; // whether CTRL/ALT/SHIFT should be checked LLKeyFunc mFunction; }; @@ -58,7 +56,6 @@ class LLMouseBinding public: EMouseClickType mMouse; MASK mMask; - bool mIgnoreMask; // whether CTRL/ALT/SHIFT should be checked LLKeyFunc mFunction; }; @@ -86,8 +83,7 @@ public: Mandatory key, mask, command; - Optional mouse; // Note, not mandatory for the sake of backward campatibility - Optional ignore; + Optional mouse; // Note, not mandatory for the sake of backward campatibility with keys.xml KeyBinding(); }; @@ -131,7 +127,7 @@ public: void scanMouse(); private: - bool scanKey(const LLKeyboardBinding* binding, + bool scanKey(const std::vector &binding, S32 binding_count, KEY key, MASK mask, @@ -149,34 +145,24 @@ private: MOUSE_STATE_SILENT // notified about 'up', do not notify again }; bool scanMouse(EMouseClickType click, EMouseState state) const; - bool scanMouse(const LLMouseBinding *binding, + bool scanMouse(const std::vector &binding, S32 binding_count, EMouseClickType mouse, MASK mask, EMouseState state) const; S32 loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mode); - BOOL bindKey(const S32 mode, const KEY key, const MASK mask, const bool ignore, const std::string& function_name); - BOOL bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const bool ignore, const std::string& function_name); + BOOL bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name); + BOOL bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const std::string& function_name); void resetBindings(); // Hold all the ugly stuff torn out to make LLKeyboard non-viewer-specific here - // We process specific keys first, then keys that should ignore mask. - // This way with W+ignore defined to 'forward' and with ctrl+W tied to camera, - // pressing undefined Shift+W will do 'forward', yet ctrl+W will do 'camera forward' - // With A defined to 'turn', shift+A defined to strafe, pressing Shift+W+A will do strafe+forward // TODO: at some point it is better to remake this, especially keyaboard part // would be much better to send to functions actual state of the button than // to send what we think function wants based on collection of bools (mKeyRepeated, mKeyLevel, mKeyDown) - S32 mKeyBindingCount[MODE_COUNT]; - S32 mKeyIgnoreMaskCount[MODE_COUNT]; - S32 mMouseBindingCount[MODE_COUNT]; - S32 mMouseIgnoreMaskCount[MODE_COUNT]; - LLKeyboardBinding mKeyBindings[MODE_COUNT][MAX_KEY_BINDINGS]; - LLKeyboardBinding mKeyIgnoreMask[MODE_COUNT][MAX_KEY_BINDINGS]; - LLMouseBinding mMouseBindings[MODE_COUNT][MAX_KEY_BINDINGS]; - LLMouseBinding mMouseIgnoreMask[MODE_COUNT][MAX_KEY_BINDINGS]; + std::vector mKeyBindings[MODE_COUNT]; + std::vector mMouseBindings[MODE_COUNT]; typedef std::map key_remap_t; key_remap_t mRemapKeys[MODE_COUNT]; diff --git a/indra/newview/skins/default/xui/en/control_table_contents.xml b/indra/newview/skins/default/xui/en/control_table_contents.xml index 00c2d27124..7d4b9be894 100644 --- a/indra/newview/skins/default/xui/en/control_table_contents.xml +++ b/indra/newview/skins/default/xui/en/control_table_contents.xml @@ -20,7 +20,7 @@ enabled="false" value=""> @@ -204,7 +204,7 @@ enabled="false" value=""> @@ -426,7 +426,7 @@ enabled="false" value=""> @@ -504,7 +504,7 @@ enabled="false" value=""> Mouse Buttons + + +Press a key to set your trigger. +Allowed input: [INPUT]. + + +Combination [KEYSTR] is reserved by menu. -- cgit v1.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/llui/llmenugl.cpp | 53 ++++++++++++++++++++++-------------- indra/llui/llmenugl.h | 7 +++-- indra/newview/llkeyconflict.cpp | 12 ++++++-- indra/newview/llsetkeybinddialog.cpp | 53 ++++++++++++++++++++++++++++-------- indra/newview/llsetkeybinddialog.h | 9 +++++- indra/newview/llviewerwindow.cpp | 9 ++++++ 6 files changed, 104 insertions(+), 39 deletions(-) (limited to 'indra/newview/llsetkeybinddialog.cpp') diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index d97bf2d674..b87819102b 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -212,6 +212,12 @@ LLSD LLMenuItemGL::getValue() const return getLabel(); } +//virtual +bool LLMenuItemGL::hasAccelerator(const KEY &key, const MASK &mask) const +{ + return (mAcceleratorKey == key) && (mAcceleratorMask == mask); +} + //virtual BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask) { @@ -1017,6 +1023,11 @@ BOOL LLMenuItemBranchGL::handleMouseUp(S32 x, S32 y, MASK mask) return TRUE; } +bool LLMenuItemBranchGL::hasAccelerator(const KEY &key, const MASK &mask) const +{ + return getBranch() && getBranch()->hasAccelerator(key, mask); +} + BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask) { return getBranch() && getBranch()->handleAcceleratorKey(key, mask); @@ -3023,6 +3034,27 @@ void LLMenuGL::updateParent(LLView* parentp) } } +bool LLMenuGL::hasAccelerator(const KEY &key, const MASK &mask) const +{ + if (key == KEY_NONE) + { + return false; + } + // Note: checking this way because mAccelerators seems to be broken + // mAccelerators probably needs to be cleaned up or fixed + // It was used for dupplicate accelerator avoidance. + item_list_t::const_iterator item_iter; + for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) + { + LLMenuItemGL* itemp = *item_iter; + if (itemp->hasAccelerator(key, mask)) + { + return true; + } + } + return false; +} + BOOL LLMenuGL::handleAcceleratorKey(KEY key, MASK mask) { // don't handle if not enabled @@ -3536,27 +3568,6 @@ S32 LLMenuBarGL::getRightmostMenuEdge() return (*item_iter)->getRect().mRight; } -bool LLMenuBarGL::hasAccelerator(const KEY &key, const MASK &mask) const -{ - if (key == KEY_NONE) - { - return false; - } - - LLMenuKeyboardBinding *accelerator = NULL; - std::list::const_iterator list_it; - for (list_it = mAccelerators.begin(); list_it != mAccelerators.end(); ++list_it) - { - accelerator = *list_it; - if ((accelerator->mKey == key) && (accelerator->mMask == (mask & MASK_NORMALKEYS))) - { - return true; - } - } - - return false; -} - // add a vertical separator to this menu BOOL LLMenuBarGL::addSeparator() { diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index adcb2ca2f9..8cef9c6463 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -98,6 +98,7 @@ public: /*virtual*/ void setValue(const LLSD& value); /*virtual*/ LLSD getValue() const; + virtual bool hasAccelerator(const KEY &key, const MASK &mask) const; virtual BOOL handleAcceleratorKey(KEY key, MASK mask); LLColor4 getHighlightBgColor() { return mHighlightBackground.get(); } @@ -443,7 +444,8 @@ public: /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); /*virtual*/ void removeChild( LLView* ctrl); /*virtual*/ BOOL postBuild(); - + + virtual bool hasAccelerator(const KEY &key, const MASK &mask) const; virtual BOOL handleAcceleratorKey(KEY key, MASK mask); LLMenuGL* findChildMenuByName(const std::string& name, BOOL recurse) const; @@ -635,6 +637,7 @@ public: virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual bool hasAccelerator(const KEY &key, const MASK &mask) const; virtual BOOL handleAcceleratorKey(KEY key, MASK mask); // check if we've used these accelerators already @@ -795,8 +798,6 @@ public: void resetMenuTrigger() { mAltKeyTrigger = FALSE; } - bool hasAccelerator(const KEY &key, const MASK &mask) const; - private: // add a menu - this will create a drop down menu. virtual BOOL appendMenu( LLMenuGL* menu ); 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) diff --git a/indra/newview/llsetkeybinddialog.cpp b/indra/newview/llsetkeybinddialog.cpp index 320f1f297d..806c70aa03 100644 --- a/indra/newview/llsetkeybinddialog.cpp +++ b/indra/newview/llsetkeybinddialog.cpp @@ -28,11 +28,10 @@ #include "llsetkeybinddialog.h" -//#include "llkeyboard.h" - #include "llbutton.h" #include "llcheckboxctrl.h" #include "lleventtimer.h" +#include "llfloaterreg.h" #include "llfocusmgr.h" #include "llkeyconflict.h" @@ -65,6 +64,8 @@ private: callback_t mCallback; }; +bool LLSetKeyBindDialog::sRecordKeys = false; + LLSetKeyBindDialog::LLSetKeyBindDialog(const LLSD& key) : LLModalDialog(key), pParent(NULL), @@ -93,9 +94,17 @@ BOOL LLSetKeyBindDialog::postBuild() return TRUE; } +//virtual +void LLSetKeyBindDialog::onOpen(const LLSD& data) +{ + sRecordKeys = true; + LLModalDialog::onOpen(data); +} + //virtual void LLSetKeyBindDialog::onClose(bool app_quiting) { + sRecordKeys = false; if (pParent) { pParent->onCancelKeyBind(); @@ -145,20 +154,41 @@ void LLSetKeyBindDialog::setParent(LLKeyBindResponderInterface* parent, LLView* pCheckBox->setValue(false); } -BOOL LLSetKeyBindDialog::handleKeyHere(KEY key, MASK mask) +// static +bool LLSetKeyBindDialog::recordKey(KEY key, MASK mask) +{ + if (sRecordKeys) + { + LLSetKeyBindDialog* dialog = LLFloaterReg::getTypedInstance("keybind_dialog", LLSD()); + if (dialog && dialog->getVisible()) + { + return dialog->recordAndHandleKey(key, mask); + } + else + { + LL_WARNS() << "Key recording was set despite no open dialog" << LL_ENDL; + sRecordKeys = false; + } + } + return false; +} + +bool LLSetKeyBindDialog::recordAndHandleKey(KEY key, MASK mask) { if ((key == 'Q' && mask == MASK_CONTROL) || key == KEY_ESCAPE) { + sRecordKeys = false; closeFloater(); - return TRUE; + return true; } if (key == KEY_DELETE) { setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false); + sRecordKeys = false; closeFloater(); - return FALSE; + return false; } // forbidden keys @@ -166,36 +196,37 @@ BOOL LLSetKeyBindDialog::handleKeyHere(KEY key, MASK mask) || key == KEY_RETURN || key == KEY_BACKSPACE) { - return FALSE; + return false; } if ((mKeyFilterMask & ALLOW_MASKS) == 0 && (key == KEY_CONTROL || key == KEY_SHIFT || key == KEY_ALT)) { // mask by themself are not allowed - return FALSE; + return false; } else if ((mKeyFilterMask & ALLOW_KEYS) == 0) { // basic keys not allowed - return FALSE; + return false; } else if ((mKeyFilterMask & ALLOW_MASK_KEYS) == 0 && mask != 0) { // masked keys not allowed - return FALSE; + return false; } if (LLKeyConflictHandler::isReservedByMenu(key, mask)) { pDesription->setText(getString("reserved_by_menu")); pDesription->setTextArg("[KEYSTR]", LLKeyboard::stringFromAccelerator(mask,key)); - return TRUE; + return true; } setKeyBind(CLICK_NONE, key, mask, pCheckBox->getValue().asBoolean()); + sRecordKeys = false; closeFloater(); - return TRUE; + return true; } BOOL LLSetKeyBindDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down) diff --git a/indra/newview/llsetkeybinddialog.h b/indra/newview/llsetkeybinddialog.h index 8faa2cc363..16a2d768e4 100644 --- a/indra/newview/llsetkeybinddialog.h +++ b/indra/newview/llsetkeybinddialog.h @@ -62,12 +62,16 @@ public: ~LLSetKeyBindDialog(); /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& data); /*virtual*/ void onClose(bool app_quiting); /*virtual*/ void draw(); void setParent(LLKeyBindResponderInterface* parent, LLView* frustum_origin, U32 key_mask = DEFAULT_KEY_FILTER); - BOOL handleKeyHere(KEY key, MASK mask); + // Wrapper around recordAndHandleKey + // It does not record, it handles, but handleKey function is already in use + static bool recordKey(KEY key, MASK mask); + BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down); static void onCancel(void* user_data); static void onBlank(void* user_data); @@ -77,6 +81,7 @@ public: class Updater; private: + bool recordAndHandleKey(KEY key, MASK mask); void setKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore); LLKeyBindResponderInterface *pParent; LLCheckBoxCtrl *pCheckBox; @@ -84,6 +89,8 @@ private: U32 mKeyFilterMask; Updater *pUpdater; + + static bool sRecordKeys; // for convinience and not to check instance each time }; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 091fc720c1..a6bc3373e2 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -45,6 +45,7 @@ #include "llmeshrepository.h" #include "llnotificationhandler.h" #include "llpanellogin.h" +#include "llsetkeybinddialog.h" #include "llviewerinput.h" #include "llviewermenu.h" @@ -2730,6 +2731,14 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) // hide tooltips on keypress LLToolTipMgr::instance().blockToolTips(); + // let menus handle navigation keys for navigation + if (LLSetKeyBindDialog::recordKey(key, mask)) + { + LL_DEBUGS() << "Key handled by LLSetKeyBindDialog" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return TRUE; + } + LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); if (keyboard_focus -- cgit v1.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/app_settings/key_bindings.xml | 60 --------------- indra/newview/llfloaterpreference.cpp | 85 ++++++++++++++++++---- indra/newview/llfloaterpreference.h | 7 +- indra/newview/llkeyconflict.cpp | 13 ---- indra/newview/llkeyconflict.h | 1 - indra/newview/llsetkeybinddialog.cpp | 12 +-- indra/newview/llsetkeybinddialog.h | 7 +- indra/newview/llviewerinput.cpp | 7 -- indra/newview/llviewerinput.h | 2 - .../skins/default/xui/en/floater_select_key.xml | 8 +- .../newview/skins/default/xui/en/notifications.xml | 13 ++++ .../default/xui/en/panel_preferences_controls.xml | 18 ++--- 12 files changed, 104 insertions(+), 129 deletions(-) (limited to 'indra/newview/llsetkeybinddialog.cpp') diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml index 536199c696..dd74293644 100644 --- a/indra/newview/app_settings/key_bindings.xml +++ b/indra/newview/app_settings/key_bindings.xml @@ -129,65 +129,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -312,6 +253,5 @@ - diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 0abd014a2c..50b7f16ec7 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -2637,7 +2637,7 @@ BOOL LLPanelPreferenceControls::postBuild() pControlsTable->setCommitCallback(boost::bind(&LLPanelPreferenceControls::onListCommit, this)); pKeyModeBox->setCommitCallback(boost::bind(&LLPanelPreferenceControls::onModeCommit, this)); - getChild("restore_defaults")->setCommitCallback(boost::bind(&LLPanelPreferenceControls::onRestoreDefaults, this)); + getChild("restore_defaults")->setCommitCallback(boost::bind(&LLPanelPreferenceControls::onRestoreDefaultsBtn, this)); return TRUE; } @@ -2659,7 +2659,6 @@ void LLPanelPreferenceControls::populateControlTable() { case LLKeyConflictHandler::MODE_THIRD_PERSON: case LLKeyConflictHandler::MODE_FIRST_PERSON: - case LLKeyConflictHandler::MODE_EDIT: case LLKeyConflictHandler::MODE_EDIT_AVATAR: case LLKeyConflictHandler::MODE_SITTING: filename = "control_table_contents.xml"; @@ -2867,20 +2866,42 @@ void LLPanelPreferenceControls::onModeCommit() populateControlTable(); } -void LLPanelPreferenceControls::onRestoreDefaults() +void LLPanelPreferenceControls::onRestoreDefaultsBtn() { - for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i) + LLNotificationsUtil::add("PreferenceControlsDefaults", LLSD(), LLSD(), boost::bind(&LLPanelPreferenceControls::onRestoreDefaultsResponse, this, _1, _2)); +} + +void LLPanelPreferenceControls::onRestoreDefaultsResponse(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch(option) { - mConflictHandler[i].resetToDefaults(); + case 0: // All + for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i) + { + mConflictHandler[i].resetToDefaults(); + // Apply changes to viewer as 'temporary' + mConflictHandler[i].saveToSettings(true); + } + + updateTable(); + break; + case 1: // Current + mConflictHandler[mEditingMode].resetToDefaults(); // Apply changes to viewer as 'temporary' - mConflictHandler[i].saveToSettings(true); - } + mConflictHandler[mEditingMode].saveToSettings(true); - updateTable(); + updateTable(); + break; + case 2: // Cancel + default: + //exit; + break; + } } // todo: copy onSetKeyBind to interface and inherit from interface -bool LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore_mask) +bool LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes) { if (!mConflictHandler[mEditingMode].canAssignControl(mEditingControl)) { @@ -2889,16 +2910,32 @@ bool LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MAS if ( mEditingColumn > 0) { - mConflictHandler[mEditingMode].registerControl(mEditingControl, mEditingColumn - 1, click, key, mask, true); - // Apply changes to viewer as 'temporary' - mConflictHandler[mEditingMode].saveToSettings(true); + if (all_modes) + { + for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i) + { + if (mConflictHandler[i].empty()) + { + mConflictHandler[i].loadFromSettings((LLKeyConflictHandler::ESourceMode)i); + } + mConflictHandler[i].registerControl(mEditingControl, mEditingColumn - 1, click, key, mask, true); + // Apply changes to viewer as 'temporary' + mConflictHandler[i].saveToSettings(true); + } + } + else + { + mConflictHandler[mEditingMode].registerControl(mEditingControl, mEditingColumn - 1, click, key, mask, true); + // Apply changes to viewer as 'temporary' + mConflictHandler[mEditingMode].saveToSettings(true); + } } updateTable(); return true; } -void LLPanelPreferenceControls::onDefaultKeyBind() +void LLPanelPreferenceControls::onDefaultKeyBind(bool all_modes) { if (!mConflictHandler[mEditingMode].canAssignControl(mEditingControl)) { @@ -2907,9 +2944,25 @@ void LLPanelPreferenceControls::onDefaultKeyBind() if (mEditingColumn > 0) { - mConflictHandler[mEditingMode].resetToDefault(mEditingControl, mEditingColumn - 1); - // Apply changes to viewer as 'temporary' - mConflictHandler[mEditingMode].saveToSettings(true); + if (all_modes) + { + for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i) + { + if (mConflictHandler[i].empty()) + { + mConflictHandler[i].loadFromSettings((LLKeyConflictHandler::ESourceMode)i); + } + mConflictHandler[i].resetToDefault(mEditingControl, mEditingColumn - 1); + // Apply changes to viewer as 'temporary' + mConflictHandler[i].saveToSettings(true); + } + } + else + { + mConflictHandler[mEditingMode].resetToDefault(mEditingControl, mEditingColumn - 1); + // Apply changes to viewer as 'temporary' + mConflictHandler[mEditingMode].saveToSettings(true); + } } updateTable(); } diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index f89923e497..6c2e655270 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -302,9 +302,10 @@ public: void onListCommit(); void onModeCommit(); - void onRestoreDefaults(); - /*virtual*/ bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore_mask); - /*virtual*/ void onDefaultKeyBind(); + void onRestoreDefaultsBtn(); + void onRestoreDefaultsResponse(const LLSD& notification, const LLSD& response); + /*virtual*/ bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes); + /*virtual*/ void onDefaultKeyBind(bool all_modes); /*virtual*/ void onCancelKeyBind(); private: 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()) { diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h index 4ebe054f22..48af0ccdfe 100644 --- a/indra/newview/llkeyconflict.h +++ b/indra/newview/llkeyconflict.h @@ -59,7 +59,6 @@ public: { MODE_FIRST_PERSON, MODE_THIRD_PERSON, - MODE_EDIT, MODE_EDIT_AVATAR, MODE_SITTING, MODE_SAVED_SETTINGS, // for settings from saved settings diff --git a/indra/newview/llsetkeybinddialog.cpp b/indra/newview/llsetkeybinddialog.cpp index 806c70aa03..8d0d71daaf 100644 --- a/indra/newview/llsetkeybinddialog.cpp +++ b/indra/newview/llsetkeybinddialog.cpp @@ -86,7 +86,7 @@ BOOL LLSetKeyBindDialog::postBuild() childSetAction("Cancel", onCancel, this); getChild("Cancel")->setFocus(TRUE); - pCheckBox = getChild("ignore_masks"); + pCheckBox = getChild("apply_all"); pDesription = getChild("descritption"); gFocusMgr.setKeystrokesOnly(TRUE); @@ -148,10 +148,6 @@ void LLSetKeyBindDialog::setParent(LLKeyBindResponderInterface* parent, LLView* } pDesription->setText(getString("basic_description")); pDesription->setTextArg("[INPUT]", input); - - bool can_ignore_masks = (key_mask & CAN_IGNORE_MASKS) != 0; - pCheckBox->setVisible(can_ignore_masks); - pCheckBox->setValue(false); } // static @@ -308,7 +304,7 @@ void LLSetKeyBindDialog::onDefault(void* user_data) LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data; if (self->pParent) { - self->pParent->onDefaultKeyBind(); + self->pParent->onDefaultKeyBind(self->pCheckBox->getValue().asBoolean()); self->pParent = NULL; } self->closeFloater(); @@ -326,11 +322,11 @@ void LLSetKeyBindDialog::onClickTimeout(void* user_data, MASK mask) self->closeFloater(); } -void LLSetKeyBindDialog::setKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore) +void LLSetKeyBindDialog::setKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes) { if (pParent) { - pParent->onSetKeyBind(click, key, mask, ignore); + pParent->onSetKeyBind(click, key, mask, all_modes); pParent = NULL; } } diff --git a/indra/newview/llsetkeybinddialog.h b/indra/newview/llsetkeybinddialog.h index 16a2d768e4..c7b4e3c364 100644 --- a/indra/newview/llsetkeybinddialog.h +++ b/indra/newview/llsetkeybinddialog.h @@ -40,7 +40,6 @@ static const U32 ALLOW_MASK_MOUSE = 2; static const U32 ALLOW_KEYS = 4; //keyboard static const U32 ALLOW_MASK_KEYS = 8; static const U32 ALLOW_MASKS = 16; -static const U32 CAN_IGNORE_MASKS = 32; // For example W (aka Forward) should work regardless of SHIFT being pressed static const U32 DEFAULT_KEY_FILTER = ALLOW_MOUSE | ALLOW_MASK_MOUSE | ALLOW_KEYS | ALLOW_MASK_KEYS; @@ -50,9 +49,9 @@ public: virtual ~LLKeyBindResponderInterface() {}; virtual void onCancelKeyBind() = 0; - virtual void onDefaultKeyBind() = 0; + virtual void onDefaultKeyBind(bool all_modes) = 0; // returns true if parent failed to set key due to key being in use - virtual bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore) = 0; + virtual bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes) = 0; }; class LLSetKeyBindDialog : public LLModalDialog, public LLDrawFrustum @@ -82,7 +81,7 @@ public: private: bool recordAndHandleKey(KEY key, MASK mask); - void setKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore); + void setKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes); LLKeyBindResponderInterface *pParent; LLCheckBoxCtrl *pCheckBox; LLTextBase *pDesription; diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 3ff4e4eb9d..9f16b6a4d5 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -936,11 +936,6 @@ BOOL LLViewerInput::modeFromString(const std::string& string, S32 *mode) const *mode = MODE_THIRD_PERSON; return TRUE; } - else if (string == "EDIT") - { - *mode = MODE_EDIT; - return TRUE; - } else if (string == "EDIT_AVATAR") { *mode = MODE_EDIT_AVATAR; @@ -1155,7 +1150,6 @@ LLViewerInput::KeyMode::KeyMode() LLViewerInput::Keys::Keys() : first_person("first_person"), third_person("third_person"), - edit("edit"), sitting("sitting"), edit_avatar("edit_avatar") {} @@ -1182,7 +1176,6 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename) { binding_count += loadBindingMode(keys.first_person, MODE_FIRST_PERSON); binding_count += loadBindingMode(keys.third_person, MODE_THIRD_PERSON); - binding_count += loadBindingMode(keys.edit, MODE_EDIT); binding_count += loadBindingMode(keys.sitting, MODE_SITTING); binding_count += loadBindingMode(keys.edit_avatar, MODE_EDIT_AVATAR); } diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h index b7124a54b2..eff42600fd 100644 --- a/indra/newview/llviewerinput.h +++ b/indra/newview/llviewerinput.h @@ -65,7 +65,6 @@ typedef enum e_keyboard_mode { MODE_FIRST_PERSON, MODE_THIRD_PERSON, - MODE_EDIT, MODE_EDIT_AVATAR, MODE_SITTING, MODE_COUNT @@ -99,7 +98,6 @@ public: { Optional first_person, third_person, - edit, sitting, edit_avatar; diff --git a/indra/newview/skins/default/xui/en/floater_select_key.xml b/indra/newview/skins/default/xui/en/floater_select_key.xml index 255de60d00..48d9eee4cd 100644 --- a/indra/newview/skins/default/xui/en/floater_select_key.xml +++ b/indra/newview/skins/default/xui/en/floater_select_key.xml @@ -44,11 +44,11 @@ Allowed input: [INPUT]. follows="top|left" height="20" initial_value="false" - label="Ignore extra accelerator keys" + label="Apply to all" layout="topleft" - left="28" - name="ignore_masks" - tool_tip="Ignore extra Shift, Alt and Ctrl keys. Example: This allows to hold W (forward, ignores shift) and Shift+A (slide left) simultaneously and agent will both move forward and slide left." + left="90" + name="apply_all" + tool_tip="Viewer uses different control combinations depending on what you are doing in world, setting this will apply your change to all combinations" top_pad="8" width="160" /> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 8a91a1f721..42d4f46d7f 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -11406,6 +11406,19 @@ Cannot create large prims that intersect other residents. Please re-try when ot notext="Cancel" yestext="OK"/> + + + Do you want to restore default values for controls? + confirm + + + - + value="2"/> + value="3"/>