diff options
| -rw-r--r-- | indra/llui/llurlentry.cpp | 121 | ||||
| -rw-r--r-- | indra/llui/llurlentry.h | 33 | ||||
| -rw-r--r-- | indra/llui/llurlregistry.cpp | 8 | ||||
| -rw-r--r-- | indra/llui/llurlregistry.h | 6 | ||||
| -rw-r--r-- | indra/llwindow/llkeyboard.cpp | 51 | ||||
| -rw-r--r-- | indra/llwindow/llkeyboard.h | 9 | ||||
| -rw-r--r-- | indra/newview/llappviewer.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llfloaterpreference.cpp | 42 | ||||
| -rw-r--r-- | indra/newview/llkeyconflict.cpp | 38 | ||||
| -rw-r--r-- | indra/newview/llviewerinput.cpp | 92 | ||||
| -rw-r--r-- | indra/newview/llviewerinput.h | 17 | 
11 files changed, 360 insertions, 59 deletions
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 6a9070634c..77e9edf5e5 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -35,7 +35,9 @@  #include "llavatarnamecache.h"  #include "llcachename.h" +#include "llkeyboard.h"  #include "llregex.h" +#include "llscrolllistctrl.h" // for LLUrlEntryKeybinding file parsing  #include "lltrans.h"  #include "lluicolortable.h"  #include "message.h" @@ -1609,3 +1611,122 @@ std::string LLUrlEntryIPv6::getUrl(const std::string &string) const  {  	return string;  } + + +// +// LLUrlEntryKeybinding Displays currently assigned key +// +LLUrlEntryKeybinding::LLUrlEntryKeybinding() +    : LLUrlEntryBase() +    , pHandler(NULL) +{ +    mPattern = boost::regex(APP_HEADER_REGEX "/keybinding/\\w+(\\?mode=\\w+)?$", +                            boost::regex::perl | boost::regex::icase); +    mMenuName = "menu_url_experience.xml"; + +    initLocalization(); +} + +std::string LLUrlEntryKeybinding::getLabel(const std::string& url, const LLUrlLabelCallback& cb) +{ +    std::string control = getControlName(url); + +    std::map<std::string, LLLocalizationData>::iterator iter = mLocalizations.find(control); + +    std::string keybind; +    if (pHandler) +    { +        keybind = pHandler->getKeyBindingAsString(getMode(url), control); +    } + +    if (iter != mLocalizations.end()) +    { +        return iter->second.mLocalization + ": " + keybind; +    } + +    return control + ": " + keybind; +} + +std::string LLUrlEntryKeybinding::getTooltip(const std::string& url) const +{ +    std::string control = getControlName(url); + +    std::map<std::string, LLLocalizationData>::const_iterator iter = mLocalizations.find(control); +    if (iter != mLocalizations.end()) +    { +        return iter->second.mTooltip; +    } +    return url; +} + +std::string LLUrlEntryKeybinding::getControlName(const std::string& url) const +{ +    std::string search = "/keybinding/"; +    size_t pos_start = url.find(search); +    if (pos_start == std::string::npos) +    { +        return std::string(); +    } +    pos_start += search.size(); + +    size_t pos_end = url.find("?mode="); +    if (pos_end == std::string::npos) +    { +        pos_end = url.size(); +    } +    return url.substr(pos_start, pos_end - pos_start); +} + +std::string LLUrlEntryKeybinding::getMode(const std::string& url) const +{ +    std::string search = "?mode="; +    size_t pos_start = url.find(search); +    if (pos_start == std::string::npos) +    { +        return std::string(); +    } +    pos_start += search.size(); +    return url.substr(pos_start, url.size() - pos_start); +} + +void LLUrlEntryKeybinding::initLocalization() +{ +    initLocalizationFromFile("control_table_contents_movement.xml"); +    initLocalizationFromFile("control_table_contents_camera.xml"); +    initLocalizationFromFile("control_table_contents_editing.xml"); +    initLocalizationFromFile("control_table_contents_media.xml"); +} + +void LLUrlEntryKeybinding::initLocalizationFromFile(const std::string& filename) +{ +    LLXMLNodePtr xmlNode; +    LLScrollListCtrl::Contents contents; +    if (!LLUICtrlFactory::getLayeredXMLNode(filename, xmlNode)) +    { +        LL_WARNS() << "Failed to load " << filename << LL_ENDL; +        return; +    } +    LLXUIParser parser; +    parser.readXUI(xmlNode, contents, filename); + +    if (!contents.validateBlock()) +    { +        LL_WARNS() << "Failed to validate " << filename << LL_ENDL; +        return; +    } + +    for (LLInitParam::ParamIterator<LLScrollListItem::Params>::const_iterator row_it = contents.rows.begin(); +         row_it != contents.rows.end(); +         ++row_it) +    { +        std::string control = row_it->value.getValue().asString(); +        if (!control.empty() && control != "menu_separator") +        { +            mLocalizations[control] = +                LLLocalizationData( +                                   row_it->columns.begin()->value.getValue().asString(), +                                   row_it->columns.begin()->tool_tip.getValue() +                ); +        } +    } +} diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 63a1506731..5d0f5479f6 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -550,4 +550,37 @@ public:  	std::string mHostPath;  }; +class LLKeyBindingToStringHandler; + +/// +/// LLUrlEntryKeybinding A way to access keybindings and show currently used one in text. +/// secondlife:///app/keybinding/control_name +class LLUrlEntryKeybinding: public LLUrlEntryBase +{ +public: +    LLUrlEntryKeybinding(); +    /*virtual*/ std::string getLabel(const std::string& url, const LLUrlLabelCallback& cb); +    /*virtual*/ std::string getTooltip(const std::string& url) const; +    void setHandler(LLKeyBindingToStringHandler* handler) {pHandler = handler;} +private: +    std::string getControlName(const std::string& url) const; +    std::string getMode(const std::string& url) const; +    void initLocalization(); +    void initLocalizationFromFile(const std::string& filename); + +    struct LLLocalizationData +    { +        LLLocalizationData() {} +        LLLocalizationData(const std::string& localization, const std::string& tooltip) +            : mLocalization(localization) +            , mTooltip(tooltip) +        {} +        std::string mLocalization; +        std::string mTooltip; +    }; + +    std::map<std::string, LLLocalizationData> mLocalizations; +    LLKeyBindingToStringHandler* pHandler; +}; +  #endif diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 23f3dca3fb..3bd7321777 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -73,6 +73,8 @@ LLUrlRegistry::LLUrlRegistry()  	registerUrl(new LLUrlEntryPlace());  	registerUrl(new LLUrlEntryInventory());      registerUrl(new LLUrlEntryExperienceProfile()); +    mUrlEntryKeybinding = new LLUrlEntryKeybinding(); +    registerUrl(mUrlEntryKeybinding);  	//LLUrlEntrySL and LLUrlEntrySLLabel have more common pattern,   	//so it should be registered in the end of list  	registerUrl(new LLUrlEntrySL()); @@ -307,3 +309,9 @@ bool LLUrlRegistry::isUrl(const LLWString &text)  	}  	return false;  } + +void LLUrlRegistry::setKeybindingHandler(LLKeyBindingToStringHandler* handler) +{ +    LLUrlEntryKeybinding *entry = (LLUrlEntryKeybinding*)mUrlEntryKeybinding; +    entry->setHandler(handler); +} diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index efafe543ab..186447c0be 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -36,6 +36,8 @@  #include <string>  #include <vector> +class LLKeyBindingToStringHandler; +  /// This default callback for findUrl() simply ignores any label updates  void LLUrlRegistryNullCallback(const std::string &url,  							   const std::string &label, @@ -88,6 +90,9 @@ public:  	bool isUrl(const std::string &text);  	bool isUrl(const LLWString &text); +    // Set handler for url registry to be capable of parsing and populating keybindings +    void setKeybindingHandler(LLKeyBindingToStringHandler* handler); +  private:  	std::vector<LLUrlEntryBase *> mUrlEntry;  	LLUrlEntryBase*	mUrlEntryTrusted; @@ -96,6 +101,7 @@ private:  	LLUrlEntryBase* mUrlEntryHTTPLabel;  	LLUrlEntryBase* mUrlEntrySLLabel;  	LLUrlEntryBase* mUrlEntryNoLink; +    LLUrlEntryBase* mUrlEntryKeybinding;  };  #endif diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp index e65cc7563e..34720ff64e 100644 --- a/indra/llwindow/llkeyboard.cpp +++ b/indra/llwindow/llkeyboard.cpp @@ -367,6 +367,45 @@ std::string LLKeyboard::stringFromKey(KEY key, bool translate)  }  //static +std::string LLKeyboard::stringFromMouse(EMouseClickType click, bool translate) +{ +    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; +    } + +    if (translate && !res.empty()) +    { +        LLKeyStringTranslatorFunc* trans = gKeyboard->mStringTranslator; +        if (trans != NULL) +        { +            res = trans(res.c_str()); +        } +    } +    return res; +} + +//static  std::string LLKeyboard::stringFromAccelerator(MASK accel_mask)  {      std::string res; @@ -433,6 +472,18 @@ std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key )  	return res;  } +//static +std::string LLKeyboard::stringFromAccelerator(MASK accel_mask, EMouseClickType click) +{ +    std::string res; +    if (CLICK_NONE == click) +    { +        return res; +    } +    res.append(stringFromAccelerator(accel_mask)); +    res.append(stringFromMouse(click)); +    return res; +}  //static  BOOL LLKeyboard::maskFromString(const std::string& str, MASK *mask) diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h index fb1ae10f50..dad150e3c1 100644 --- a/indra/llwindow/llkeyboard.h +++ b/indra/llwindow/llkeyboard.h @@ -96,8 +96,10 @@ public:  	static BOOL		maskFromString(const std::string& str, MASK *mask);		// False on failure  	static BOOL		keyFromString(const std::string& str, KEY *key);			// False on failure  	static std::string stringFromKey(KEY key, bool translate = true); +    static std::string stringFromMouse(EMouseClickType click, bool translate = true);  	static std::string stringFromAccelerator( MASK accel_mask ); // separated for convinience, returns with "+": "Shift+" or "Shift+Alt+"...  	static std::string stringFromAccelerator( MASK accel_mask, KEY key ); +    static std::string stringFromAccelerator(MASK accel_mask, EMouseClickType click);  	void setCallbacks(LLWindowCallbacks *cbs) { mCallbacks = cbs; }  	F32				getKeyElapsedTime( KEY key );  // Returns time in seconds since key was pressed. @@ -130,6 +132,13 @@ protected:  	static std::map<std::string,KEY> sNamesToKeys;  }; +// Interface to get key from assigned command +class LLKeyBindingToStringHandler +{ +public: +    virtual std::string getKeyBindingAsString(const std::string& mode, const std::string& control) const = 0; +}; +  extern LLKeyboard *gKeyboard;  #endif diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 8235e4466c..3d81d4d7ea 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -195,6 +195,7 @@  #include "llhudeffecttrail.h"  #include "llvectorperfoptions.h"  #include "llslurl.h" +#include "llurlregistry.h"  #include "llwatchdog.h"  // Included so that constants/settings might be initialized @@ -4447,6 +4448,7 @@ void LLAppViewer::loadKeyBindings()  			LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL;  		}  	} +    LLUrlRegistry::instance().setKeybindingHandler(&gViewerInput);  }  void LLAppViewer::purgeCache() diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 9ea49e935f..e59c2ee2cd 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -251,11 +251,49 @@ void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator)  		}  	}  } -// static -std::string LLFloaterPreference::sSkin = ""; + +// handle secondlife:///app/worldmap/{NAME}/{COORDS} URLs +// Also see LLUrlEntryKeybinding, the value of this command type +// is ability to show up to date value in chat +class LLKeybindingHandler: public LLCommandHandler +{ +public: +    // requires trusted browser to trigger +    LLKeybindingHandler(): LLCommandHandler("keybinding", UNTRUSTED_CLICK_ONLY) +    { +    } + +    bool handle(const LLSD& params, const LLSD& query_map, +                LLMediaCtrl* web) +    { +        if (params.size() < 1) return false; + +        LLFloaterPreference* prefsfloater = dynamic_cast<LLFloaterPreference*> +            (LLFloaterReg::showInstance("preferences")); + +        if (prefsfloater) +        { +            // find 'controls' panel and bring it the front +            LLTabContainer* tabcontainer = prefsfloater->getChild<LLTabContainer>("pref core"); +            LLPanel* panel = prefsfloater->getChild<LLPanel>("controls"); +            if (tabcontainer && panel) +            { +                tabcontainer->selectTabPanel(panel); +            } +        } + +        return true; +    } +}; +LLKeybindingHandler gKeybindHandler; + +  //////////////////////////////////////////////  // LLFloaterPreference +// static +std::string LLFloaterPreference::sSkin = ""; +  LLFloaterPreference::LLFloaterPreference(const LLSD& key)  	: LLFloater(key),  	mGotPersonalInfo(false), diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 60f8aca94c..4a0ee8fd0c 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -74,40 +74,6 @@ std::string string_from_mask(MASK mask)      return res;  } -std::string string_from_mouse(EMouseClickType click, bool translate) -{ -    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; -    } - -    if (translate && !res.empty()) -    { -        res = LLTrans::getString(res); -    } -    return res; -} -  // LLKeyConflictHandler  S32 LLKeyConflictHandler::sTemporaryFileUseCount = 0; @@ -270,7 +236,7 @@ std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata)          result = LLKeyboard::stringFromAccelerator(keydata.mMask);      } -    result += string_from_mouse(keydata.mMouse, true); +    result += LLKeyboard::stringFromMouse(keydata.mMouse);      return result;  } @@ -545,7 +511,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, false), true); +                        binding.mouse.set(LLKeyboard::stringFromMouse(data.mMouse, false), true);                      }                      binding.command = iter->first;                      mode.bindings.add(binding); diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 226e0a9a56..3f8e6f57f6 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -991,34 +991,50 @@ LLViewerInput::LLViewerInput()  	}  } +LLViewerInput::~LLViewerInput() +{ + +} +  // static -BOOL LLViewerInput::modeFromString(const std::string& string, S32 *mode) +bool LLViewerInput::modeFromString(const std::string& string, S32 *mode)  { -	if (string == "FIRST_PERSON") +    if (string.empty()) +    { +        return false; +    } + +    std::string cmp_string = string; +    LLStringUtil::toLower(cmp_string); +	if (cmp_string == "first_person")  	{  		*mode = MODE_FIRST_PERSON; -		return TRUE; +		return true;  	} -	else if (string == "THIRD_PERSON") +	else if (cmp_string == "third_person")  	{  		*mode = MODE_THIRD_PERSON; -		return TRUE; +		return true;  	} -	else if (string == "EDIT_AVATAR") +	else if (cmp_string == "edit_avatar")  	{  		*mode = MODE_EDIT_AVATAR; -		return TRUE; +		return true;  	} -	else if (string == "SITTING") +	else if (cmp_string == "sitting")  	{  		*mode = MODE_SITTING; -		return TRUE; -	} -	else -	{ -		*mode = MODE_THIRD_PERSON; -		return FALSE; +		return true;  	} + +    S32 val = atoi(string.c_str()); +    if (val >= 0 || val < MODE_COUNT) +    { +        *mode = val; +        return true; +    } + +    return false;  }  // static @@ -1222,6 +1238,7 @@ BOOL LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, cons      bind.mKey = key;      bind.mMask = mask;      bind.mFunction = function; +    bind.mFunctionName = function_name;      if (result->mIsGlobal)      { @@ -1303,6 +1320,7 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const      bind.mMouse = mouse;      bind.mMask = mask;      bind.mFunction = function; +    bind.mFunctionName = function_name;      if (result->mIsGlobal)      { @@ -1801,3 +1819,49 @@ bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask      }      return false;  } + +std::string LLViewerInput::getKeyBindingAsString(const std::string& mode, const std::string& control) const +{ +    S32 keyboard_mode; +    if (!modeFromString(mode, &keyboard_mode)) +    { +        keyboard_mode = getMode(); +    } + +    std::string res; +    bool needs_separator = false; + +    // keybindings are sorted from having most mask to no mask (from restrictive to less restrictive), +    // but it's visually better to present this data in reverse +    std::vector<LLKeyboardBinding>::const_reverse_iterator iter_key = mKeyBindings[keyboard_mode].rbegin(); +    while (iter_key != mKeyBindings[keyboard_mode].rend()) +    { +        if (iter_key->mFunctionName == control) +        { +            if (needs_separator) +            { +                res.append(" | "); +            } +            res.append(LLKeyboard::stringFromAccelerator(iter_key->mMask, iter_key->mKey)); +            needs_separator = true; +        } +        iter_key++; +    } + +    std::vector<LLMouseBinding>::const_reverse_iterator iter_mouse = mMouseBindings[keyboard_mode].rbegin(); +    while (iter_mouse != mMouseBindings[keyboard_mode].rend()) +    { +        if (iter_mouse->mFunctionName == control) +        { +            if (needs_separator) +            { +                res.append(" | "); +            } +            res.append(LLKeyboard::stringFromAccelerator(iter_mouse->mMask, iter_mouse->mMouse)); +            needs_separator = true; +        } +        iter_mouse++; +    } + +    return res; +} diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h index 52e95e2168..41e289ac1d 100644 --- a/indra/newview/llviewerinput.h +++ b/indra/newview/llviewerinput.h @@ -28,12 +28,13 @@  #define LL_LLVIEWERINPUT_H  #include "llkeyboard.h" // For EKeystate -#include "llinitparam.h"  const S32 MAX_KEY_BINDINGS = 128; // was 60  const S32 keybindings_xml_version = 1;  const std::string script_mouse_handler_name = "script_trigger_lbutton"; +class LLWindow; +  class LLNamedFunction  {  public: @@ -51,6 +52,7 @@ public:      MASK			mMask;      LLKeyFunc		mFunction; +    std::string     mFunctionName;  };  class LLMouseBinding @@ -60,6 +62,7 @@ public:      MASK			mMask;      LLKeyFunc		mFunction; +    std::string     mFunctionName;  }; @@ -72,11 +75,7 @@ typedef enum e_keyboard_mode  	MODE_COUNT  } EKeyboardMode; -class LLWindow; - -void bind_keyboard_functions(); - -class LLViewerInput +class LLViewerInput : public LLKeyBindingToStringHandler  {  public:  	struct KeyBinding : public LLInitParam::Block<KeyBinding> @@ -107,6 +106,7 @@ public:  	};  	LLViewerInput(); +    virtual ~LLViewerInput();  	BOOL			handleKey(KEY key, MASK mask, BOOL repeated);  	BOOL			handleKeyUp(KEY key, MASK mask); @@ -121,7 +121,7 @@ public:  	S32				loadBindingsXML(const std::string& filename);										// returns number bound, 0 on error  	EKeyboardMode	getMode() const; -	static BOOL		modeFromString(const std::string& string, S32 *mode);			// False on failure +	static bool		modeFromString(const std::string& string, S32 *mode);			// False on failure  	static BOOL		mouseFromString(const std::string& string, EMouseClickType *mode);// False on failure      bool            scanKey(KEY key, @@ -136,6 +136,9 @@ public:      bool            isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) const;      bool            isLMouseHandlingDefault(const S32 mode) const { return mLMouseDefaultHandling[mode]; } +    // inherited from LLKeyBindingToStringHandler +    virtual std::string getKeyBindingAsString(const std::string& mode, const std::string& control) const override; +  private:      bool            scanKey(const std::vector<LLKeyboardBinding> &binding,                              S32 binding_count,  | 
