summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcommon/llkeybind.h2
-rw-r--r--indra/newview/app_settings/key_bindings.xml1
-rw-r--r--indra/newview/llappviewer.cpp99
-rw-r--r--indra/newview/llkeyconflict.cpp67
-rw-r--r--indra/newview/llkeyconflict.h16
5 files changed, 182 insertions, 3 deletions
diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h
index ad0ebec67c..c6b4bd970f 100644
--- a/indra/llcommon/llkeybind.h
+++ b/indra/llcommon/llkeybind.h
@@ -53,7 +53,7 @@ public:
EMouseClickType mMouse;
KEY mKey;
MASK mMask;
- // Either to expect exact match or ignore not expected masks
+ // Either to expect exact match or ignore not expected masks as long as expected mask-bit is present
bool mIgnoreMasks;
};
diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml
index 81423c4716..4f6deb1f98 100644
--- a/indra/newview/app_settings/key_bindings.xml
+++ b/indra/newview/app_settings/key_bindings.xml
@@ -224,7 +224,6 @@
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
- <binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
</sitting>
<edit_avatar>
<!--Avatar editing camera controls-->
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 4c2de27f42..911cc224a1 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -49,6 +49,7 @@
#include "llwindow.h"
#include "llviewerstats.h"
#include "llviewerstatsrecorder.h"
+#include "llkeyconflict.h" // for legacy keybinding support, remove later
#include "llmarketplacefunctions.h"
#include "llmarketplacenotifications.h"
#include "llmd5.h"
@@ -1004,6 +1005,104 @@ bool LLAppViewer::init()
// Load User's bindings
std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml");
+#if 1
+ // Legacy support
+ // Remove #if-#endif section half a year after DRTVWR-501 releases.
+ // Mouse actions are part of keybinding file since DRTVWR-501 instead of being stored in
+ // settings.xml. To support legacy viewers that were storing in settings.xml we need to
+ // transfer old variables to new format.
+ // Also part of backward compatibility is present in LLKeyConflictHandler to modify
+ // legacy variables on changes in new system (to make sure we won't enforce
+ // legacy values again if user dropped to defaults in new system)
+ if (mIsFirstRun
+ && !gDirUtilp->fileExists(key_bindings_file)) // if file is missing, assume that there were no changes by user yet
+ {
+ // copy mouse actions and voice key changes to new file
+ LL_INFOS("InitInfo") << "Converting legacy mouse bindings to new format" << LL_ENDL;
+ // Load settings from file
+ LLKeyConflictHandler third_person_view(LLKeyConflictHandler::MODE_THIRD_PERSON);
+
+ // Since we are only modifying keybindings if personal file doesn't exist yet,
+ // it should be safe to just overwrite the value
+ // If key is already in use somewhere by default, LLKeyConflictHandler should resolve it.
+ BOOL value = gSavedSettings.getBOOL("DoubleClickAutoPilot");
+ third_person_view.registerControl("walk_to",
+ 0,
+ value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE,
+ KEY_NONE,
+ MASK_NONE,
+ value);
+
+ U32 index = value ? 1 : 0; // we can store multiple combinations per action, so if first is in use by doubleclick, go to second
+ value = gSavedSettings.getBOOL("ClickToWalk");
+ third_person_view.registerControl("walk_to",
+ index,
+ value ? EMouseClickType::CLICK_LEFT : EMouseClickType::CLICK_NONE,
+ KEY_NONE,
+ MASK_NONE,
+ value);
+
+ value = gSavedSettings.getBOOL("DoubleClickTeleport");
+ third_person_view.registerControl("teleport_to",
+ 0,
+ value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE,
+ KEY_NONE,
+ MASK_NONE,
+ value);
+
+ std::string key_string = gSavedSettings.getString("PushToTalkButton");
+ EMouseClickType mouse = EMouseClickType::CLICK_NONE;
+ KEY key = KEY_NONE;
+ if (key_string == "MiddleMouse")
+ {
+ mouse = EMouseClickType::CLICK_MIDDLE;
+ }
+ else if (key_string == "MouseButton4")
+ {
+ mouse = EMouseClickType::CLICK_BUTTON4;
+ }
+ else if (key_string == "MouseButton5")
+ {
+ mouse = EMouseClickType::CLICK_BUTTON5;
+ }
+ else
+ {
+ LLKeyboard::keyFromString(key_string, &key);
+ }
+
+ value = gSavedSettings.getBOOL("PushToTalkToggle");
+ std::string control_name = value ? "toggle_voice" : "voice_follow_key";
+ third_person_view.registerControl(control_name, 0, mouse, key, MASK_NONE, true);
+
+ if (third_person_view.hasUnsavedChanges())
+ {
+ // calls loadBindingsXML()
+ third_person_view.saveToSettings();
+ }
+
+ // in case of voice we need to repeat this in other modes (teleports and
+ // autopilot are not entirely practical when sitting or editing)
+
+ for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
+ {
+ if (i != LLKeyConflictHandler::MODE_THIRD_PERSON)
+ {
+ LLKeyConflictHandler handler((LLKeyConflictHandler::ESourceMode)i);
+
+ handler.registerControl(control_name, 0, mouse, key, MASK_NONE, true);
+
+ if (handler.hasUnsavedChanges())
+ {
+ // calls loadBindingsXML()
+ handler.saveToSettings();
+ }
+ }
+ }
+ }
+ // since something might have gone wrong or there might have been nothing to save
+ // (and because otherwise following code will have to be encased in else{}),
+ // load everything one last time
+#endif
if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file))
{
// Failed to load custom bindings, try default ones
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)
diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h
index 73d59cc217..5451c16ae2 100644
--- a/indra/newview/llkeyconflict.h
+++ b/indra/newview/llkeyconflict.h
@@ -82,6 +82,18 @@ public:
bool canAssignControl(const std::string &control_name);
static bool isReservedByMenu(const KEY &key, const MASK &mask);
static bool isReservedByMenu(const LLKeyData &data);
+
+ // @control_name - see REGISTER_KEYBOARD_ACTION in llviewerinput for avaliable options,
+ // usually this is just name of the function
+ // @data_index - single control (function) can have multiple key combinations trigering
+ // it, this index indicates combination function will change/add note that preferences
+ // floater can only display up to 3 options, but data_index can be bigger then that
+ // @mouse_ind - mouse action (middle click, MB5 etc)
+ // @key - keyboard key action
+ // @mask - shift/ctrl/alt flags
+ // @ignore_mask - Either to expect exact match (ctrl+K will not trigger if ctrl+shift+K
+ // is active) or ignore not expected masks as long as expected mask is present
+ // (ctrl+K will be triggered if ctrl+shift+K is active)
bool registerControl(const std::string &control_name, U32 data_index, EMouseClickType mouse_ind, KEY key, MASK mask, bool ignore_mask); //todo: return conflicts?
LLKeyData getControl(const std::string &control_name, U32 data_index);
@@ -101,6 +113,10 @@ public:
// 'temporary' does not support gSavedSettings, those are handled
// by preferences, so 'temporary' is such case will simply not
// reset mHasUnsavedChanges
+ //
+ // 'temporary' exists to support ability of live-editing settings in
+ // preferences: temporary for testing changes 'live' without saving them,
+ // then hitting ok/cancel and save/discard values permanently.
void saveToSettings(bool apply_temporary = false);
LLKeyData getDefaultControl(const std::string &control_name, U32 data_index);